libxml-ruby で XML のパース導入編
「Ruby で XML をパースしたい」ということで(蛇足気味ですが)調べたメモを公開します。
前提条件
libxml2 が必要です。CentOSであれば以下のように準備します。
yum install libxml2-devel
Windows の場合はここから
ftp://ftp.zlatkovic.com/libxml/
「libxml2-2.7.8.win32.zip」を解凍してできた「bin/libxml2.dll」を「libxml2-2.dll」にリネームして「%RUBY_HOME%/bin」に置く。
LibXML::XML::Document
とりあえず XML をパースするだけならこのクラスの使い方を知れば事足りそうです。
#!/usr/bin/env ruby require 'libxml' xml = <<EOM <?xml version="1.0" encoding="UTF-8"?> <items> <item id="123">Andy</item> <item id="234">Brian</item> <item id="345">Charles</item> </items> EOM doc = XML::Document.string(xml)
実際には「LibXML::XML::Document」というパッケージで libxml.rb の中で include していて「LibXML::」を省略することができています*1。
doc = LibXML::XML::Document.string(xml)
XPath を使って XML をパースする
ここでは文字列の XML をパースするので Document.string を使っていますがファイル読み込みの場合は Document.file など他の入力からもパースすることができます。
require 'libxml' xml = <<EOM <?xml version="1.0" encoding="UTF-8"?> <items> <item id="123">Andy</item> <item id="234">Brian</item> <item id="345">Charles</item> </items> EOM doc = LibXML::XML::Document.string(xml)
Document#find に XPath を渡して要素を絞り込みます。
irb(main):018:0> doc.find('/items/item') => #<LibXML::XML::XPath::Object:0x1369608> irb(main):029:0> xpath_object = doc.find('/items/item').is_a?(Enumerable) => true
属性は Hash のようにして取得し値は #content で取り出します。
first で最初の要素、 last で最後の要素を取得することもできます。
irb(main):051:0> doc.find('/items/item').each do |item| irb(main):052:1* puts item[:id] + ' -> ' + item.content irb(main):053:1> end 123 -> Andy 234 -> Brian 345 -> Charles => #<LibXML::XML::XPath::Object:0x13ddca8> irb(main):054:0> doc.find('/items/item').first => <item id="123">Andy</item> irb(main):055:0> doc.find('/items/item').last => <item id="345">Charles</item>