ActiveSupport で XML のパース導入編
「Ruby で XML をパースしたい」ということで(蛇足気味ですが)調べたメモを公開します。
ActiveSupport でやるのが簡単でいいですね。
公式ドキュメント
前提条件
Hash.from_xml や XmlMini をデフォルトで使う
標準ライブラリの REXML を使うので、特にありません。
XmlMini.backend = 'Nokogiri' で使う
libxml2 と libxslt が必要です。
Ruby Gems
Windows の場合は sudo は要りません。
Hash.from_xml や XmlMini をデフォルトで使う
sudo gem install activesupport
XmlMini.backend = 'LibXML' で使う
sudo gem install libxml-ruby sudo gem install activesupport
XmlMini.backend = 'Nokogiri' で使う
sudo gem install nokogiri sudo gem install activesupport
XML をパースして Hash オブジェクトにする
デフォルトのまま
require 'active_support' xml = <<EOM <?xml version="1.0" encoding="UTF-8"?> <items> <item id="123"> <name>Andy</name> <age>21</age> </item> <item id="234"> <name>Brian</name> <age>23</age> </item> <item id="345"> <name>Charles</name> <age>19</age> </item> </items> EOM doc = ActiveSupport::XmlMini.parse(xml) doc.is_a?(Hash) # => true
doc はこんな感じの Hash になります。
{"items" => {"item" => [ {"id" => "123", "name" => {"__content__" => "Andy"}, "age" => {"__content__" => "21"}}, {"id" => "234", "name" => {"__content__" => "Brian"}, "age" => {"__content__" => "23"}}, {"id" => "345", "name" => {"__content__" => "Charles"}, "age" => {"__content__" => "19"}} ]} }
階層が深くなってしまいます。
以下のリンク先にあるような問題を考慮しなくてよい場合は
http://techracho.bpsinc.jp/baba/2010_05_25/1597
Hash.from_xml を使う方が便利です。
ソースコードを読むと分かるとおり、内部的に XmlMini.parse を呼んでさらに結果の Hash を加工しています。
require 'active_support/core_ext' doc = Hash.from_xml(xml)
結果はこのようになります。属性の id も小要素の name や age も同じように Hash に格納されます。
{"items" => {"item" => [ {"id"=>"123", "name"=>"Andy", "age"=>"21"}, {"id"=>"234", "name"=>"Brian", "age"=>"23"}, {"id"=>"345", "name"=>"Charles", "age"=>"19"} ]} }
ActiveSupport::XmlMini.backend = 'LibXML'
使い方は何も変わりません。内部的に LibXML Ruby が使われて高速になります。
require 'active_support' ActiveSupport::XmlMini.backend = 'LibXML' doc = ActiveSupport::XmlMini.parse(xml) require 'active_support/core_ext' doc = Hash.from_xml(xml)
ActiveSupport::XmlMini.backend = 'Nokogiri'
使う側は何も変わりません。内部的に Nokogiri が使われて高速になります。
require 'active_support' ActiveSupport::XmlMini.backend = 'Nokogiri' doc = ActiveSupport::XmlMini.parse(xml) require 'active_support/core_ext' doc = Hash.from_xml(xml)