我需要阅读几个大的(200Mb-500Mb)XML文件,所以我想使用StaX。 我的系统有两个模块 - 一个用于读取文件(使用StaX);另一个模块('parser'模块)假设获取该XML的单个条目并使用DOM解析它。 我的XML文件没有特定的结构 - 所以我不能使用JaxB。 如何将“解析器”模块传递给我想要解析的特定条目? 例如:
<Items>
<Item>
<name> .... </name>
<price> ... </price>
</Item>
<Item>
<name> .... </name>
<price> ... </price>
</Item>
</Items>
我想使用StaX来解析该文件 - 但每个'item'条目都将传递给'parser'模块。
修改
稍微阅读一下 - 我想我需要一个使用流读取XML文件的库 - 但是使用DOM解析每个条目。有这样的事吗?
答案 0 :(得分:18)
您可以使用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();
}
}
}
另见:
答案 1 :(得分:2)
Blaise Doughan's answer fails in clean java 7 and 8 due to https://bugs.openjdk.java.net/browse/JDK-8016914
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)
Funny thing: if you use jaxb unmarshaller, you don't get the 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"));
xsr.nextTag(); // Advance to root element
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();
}
}
}
}
The reason is: com.sun.xml.internal.bind.v2.runtime.unmarshaller.StAXConnector$1
does not implement Locator2
therefore it has no getXMLVersion()
.
答案 2 :(得分:0)
你可以从JLibs尝试XMLDog。
它使用SAX评估xml文档上的xpath(即不将整个xml加载到内存中)。 并在节点被击中时返回节点的dom节点。
因此您可以评估fat xml文档中的xpath / Items / Item。在解析每个Item节点时,您将收到通知。您可以处理当前的项目dom节点,然后继续。
因此它适用于评估大型文档上的xpath