2011-07-13 95 views
12

我正在嘗試使用Ruby的Nokogiri來解析大型(1 GB或更多)XML文件。我在一個較小的文件上測試代碼,只包含4條記錄available here。我在Ubuntu 10.10上使用Nokogiri版本1.5.0,Ruby 1.8.7。由於我不太瞭解SAX,我正在嘗試使用Nokogiri :: XML :: Reader來啓動。如何使用Nokogiri :: XML :: Reader來解析大型XML文件?

我第一次嘗試,檢索PMID標籤的內容,看起來像這樣:

#!/usr/bin/ruby 
require "rubygems" 
require "nokogiri" 

file = ARGV[0] 
reader = Nokogiri::XML::Reader(File.open(file)) 
p  = [] 
reader.each do |node| 
    if node.name == "PMID" 
    p << node.inner_xml 
    end 
end 

puts p.inspect 

這是我希望看到:

["21714156", "21693734", "21692271", "21692260"] 

這是我居然看到:

["21714156", "", "21693734", "", "21692271", "", "21692260", ""] 

似乎由於某種原因,我的代碼正在爲每個實例找到或生成一個額外的空PMID標記PMID的。無論是或inner_xml不工作,因爲我認爲。

如果有人可以確認我的代碼和數據生成顯示的結果並提示我出錯的位置,我將不勝感激。

+0

在「過去的日子」裏,在我們擁有很多RAM的主機之前,我們曾經擔心加載一個或兩個GB內容。現在,除非有接收意外文件的風險,否則會消耗所有可用的RAM,否則我會嘗試讓Nokogiri和Ruby拉入完整大小的文件。是的,1GB是很多文本,但是在8GB或16GB系統上沒有任何內容。觀察內存分配和垃圾收集是否會影響速度,從而加載和處理時間是否改善或受到影響;在這種情況下使用SAX模型可以提供幫助,但是我更喜歡將其加載並像DOM一樣對待它。 –

+0

速度比RAM更多的問題。例如,我嘗試使用96 GB RAM的共享服務器上的Hpricot(我的首選庫)解析:72分鐘。 – neilfws

+0

我一直未遵循Hpricot一兩年;我用了很多,但遇到了一些以光榮的方式持續爆炸的問題,而Nokogiri沒有,所以我轉而不回頭。 72分鐘似乎很長時間才能運行。您可以嘗試運行分析器並查看它是否顯示任何內容。否則,總結一下代碼和XML並將其發佈到此處,我們將盡力幫助加快速度。 –

回答

18

流中的每個元素都以兩個事件發生:一個用於打開元素,另一個用於關閉它。開幕活動將有

node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT 

和閉幕活動將有

node.node_type == Nokogiri::XML::Reader::TYPE_END_ELEMENT 

你看到的空字符串是剛剛閉幕的事件的元素。請記住,在SAX解析中,基本上你正在步行穿過一棵樹,所以你需要第二個事件來告訴你什麼時候你要回去並關閉一個元素。

你可能想要更多的東西是這樣的:

reader.each do |node| 
    if node.name == "PMID" && node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT 
    p << node.inner_xml 
    end 
end 

或許:

reader.each do |node| 
    next if node.name  != 'PMID' 
    next if node.node_type != Nokogiri::XML::Reader::TYPE_ELEMENT 
    p << node.inner_xml 
end 

或者在其他一些變化。

+0

您的第一個解決方案有效;非常感謝。 – neilfws

+0

爲什麼不試試這個 - https://github.com/amolpujari/reading-huge-xml –