我想编写一些基本上类似于使用 stax 和 dom 读取大型 XML 文件 但使用 XMLEventReader 而不是 XMLStreamReader 的代码(我需要能够在继续创建 DOM 之前检查某些元素的值)。
有没有人有一个最小的例子来说明这看起来如何?到目前为止,我尝试过的所有事情都会给我错误或空指针异常。
谢谢!爱洛
我想编写一些基本上类似于使用 stax 和 dom 读取大型 XML 文件 但使用 XMLEventReader 而不是 XMLStreamReader 的代码(我需要能够在继续创建 DOM 之前检查某些元素的值)。
有没有人有一个最小的例子来说明这看起来如何?到目前为止,我尝试过的所有事情都会给我错误或空指针异常。
谢谢!爱洛
看看:http ://www.vogella.com/articles/JavaXML/article.html#javastax_read
它提供了一个很好的小例子,如何使用 xml-streaming 和 XMLEventReader
我遇到了同样的问题,据我调试,一切都表明 JDK 中存在错误(至少在构建 1.8.0_162-b12 上),更具体地说是在 class 中com.sun.org.apache.xalan.internal.xsltc.trax.StAXEvent2SAX
。
NPE实际上只是另一个错误的结果,这与阅读器在此类bridge()
方法中的处理方式有关。在那里,如果读者不在START_DOCUMENT
状态,下一个事件只会在第一次被偷看但不会被推进nextEvent()
。这导致第一个START_ELEMENT
事件被处理两次。StreamResult
如果您使用 a而不是 ,则可以很好地观察到这一点DOMResult
。那里不会发生 NPE,但结果流中生成的 XML 将包含两次第一个元素的标记的开头。
我现在正在尝试使用XmlEventWriter
接收DOMResult
. 因此,基本上模拟了Transformer
会做什么,将每个读取事件直接推送给该作者。如果我成功了,我也会在这里发布我的解决方案。
PS:我想在 JDK 上报告这个问题,或者最终推一个潜在的解决方案。如果有人能告诉我这应该如何完成,我将非常感激。
所以,我设法用上面提到的方法解决了这个问题。根据Reading a big XML file using stax and domTransformer
中建议的代码,您可以使用以下方法,而不是使用:
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 编写器会遇到问题。如果您打算操作此 DOM 并随后XMLEventWriter
使用再次将其发送到另一个活动(正如我试图做的那样)Transformer
,它将失败。这是因为Transformer
将向已经启动的编写器发送一个 START_DOCUMENT 事件。我反过来尝试了相同的方法,即将节点包装成 a DOMSource
,将其发送到另一个XmlEventReader
并将事件通过管道传输到我现有的XmlEventWriter
,但这也不起作用,因为XmlEventReader
显然只支持StreamSource
s (请参见此处)。
总而言之,如果您只需要 DOM 对象,这可能会很好,但如果您尝试将 XML 片段转换为将事件管道传输到写入器(就像我一样),您可能会遇到问题。