Java 从XML中读取有限数量的元素

Java 从XML中读取有限数量的元素,java,xml,streaming,Java,Xml,Streaming,我有一个很大的XML文件(很多MB),我不能作为一个整体下载 <doc> <element>...</element> <element>...</element> ... <element>...</element> </doc> ... ... ... ... 我需要从web上读取这个XML(或者更好的是流式处理),然后从它的主体中取出第一个N元素s,用XSLT模板处

我有一个很大的XML文件(很多MB),我不能作为一个整体下载

<doc>
   <element>...</element>
   <element>...</element>
   ...
   <element>...</element>
</doc>

...
...
...
...
我需要从web上读取这个XML(或者更好的是流式处理),然后从它的主体中取出第一个N
元素
s,用XSLT模板处理它们

对于这样的任务,您推荐什么库/技术?我在用Java写东西

最亲切的问候,

Q.

您可以使用STAX读取元素并将其子集重定向到不同的流:

final XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
final XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
final XMLEventReader xmlReader = xmlInputFactory.createXMLEventReader(yourInputStream);
final XMLEventWriter xmlWriter = xmlOutputFactory .createXMLEventWriter(yourOutputStream); //The place where the resulting partial XML will go

while (xmlReader.hasNext()) {
    XMLEvent event = xmlReader.nextEvent();

    if (event ... some validation) {
        xmlWriter.add(event); //Forward it to xmlWriter
    }

    if (we have read enough elements) {
        break;
    }
}
xmlReader.close();
xmlWriter.flush();
xmlWriter.close();
添加:

要编写结束标记,您应该创建一个结束标记事件,并在需要时将其传递给相同的
XMLEventWriter
对象。为此,您需要一个
XMLEventFactory
的实例。下面是编写结束标记的示例:

XMLEventFactory eventFactory = XMLEventFactory.newInstance();
XMLEvent closeTagEvent = eventFactory.createEndElement("prefix", "http://namespace.com", "elementName");
//This will create a closing tag event for a previously opened <prefix:elementName xmlns:prefix="http://namespace.com">

xmlWriter.add(closeTagEvent);

xmlWriter.flush();
xmlWriter.close();
XMLEventFactory eventFactory=XMLEventFactory.newInstance();
XMLEvent closeTagEvent=eventFactory.createEndElement(“前缀”)http://namespace.com“,”元素名称“);
//这将为以前打开的文件创建结束标记事件
add(closeTagEvent);
xmlWriter.flush();
xmlWriter.close();

另外,对于我建议使用
XMLStreamWriter
的一条评论造成的混乱,我深表歉意。我从未使用过
XMLEventWriter
,因此直到现在才知道如何正确使用它。

在阅读XML元素时,使用SAX而不是DOM来解析XML元素。当您读得足够多时,停止从InputStream读取内容,并将其提供给XSLT处理器。@Alex我同意您使用SAX,但XSLT处理器不会接受xml文件的片段,它需要有效的文件/树/结构。当然,除非您在将结束文档标记提供给XSLT之前手动添加它processor@Kennet我不认为有一种方法可以添加关闭文档标记,如果它从未从流中读取。因此,在任何情况下,您都必须手动添加它。当您覆盖startElement时,请按顺序保留对每个开始标记的引用。这样,当您已经读取了足够的数据时,您就已经知道需要关闭哪些标记以及关闭顺序。即使它不包含所有数据,XML元素也是正确的,因此可以提供给XSLT处理器。但是下面@Max的答案是可以的,STAX是一个解决方案。部分xml注释意味着您的代码片段将只下载部分在线xml并关闭所有必要的xml标记,对吗?然后我只需阅读部分XML并做任何我想做的事情?不,您仍然需要以某种方式手动将结束标记写入
yourOutputStream
。STAX并不能确保所有标记都被关闭,它只是简化了从/到流的XML读/写操作,而不必考虑XML语法。你有两个选择:1。将结束标记作为文本直接写入
yourOutputStream
。2.使用XMLStreamWriter包装输出流,并在其中写入结束标记。是的,每次调用
xmlReader.nextEvent()
时,它都会开始从
inputStream
读取数据,直到读取整个
事件。例如,当它获得
-时,它将停止从流中读取,因为这些数据足以触发begin\u元素事件。基本上,这就是您所需要的。当尝试编写最后一个结束标记时,我发现
没有要编写的元素:java.lang.ArrayIndexOutOfBoundsException:-1
-知道为什么吗?@Queequeg请参阅我的答案的补充部分,忽略我对XMLStreamWriter的评论。