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 を使用することができ高速に処理できるようです。