旅とサブカル、時々ガジェット。

Ruby で XML⇒Hash変換 ActiveSupport+REXML vs. Nokogiri

 2019/03/08  Ruby

Ruby で XML のデータを Hash に変換して使う必要があったが、要素数がおよそ65万もあり、Hash.from_xml でやるとものすごく時間がかかってしまったので、Nokogiri を使用した場合との比較メモ。

  • XMLファイル(ファイルサイズ:31.5MB)
1
2
3
4
5
6
7
8
<IdNameList>
    <Record id="12345" name="abcd" />
    <Record id="67890" name="efgh" />
    <Record id="13467" name="ijkl" />
      ・・・
  (約65万行)
      ・・・
</IdNameList>
  • 出力するHash
1
2
3
4
5
6
hash = {
  "12345" => "abcd",
  "67890" => "efgh",
  "13467" => "ijkl",
    ・・・
}

REXML(Ruby標準ライブラリ)+ ActiveSupport

内部的に ActiveSupport::XmlMini.parse の処理が行われる。

1
2
3
4
5
6
7
8
require 'active_support'
require 'active_support/core_ext'

hash = Hash.new

xml = Hash.from_xml(File.open('userlist.xml'))

xml['IdNameList']['Record'].each { |data| hash.store(data[id], data[name]) }

処理時間:316.669600947 sec.

Nokogiri

1
2
3
4
5
6
7
require 'nokogiri'

hash = Hash.new

xml = Nokogiri::XML(File.open('userlist.xml'))

xml.path('/IdNameList/Record').each { |data| hash.store(data.attributes['id'].value, data.attributes['name'].value) }

処理時間:5.729888423 sec.

結果

Nokogiri を使うことで圧倒的に速くなりました。

今回は試していませんが、LibXML というライブラリもあるそうです。

また、ActiveSupport を使う場合でも、

1
2
ActiveSupport::backend = 'LibXML'
ActiveSupport::XmlMini.parse(xml)
1
2
ActiveSupport::backend = 'Nokogiri'
ActiveSupport::XmlMini.parse(xml)

などとすることで、内部処理に LibXML や Nokogiri を使用することができ高速に処理できるようです。

参考

© 2020 orangeliner.net