我想写一些基本类似于Reading a big XML file using stax and dom的代码 但是使用XMLEventReader而不是XMLStreamReader(我需要能够在继续创建DOM之前检查一些元素的值)。
有没有人有这个看起来如何的最小例子?到目前为止我尝试的所有内容都会给我错误或空指针异常。
谢谢! 阿洛
答案 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片段将事件传递给一个编写器(就像我一样),你可能会遇到问题。