繁体   English   中英

使用stax和dom读取大的XML文件

[英]Reading a big XML file using stax and dom

我需要读取几个大的(200Mb-500Mb)XML文件,所以我想使用StaX。 我的系统有两个模块-一个用于读取文件(使用StaX);另一个用于读取文件。 另一个模块(“解析器”模块)假定获取该XML的单个条目并使用DOM对其进行解析。 我的XML文件没有特定的结构-因此我无法使用JaxB。 如何向“解析器”模块传递要解析的特定条目? 例如:

<Items>
   <Item>
        <name> .... </name>
        <price> ... </price>
   </Item>
   <Item>
        <name> .... </name>
        <price> ... </price>
   </Item>
</Items>

我想使用StaX来解析该文件-但每个“项目”条目都将传递到“解析器”模块。

编辑:
经过一番阅读之后-我想我需要一个使用流读取XML文件的库-但使用DOM解析每个条目。 有这样的事吗?

您可以使用StAX( javax.xml.stream )解析器,并将每个部分转换( javax.xml.transform )到DOM节点( org.w3c.dom ):

import java.io.*;
import javax.xml.stream.*;
import javax.xml.transform.*;
import javax.xml.transform.stax.StAXSource;
import javax.xml.transform.dom.DOMResult;
import org.w3c.dom.*

public class Demo {

    public static void main(String[] args) throws Exception  {
        XMLInputFactory xif = XMLInputFactory.newInstance();
        XMLStreamReader xsr = xif.createXMLStreamReader(new FileReader("input.xml"));
        xsr.nextTag(); // Advance to statements element

        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer t = tf.newTransformer();
        while(xsr.nextTag() == XMLStreamConstants.START_ELEMENT) {
            DOMResult result = new DOMResult();
            t.transform(new StAXSource(xsr), result);
            Node domNode = result.getNode();
        }
    }

}

另请参阅:

由于https://bugs.openjdk.java.net/browse/JDK-8016914,Blaise Doughan的答案在干净的Java 7和8中失败

java.lang.NullPointerException
at com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl.setXmlVersion(CoreDocumentImpl.java:860)
at com.sun.org.apache.xalan.internal.xsltc.trax.SAX2DOM.setDocumentInfo(SAX2DOM.java:144)

有趣的是:如果使用jaxb解组器,则不会获得NPE:

package com.common.config;

import java.io.*;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.*;

import org.w3c.dom.*;

public class Demo {


    public static void main(String[] args) throws Exception  {
        XMLInputFactory xif = XMLInputFactory.newInstance();
        XMLStreamReader xsr = xif.createXMLStreamReader(new FileReader("input.xml"));
        // Advance to root element
        xsr.nextTag(); // TODO: nextTag() can't skip DTD
        xsr.next(); // Advance to first item or EOD

        final JAXBContext jaxbContext = JAXBContext.newInstance();
        final Unmarshaller unm = jaxbContext.createUnmarshaller();
        while(true) {
            // previous unmarshal() already did advance to next element or whitespace
            if (xsr.getEventType() == XMLStreamReader.START_ELEMENT) {
                JAXBElement<Object> jel = unm.unmarshal(xsr, Object.class);
                Node domNode = (Node)jel.getValue();
                System.err.println(domNode.getNodeName());
            } else if (!xsr.hasNext()) {
                    break;
            } else {
                xsr.next();
            }
        }
    }

}

原因是: com.sun.xml.internal.bind.v2.runtime.unmarshaller.StAXConnector$1没有实现Locator2因此它没有getXMLVersion()

您可以尝试JLibs的XMLDog。

它使用SAX评估xml文档上的xpath(即,无需将整个xml加载到内存中)。 并在命中节点时返回dom节点。

因此,您可以在胖xml文档中评估xpath / Items / Item。 系统会在解析每个Item节点时通知您。 您可以处理当前的Item dom节点,然后继续。

因此,它适用于评估大型文档上的xpath

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM