2011-04-20 64 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