2011-10-12 75 views
6

我有以下問題:我有非常大的XML文件(如300 +兆),我需要對其進行解析,以他們的一些價值添加到數據庫。這些文件的結構也非常複雜。我想用斯塔克斯解析器,因爲它提供的拉解析(因而處理)只有XML文件的部分好的可能性的時間,因而不加載在內存中的整個事情,但另一方面與得到的值Stax(至少在這些XML文件上)很麻煩,我需要編寫大量的代碼。但從後面這一點,將immensly幫助我,如果我能馬歇爾XML文件的Java對象(如JAX-B做),但是這會一下子加載整個文件加上一噸的對象實例在內存中。解析非常大的XML文件,並編組爲Java對象

我的問題是,是否有某種方法可以順序地解析(或部分解析)文件,然後只將那些部分編組爲Java對象,這樣我就可以輕鬆處理它們而不會在內存中陷入困境?

回答

2

嗯,首先我要感謝兩個人回答我的問題,但我終於結束了不使用這些主張部分是因爲這些建議的技術是有點遠從Java,讓我們比如說「標準的XML解析」,並且在Java中已經存在類似的工具時感覺很奇怪,部分原因是因爲我確實找到了一種只使用Java API來實現這一點的解決方案。

我就不詳細太多,我發現,因爲我已經完成實施,這是的代碼放在這裏相當一大塊的解決方案(我使用Spring Batch的在這一切之上,一噸配置和東西)。

我不過做什麼我終於結束了做小評:

這裏最大的想法是,如果你有一個XML文檔,它的相應的XSD架構,您可以分析&馬歇爾它與事實JAXB,並且可以以塊的形式實現,並且可以使用諸如STAX的解析器讀取塊,然後傳遞給JAXB Marshaller。

這實際上意味着你必須首先決定XML文件中的哪個位置,你可以說「這裏的這個部分有很多重複結構,我會一次處理一個這樣的重複」。那些重複的部分通常是在父標籤內部重複相同的(子)標籤。因此,您所要做的就是在STAX解析器中創建一個事件監聽器,這些事件監聽器在每個子標記開始時觸發,而不是將該子標記的內容流式傳輸到JAXB,然後使用JAXB對其進行處理並進行處理。 (真的,它是從2006年開始的,但是它處理JDK 1.6,當時它非常新,所以在版本上它並不是那麼古老):

http://www.javarants.com/2006/04/30/simple-and-efficient-xml-parsing-using-jaxb-2-0/

+0

很高興知道您的問題已解決。只是想知道這是如何(在這篇文章中的soln)不同於我發佈的內容? – Kashyap

+0

那麼,誠實地說,它是大型框架的一部分恐懼,部分懶惰:)(這兩者都很糟糕和令人遺憾)。首先,從文檔看,EMF看起來像一個相當複雜的框架,它不僅適用於XML處理,還適用於其他許多事情,而且我總是儘可能地避免這種沉重的框架(這只是個人偏好,我不是說一般做不好)。其次,我很懶,而且EMF使用了我不知道的非標準XML解析API,因此我用標準的Java XML API來提供解決方案。 –

+1

事實上,無論您是否喜歡EMF,我都建議不要使用它(「**因爲EMF對於這麼小的問題**太大了,除非你沒有選擇。」)。解析器再次引用「so **只是使用任何你想要的**解析,在循環中爲每個創建一些StringStream或者**,並傳遞給JAX-B或EMF。**」 – Kashyap

5

我會推薦的Eclipse EMF。但它有同樣的問題,如果你給它的文件名,它會解析整個事情。雖然有一些選項可以減少加載的數量,但是我們沒有打擾太多,因爲我們在96 GB RAM的機器上運行。 :)

無論如何,如果你的XML格式是明確界定,那麼一個解決辦法是通過愚弄打破整個文件分成幾個較小(但仍然良好定義的)XML片段的EMF。然後將每個片段依次加入。我不知道JAX-B,但也許可以在那裏應用相同的解決方法。我會推薦這種方法,因爲對於這樣一個小問題,EMF太大了。

只是爲了詳細一點,如果你的XML是這樣的:

<tag1> 
    <tag2> 
     <tag3/> 
     <tag4> 
      <tag5/> 
     </tag4> 
     <tag6/> 
     <tag7/> 
    </tag2> 

    <tag2> 
     <tag3/> 
     <tag4> 
      <tag5/> 
     </tag4> 
     <tag6/> 
     <tag7/> 
    </tag2> 
............ 
    <tag2> 
     <tag3/> 
     <tag4> 
      <tag5/> 
     </tag4> 
     <tag6/> 
     <tag7/> 
    </tag2> 
</tag1> 

然後,它可以分解成一個XML每個開始<tag2></tag2>結束。而在java中最解析器會接受一個流,所以只使用解析無論你想,在一個循環中創建一些字符串流或東西每個<tag2>,並傳遞到JAX-B或EMF。

HTH

+0

這事聽起來不錯,而且我會(在這裏它的午夜現在:))嘗試明天第一件事。感謝您的建議,聽起來很有希望 –

+1

@thekashyap。我可以買一臺這樣的機器嗎?只有一個! –

+0

嘿嘿..那些是我們的測試機器,在家裏我和其他人一樣在4GB的Win7筆記本電腦上工作.. :) – Kashyap

1

文件投影可能是這裏的答案。 Saxon和其他一些XQuery處理器提供這個選項。如果您有一個合理簡單的查詢從大型文檔中選擇少量數據,則查詢處理器會分析查詢以確定哪些樹部分需要用於查詢,哪些部分可以在處理期間被丟棄。生成的樹通常只能是整個文檔大小的1%。對於撒克遜這裏詳細介紹:

http://saxonica.com/documentation/sourcedocs/projection.xml