【问题标题】:JAXB Unmarshalling an subset of Unknown XML contentJAXB 解组未知 XML 内容的子集
【发布时间】:2013-05-23 16:22:20
【问题描述】:

我需要 unmarshall 未知 XML 内容的子集,使用该未编组的对象,我需要修改一些内容并将相同的 XML 内容(子集)与原始 XML 重新绑定。

输入 XML 示例:

<Message>
    <x>
    </x>
    <y>
    </y>
    <z>
    </z>
    <!-- Need to unmarshall this content to "Content" - java Object -->
    <Content>
        <Name>Robin</Name>
        <Role>SM</Role>
        <Status>Active</Status>
    </Content>
.....
</Message>

需要单独解组 &lt;Content&gt; 标记,保持其他 XML 部分相同。需要修改&lt;Content&gt;标签中的元素,并将修改后的XML部分与原文绑定如下:

预期输出 XML:

<Message>
    <x>
    </x>
    <y>
    </y>
    <z>
    </z>
    <!-- Need to unmarshall this content to "Content" - java Object -->
    <Content>
        <Name>Robin_123</Name>
        <Role>Senior Member</Role>
        <Status>1</Status>
    </Content>
.....
</Message>

我的问题:

  1. 此要求的可能解决方案是什么? DOM 解析除外 - 因为 XML 网络非常庞大)

  2. JAXB2.0 中是否有任何选项可以执行此操作?

请就此提出您的建议。

【问题讨论】:

    标签: java xml xml-parsing sax jaxb2


    【解决方案1】:

    考虑使用StAX API 将源文档缩小。

    对于给定的示例,此代码创建一个根元素为 Content 元素的 DOM 文档:

    class ContentFinder implements StreamFilter {
      private boolean capture = false;
    
      @Override public boolean accept(XMLStreamReader xml) {
        if (xml.isStartElement() && "Content".equals(xml.getLocalName())) {
          capture = true;
        } else if (xml.isEndElement() && "Content".equals(xml.getLocalName())) {
          capture = false;
          return true;
        }
        return capture;
      }
    }
    
    XMLInputFactory inFactory = XMLInputFactory.newFactory();
    XMLStreamReader reader = inFactory.createXMLStreamReader(inputStream);
    reader = inFactory.createFilteredReader(reader, new ContentFinder());
    Source src = new StAXSource(reader);
    DOMResult res = new DOMResult();
    TransformerFactory.newInstance().newTransformer().transform(src, res);
    Document doc = (Document) res.getNode();
    

    这可以是passed to JAXB 作为DOMSource

    在输出时重写 XML 时可以使用类似的技术。

    JAXB 似乎不直接接受 StreamSource,至少在 Oracle 1.7 实现中是这样。

    【讨论】:

    • 是否可以以流方式迭代多个 节点?我有一个巨大的 XML 文件,我想一个一个地提取节点,而不必将整个内容加载到内存中。
    • 我相信是的。我可能会使用 StAX 事件来创建某种访问者模式。要求是不同的足以保证它自己的问题。如果您愿意同时在内存中拥有所有未编组的对象,您可能仍然可以使用过滤器方法。
    • 谢谢,我创建了一个separate question。但是,我不能将所有对象都保存在内存中,因此我需要找出一种不同的方法。 Camel 的tokenizeXML 和我一模一样,所以我想我可以调查一下。
    【解决方案2】:

    您可以使用 @XmlAnyElement 在您的类上注释 Object 属性,默认情况下,未映射的内容将被捕获为 DOM 节点。如果您在@XmlAnyElement 上指定DomHandler,那么您可以控制格式。这是一个示例的链接,其中内容保存为String

    【讨论】:

      猜你喜欢
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      • 2014-08-21
      • 1970-01-01
      • 2013-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多