我想迭代一个基本上是相同结构化XML元素列表的XML文档。元素将被序列化为Java对象。
<root>
<element attribute="value" />
<element attribute="value" />
<element attribute="value" />
...
</root>
根元素中有很多元素。我宁愿不将它们全部加载到内存中。我意识到我可以使用SAX处理程序,但使用SAX处理程序将所有内容反序列化为Java对象似乎相当迟钝。我发现JDOM非常容易使用,但据我所知,JDOM总是会解析整个树。有没有办法可以使用JDOM一次解析一个子元素?
使用JDOM的另一个原因是它使得编写序列化/反序列化代码对于相应的Java对象来说很容易,如果不是完全在内存中则没有意义。但是,我不想同时将所有Java对象加载到内存中。相反,我想迭代它们一次。
更新:以下是dom4j中如何执行此操作的示例:http://docs.codehaus.org/display/GROOVY/Reading+XML+with+Groovy+and+DOM4J。无论如何要在jdom做到这一点?
答案 0 :(得分:3)
为什么不使用StAX(javax.xml.stream。*,Java SE 6中包含一个实现)来流式传输XML,并将各个部分转换为对象?
import java.io.FileReader;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Element.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
XMLInputFactory xif = XMLInputFactory.newFactory();
XMLStreamReader xsr = xif.createXMLStreamReader(new FileReader("input.xml"));
xsr.nextTag();
xsr.nextTag();
while(xsr.hasNext()) {
Element element = (Element) unmarshaller.unmarshal(xsr);
System.out.println(element.getAttribute());
if(xsr.nextTag() != XMLStreamReader.START_ELEMENT) {
break;
}
}
}
}
在上面的示例中,使用JAXB将一个单独的“元素”解组成POJO(Java SE 6中包含一个实现),但您可以按照自己的意愿处理该片段。 JAXB模型详情如下:
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Element {
private String attribute;
@XmlAttribute
public String getAttribute() {
return attribute;
}
public void setAttribute(String attribute) {
this.attribute = attribute;
}
}
注意:强>
StAX和JAXB也与Java SE 5兼容,您只需要单独下载这些实现。
答案 1 :(得分:2)
您应该使用VTD-XML,它主要用于流处理。我用它来阅读广告商提供的产品。
最大的优点是它只需要一个XPath,它可以以极快的速度迭代XML并且内存占用非常小(在迭代XML时只保留几个指针)。
我知道该网站表示它们的执行速度比解析DOM快x5-12倍,但根据我对您的任务类型的体验(特别是如果大小在100的MB中),您可以轻松获得x20速度。
以下是如何使用VTD-XML读取XML的简单示例:
VTDGen vg = new VTDGen();
AutoPilot ap = new AutoPilot();
int i;
ap.selectXPath("/root/element");
if (vg.parseFile(FILE_LOCATION,true)){
VTDNav vn = vg.getNav();
ap.bind(vn); // apply XPath to the VTDNav instance
// AutoPilot moves the cursor for you
while((i=ap.evalXPath())!=-1){
System.out.println("the attribute index val is "+
i +" the attribute string ==>"+vn.toString(vn.getAttrVal("attribute")));
}
}
答案 2 :(得分:0)
简答:不。 Jdom是关于解析xml并将其转换为数据结构以执行操作。这意味着始终反序列化整个xml。
答案 3 :(得分:0)
一种可以减少内存需求的简单方法是使用XPath和JDOM来查询XML的子集,并只获取满足查询的那些位。
否则你可以查看这个interesting hint from Elliotte Rusty Harold,它表示你想要的流媒体API就在那里,只是没有做广告:
JDOM确实有一个流API。它只是隐藏而不是广泛的 广告或解释。在XOM中,我更多地采用了这种方法 明确并记录下来。如果你想要一个流树模型, 你可能更适合使用XOM,但如果你必须坚持使用JDOM 然后阅读XOM示例可能会给你足够的线索 如何在流模式下使用JDOM。