2011-04-20 60 views
4

我想遍历基本上是相同结构化XML元素列表的XML文档。这些元素将被序列化为Java对象。读取Java中的XML元素列表

<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

你可能应该看看[JSefa](http://jsefa.sourceforge.net/)它不是非常流行但简单易用。你应该下载它并看看这些例子。 – FrVaBe 2011-04-20 18:46:02

回答

0

减少内存需求的一种简单方法是使用XPath和JDOM来查询XML的子集并仅获取满足查询的那些位。

否则,你可以看看这个interesting hint from Elliotte Rusty Harold,则表明你想要的流API是存在的,只是不公布:

JDOM确实有流API。这只是一些隐藏的广告或广告 广告或解释。在XOM中,我使这种方法明确并且记录了它。如果流式树模型是你想要的,你可能会更适合使用XOM,但是如果你必须坚持使用JDOM ,那么阅读XOM示例可能会给你提供足够的关于如何在流模式下使用JDOM的线索。

+0

感谢您的链接。我看到了2001年提到的流媒体功能(http://www.jdom.org/pipermail/jdom-interest/2000-November/002876.html)。似乎有很多兴趣,但它似乎也没有去任何地方。我将调查XPath,但我不确定这是我想要的,因为我想要所有的结果,但我只需要一次在内存中的每个结果。 – schmmd 2011-04-20 18:40:33

0

简短回答:No. Jdom是关于解析XML并将其转换为数据结构来执行操作。这意味着总是反序列化整个xml。

+0

您还有什么建议?有没有办法与JDOM一起使用SAX处理程序来解析子树? – schmmd 2011-04-20 17:42:34

+0

我看不出JDOM非常适合您的需求。如果你仍然坚持使用它,我想你可能有一个SAX解析器在解析XML时创建过滤的JDOM文档。 – Buhb 2011-04-20 17:48:22

+0

让我澄清一下,子元素比上例更加复杂。 – schmmd 2011-04-20 17:53:59

2

您应该使用VTD-XML,它主要用于流处理。我用它来读取广告商的产品信息。

最大的好处是它只需要一个XPath,它可以以极快的速度迭代XML并且具​​有非常小的内存占用量(在遍历XML时只保留几个指针)。

我知道该网站说他们执行的速度比解析DOM快x5-12倍,但是根据我对您任务类型的体验(尤其是如果大小在100几MB的情况下),您可以轻松获得x20速度。

下面是如何使用VTD-XML来读取你的XML一个简单的例子:

为什么不使用的StAX(javax.xml.stream *,实现包含在Java SE 6)
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"))); 
    } 
} 
3

到在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

为什么选择投票? – 2011-04-20 21:14:29