我想编写一些代码,本质上类似于使用stax和dom读取一个大的xml文件,但是使用xmleventreader而不是xmlstreamreader(在继续创建dom之前,我需要能够检查一些元素的值)。有没有人能举一个最简单的例子来说明这一点?到目前为止,我尝试的所有方法都会导致错误或空指针异常。谢谢!爱洛
dauxcl2d1#
我也遇到了同样的问题,就我所能调试的而言,一切都表明jdk中有一个bug(至少在build1.8.0\u 162-b12上),更具体地说是在类中 com.sun.org.apache.xalan.internal.xsltc.trax.StAXEvent2SAX .npe实际上只是另一个bug的结果,这个bug与在这个类中如何处理读取器有关 bridge() 方法。如果读者不在 START_DOCUMENT 状态下,下一个事件只会被窥视,而不会随着 nextEvent() 就在第一次。这导致了第一个问题 START_ELEMENT 要处理两次的事件。如果使用 StreamResult 而不是 DOMResult . 在那里,npe不会发生,但是结果流中生成的xml将包含第一个元素的标记开头两次。我现在正试着用一个 XmlEventWriter 接收 DOMResult . 所以,基本上模拟 Transformer 将每个read事件直接推送到该writer。如果我成功了,我也会在这里发布我的解决方案。ps:我想在jdk上报告这个问题,或者最终推动一个潜在的解决方案。如果有人能告诉我应该怎么做,我将非常感激。
com.sun.org.apache.xalan.internal.xsltc.trax.StAXEvent2SAX
bridge()
START_DOCUMENT
nextEvent()
START_ELEMENT
StreamResult
DOMResult
XmlEventWriter
Transformer
所以,我用上面提到的方法解决了这个问题。基于使用stax和dom而不是使用 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编写器将遇到问题。如果您打算操纵这个dom,然后将它发送给另一个活动的 XMLEventWriter (正如我试图做的)使用 Transformer 再次,它将失败。这是因为 Transformer 将向已启动的写入程序发送开始文档事件。我也试过同样的方法。e。将节点 Package 到 DOMSource ,发送给另一个 XmlEventReader 把这些事情告诉我现有的 XmlEventWriter ,但这也不起作用 XmlEventReader 显然只支持 StreamSource s(见此处)。总之,如果您只需要dom对象,这可能会很好地工作,但是如果您尝试将事件传递给编写器的xml片段进行转换(如我所做的),则可能会遇到问题。
Document
XMLEventWriter
DOMSource
XmlEventReader
StreamSource
smdncfj32#
看看:http://www.vogella.com/articles/javaxml/article.html#javastax_read它给出了一个如何使用xml流和xmleventreader的很好的小示例
2条答案
按热度按时间dauxcl2d1#
我也遇到了同样的问题,就我所能调试的而言,一切都表明jdk中有一个bug(至少在build1.8.0\u 162-b12上),更具体地说是在类中
com.sun.org.apache.xalan.internal.xsltc.trax.StAXEvent2SAX
.npe实际上只是另一个bug的结果,这个bug与在这个类中如何处理读取器有关
bridge()
方法。如果读者不在START_DOCUMENT
状态下,下一个事件只会被窥视,而不会随着nextEvent()
就在第一次。这导致了第一个问题START_ELEMENT
要处理两次的事件。如果使用StreamResult
而不是DOMResult
. 在那里,npe不会发生,但是结果流中生成的xml将包含第一个元素的标记开头两次。我现在正试着用一个
XmlEventWriter
接收DOMResult
. 所以,基本上模拟Transformer
将每个read事件直接推送到该writer。如果我成功了,我也会在这里发布我的解决方案。ps:我想在jdk上报告这个问题,或者最终推动一个潜在的解决方案。如果有人能告诉我应该怎么做,我将非常感激。
更新:
所以,我用上面提到的方法解决了这个问题。基于使用stax和dom而不是使用
Transformer
,可以使用以下方法:但是,这种方法有一些局限性!在代码中可见,我们需要创建一个
Document
对象,否则xml编写器将遇到问题。如果您打算操纵这个dom,然后将它发送给另一个活动的XMLEventWriter
(正如我试图做的)使用Transformer
再次,它将失败。这是因为Transformer
将向已启动的写入程序发送开始文档事件。我也试过同样的方法。e。将节点 Package 到DOMSource
,发送给另一个XmlEventReader
把这些事情告诉我现有的XmlEventWriter
,但这也不起作用XmlEventReader
显然只支持StreamSource
s(见此处)。总之,如果您只需要dom对象,这可能会很好地工作,但是如果您尝试将事件传递给编写器的xml片段进行转换(如我所做的),则可能会遇到问题。
smdncfj32#
看看:http://www.vogella.com/articles/javaxml/article.html#javastax_read
它给出了一个如何使用xml流和xmleventreader的很好的小示例