在Java中读取XML元素列表

时间:2011-04-20 17:36:02

标签: java xml

我想迭代一个基本上是相同结构化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做到这一点?

4 个答案:

答案 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。