使用XMLEventReader而不是XMLStreamReader的StAX和DOM

时间:2013-06-06 12:55:01

标签: java dom stax

我想写一些基本类似于Reading a big XML file using stax and dom的代码 但是使用XMLEventReader而不是XMLStreamReader(我需要能够在继续创建DOM之前检查一些元素的值)。

有没有人有这个看起来如何的最小例子?到目前为止我尝试的所有内容都会给我错误或空指针异常。

谢谢! 阿洛

2 个答案:

答案 0 :(得分:2)

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

它提供了一个很好的小例子,如何使用xml-streaming和XMLEventReader

答案 1 :(得分:0)

我遇到了同样的问题,据我所知,一切都表明JDK中存在一个错误(至少在构建版本1.8.0_162-b12上),更具体地说是在类{{ {1}}。

NPE实际上只是另一个错误的结果,这与在本课程com.sun.org.apache.xalan.internal.xsltc.trax.StAXEvent2SAX方法中处理读者的方式有关。如果读者不在bridge()状态,那么下一个事件只是在第一次被START_DOCUMENT偷看但没有进展。这导致第一个nextEvent()事件被处理两次。如果您使用START_ELEMENT代替StreamResult,则可以很好地观察到这种情况。 NPE不会发生,但结果流中生成的XML将包含第一个元素的标记的开头两次。

我现在尝试使用收到DOMResult的{​​{1}}解决此问题。因此,基本上模拟XmlEventWriter将要执行的操作,将每个读取事件直接推送到该编写器。如果我成功了,我也会在这里发布我的解决方案。

PS:我想在JDK上报告这个问题,或者最终推出一个潜在的解决方案。如果有人能告诉我这是怎么做的,我会非常感激。

<强>更新

所以,我设法用上面提到的方法解决了这个问题。根据{{​​3}}中建议的代码,您可以使用以下方法,而不是使用DOMResult

Transformer

但是,这种方法有一些限制!在代码中可见,我们需要创建一个包装节点的Transformer对象,否则XML编写器会遇到问题。如果您打算操纵此DOM并在之后再次使用 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(正如我尝试的那样),则会失败。这是因为XMLEventWriter会向已经启动的作者发送START_DOCUMENT事件。我反过来试过同样的方法,我。即将节点包装到Transformer,将其发送给另一个Transformer并将事件传递给我现有的DOMSource,但这也不起作用XmlEventReader显然支持仅XmlEventWriter s(参见Reading a big XML file using stax and dom)。

总结一下,如果你只需要DOM对象,这可能会很好,但是如果你试图转换XML片段将事件传递给一个编写器(就像我一样),你可能会遇到问题。