2011-07-13 10 views
12

私はRubyのNokogiriを使用して、大きな(1 GB以上の)XMLファイルを解析しようとしています。私は小さなファイルにコードをテストしていますが、available hereという4つのレコードしか含まれていません。私はUbuntu 10.10でNokogiriバージョン1.5.0、Ruby 1.8.7を使用しています。私はSAXをよく理解していないので、Nokogiri :: XML :: Readerを起動しようとしています。大きなXMLファイルを解析するためにNokogiri :: XML :: Readerを使用するにはどうすればよいですか?

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", ""] 

何らかの理由で、私のコードが、すべてのinstancに対して余分な空のPMIDタグを見つけている、または生成しているようですPMIDのe。どちらか、それともinner_xmlは私が思ったように動作しません。

私のコードとデータが表示された結果を生成することを誰もが確認でき、私が間違っている場所を示唆してくれればと感謝します。

+0

「旧式」では、GBのRAMを搭載したホストを使用する前に、1〜2 GBのコンテンツを読み込むことを心配していました。今では、使用可能なすべてのRAMを消費する予期しないファイルを受け取るリスクがない限り、NokogiriとRubyにフルサイズのファイルをプルするようにします。ええ、1GBは多くのテキストですが、8GBまたは16GBシステムでは何もありません。メモリ割り当てとガベージコレクションが速度に影響を及ぼすため、負荷と処理時間が改善されるか影響を受けるかどうかを監視してください。その場合はSAXモデルを使用すると助けになりますが、ロードしてDOMのように扱う方がはるかに好きです。 –

+0

RAMよりも速度が重要です。たとえば、96 GBのRAMを持つ共有サーバー上でHpricot(私の推奨ライブラリ)を解析しようとしました:72分。 – neilfws

+0

私は数年間Hpricotをフォローしていません。私はそれをたくさん使っていましたが、輝かしい形で一貫して爆発し、ノコギリはそうしなかったいくつかの問題に遭遇しました。 72分は走るのに長い時間のようです。プロファイラを実行して、それが何かを明らかにするかどうかを調べるかもしれません。それ以外の場合は、コードとXMLを要約してここに投稿してください。これをスピードアップするのに役立ちます。 –

答えて

18

ストリームの各要素は、要素を開くためのものと閉じるためのものの2つのイベントとして処理されます。オープニングイベントは

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

を持っていますし、closingイベントは

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

あなたが見ている空の文字列がイベントを閉じるだけの要素である必要があります。 SAXの解析では、基本的にツリーを歩いているので、2つ目のイベントが必要なときに、バックアップを取って要素を閉じる必要があることを覚えておいてください。

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 –

関連する問題