巨大な XML(XMLファイル)を Nokogiri で取り扱うときは Nokogiri::XML::Reader を用いる

結論

たとえば、数GBある XML ファイル sample.xml があったとします*1。 これを以下のように読み込むとエラーになります*2

xml = Nokogiri::XML.parse(File.open('sample.xml'))

なので、そのような場合には Nokogiri::XML::Reader を以下のように用います。

xml = Nokogiri::XML::Reader(File.open('sample.xml'))

Nokogiri::XML::Reader をどう取り扱うか

Nokogiri::XML::Reader は Ennumurable なので each で回してあげればいいです。

xml = Nokogiri::XML::Reader(File.open('sample.xml'))

xml_reader.each do |node|
  node_name = node.name
  node_type = node.node_type

  # node が <page> で始まる場合にはその中身を表示する
  next if node_name != 'page' || node_type != Nokogiri::XML::Reader::TYPE_ELEMENT

  puts node.outer_xml
end

上記の node に生えているメソッドは公式ドキュメントを参考にしてください。

nokogiri.org

node.node_type の戻り値は数値です。上記ドキュメントの Constants にある文字列も数値を返しますので比較や判別ができます*3。数値そのものを比較にもちいるのではなく node.node_typeNokogiri::XML::Reader::HOGEHOGE を比較するという感じです。

たとえば Nokogiri::XML::Reader::TYPE_ELEMENT はその node が「開始タグ」であることを表し、 Nokogiri::XML::Reader::TYPE_END_ELEMENT はその node が「終了タグ」であることを表します。

*1:例として Wikipedia のダンプファイル

*2:たとえ読み込めても読み込み完了までに時間がかかり、リソースも食います

*3:enum のようなもの

Powered by はてなブログ