繁体   English   中英

使用XMLEventReader而不是XMLStreamReader的StAX和DOM

[英]StAX and DOM using XMLEventReader rather than XMLStreamReader

我想编写一些类似于使用stax和dom读取大XML文件的代码但使用XMLEventReader而不是XMLStreamReader(我需要能够检查某些元素的值,然后再创建DOM)。

有没有人有一个最小的例子,这看起来如何? 到目前为止,我尝试过的所有操作都会给我带来错误或Null Pointer Exception。

谢谢! 阿罗

看看: http : //www.vogella.com/articles/JavaXML/article.html#javastax_read

它给出了一个很好的小示例,说明如何使用xml流和XMLEventReader

我遇到了同样的问题,据我所知,一切都表明JDK中存在一个错误(至少在内部版本1.8.0_162-b12上),更具体地说是在com.sun.org.apache.xalan.internal.xsltc.trax.StAXEvent2SAX类中com.sun.org.apache.xalan.internal.xsltc.trax.StAXEvent2SAX

NPE实际上只是另一个错误的结果,该错误与在此类的bridge()方法中如何处理阅读器有关。 如果读者不在START_DOCUMENT状态,则仅在下一次事件被START_DOCUMENT ,而第一次没有使用nextEvent()进行下一个事件。 这导致第一个START_ELEMENT事件被处理两次。 如果使用StreamResult而不是DOMResult则可以很好地观察到这DOMResult 在那里不会发生NPE,但是在结果流中生成的XML将两次包含第一个元素的标签的开头。

我现在正在尝试使用接收DOMResultXmlEventWriter来解决此DOMResult 因此,基本上模拟了Transformer功能,将每个读取事件直接推给该编写器。 如果我成功了,我也将在这里发布我的解决方案。

PS:我想在JDK上报告此问题,或者最终甚至提出潜在的解决方案。 如果有人能告诉我应该怎么做,我将非常感谢。

更新:

因此,我设法通过上述方法解决了这个问题。 根据使用stax和dom读取大型XML文件中建议的代码,而不是使用Transformer ,可以使用以下方法:

  private Node readToNode(final XMLEventReader reader) throws XMLStreamException, ParserConfigurationException {
    XMLEvent event = reader.peek();
    if (!event.isStartElement()) {
      throw new IllegalArgumentException("reader must be on START_ELEMENT event");
    }
    final Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
    final XMLEventWriter writer = XMLOutputFactory.newInstance().createXMLEventWriter(new DOMResult(document));
    int depth = 0;
    do {
      event = reader.nextEvent();
      writer.add(event);
      if (event.isStartElement()) {
        depth++;
      } else if (event.isEndElement()) {
        depth--;
      }
    } while (reader.hasNext() && !(event.isEndElement() && depth <= 0));
    return document.getDocumentElement();
  }

但是,这种方法有一些局限性 在代码中可见,我们需要创建一个包装该节点的Document对象,否则XML writer将遇到问题。 如果您打算操纵此DOM,然后再使用Transformer将其发送到另一个活动的XMLEventWriter (如我所尝试的那样),它将失败。 这是因为Transformer会将START_DOCUMENT事件发送给已经开始的编写器。 我想同样的方法倒过来,即包裹节点为DOMSource ,其发送给其他XmlEventReader和管道的事件,以我现有的XmlEventWriter ,但也不能按XmlEventReader显然只支持StreamSource S(参见这里 ) 。

总而言之,如果只需要DOM对象,这可能会很好地工作,但是如果您试图将传递事件的XML片段转换为writer(就像我所做的那样),则可能会遇到问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM