xmlのパースがしたい!nokogiri
RubyでxmlやhtmlのパースするためにNokogiriの使い方を調べました。
インストール
gemからインストールできます。
gem install nokogiri
■パース
・直接パース
html = "<html><body><h1>Mr. Belvedere Fan Club</h1></body></html>"
html_doc = Nokogiri::HTML(html)
xml_doc = Nokogiri::XML("<root><aliens><alien><name>Alf</name></alien></aliens></root>")
puts html_doc
puts xml_doc
結果
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><h1>Mr. Belvedere Fan Club</h1></body></html>
<root>
<aliens>
<alien>
<name>Alf</name>
</alien>
</aliens>
</root>
・ファイルからパース
f = File.open("test.xml")
doc = Nokogiri::XML(f)
f.close
puts doc
結果
<?xml version="1.0"?>
<sushi>
<ikura>very good</ikura>
<saba>good</saba>
</sushi>
・urlからパース
require 'open-uri'
doc = Nokogiri::HTML(open("http://yahoo.co.jp"))
puts doc.title
実行結果
・自動で補完する
</b>がないので通常であればエラーになるはずが、、
doc = Nokogiri::XML('<a><b>b<c>c</c></a>')
puts doc
<?xml version="1.0"?>
<a>
<b>b<c>c</c></b>
</a>
勝手に補完してくれます。
・パースするときのオプション
xmlの構文が間違っているときエラーにしたい場合はオプションをつけて読み込みます
doc = Nokogiri::XML('<a><b>b<c>c</c></a>') do |config|
config.strict
end
puts doc
実行するとちゃんとエラーになります
/opt/ruby-1.9.3-p545/lib/ruby/gems/1.9.1/gems/nokogiri-1.6.1/lib/nokogiri/xml/document.rb:55:in `read_memory': Premature end of data in tag a line 1 (Nokogiri::XML::SyntaxError)
from /opt/ruby-1.9.3-p545/lib/ruby/gems/1.9.1/gems/nokogiri-1.6.1/lib/nokogiri/xml/document.rb:55:in `parse'
from /opt/ruby-1.9.3-p545/lib/ruby/gems/1.9.1/gems/nokogiri-1.6.1/lib/nokogiri/xml.rb:33:in `XML'
from noko.rb:43:in `<main>'
■検索
・<b></b>で囲まれたタグを取得
コード
doc = Nokogiri::XML('<a><b>b1</b><b>b2</b><c><b>b3</b></c></a>')
puts doc
puts doc.xpath("//b")
パースしたxml
<?xml version="1.0"?>
<a>
<b>b1</b>
<b>b2</b>
<c>
<b>b3</b>
</c>
</a>
結果
<b>b1</b>
<b>b2</b>
<b>b3</b>
・特定のタグを取得
コード
doc = Nokogiri::XML('<a><b>b1</b><b>b2</b><c><b>b3</b></c></a>')
puts doc
puts doc.xpath("/a/b")[1]
パースしたxml
<?xml version="1.0"?>
<a>
<b>b1</b>
<b>b2</b>
<c>
<b>b3</b>
</c>
</a>
結果
<b>b2</b>
・値を取得
コード
doc = Nokogiri::XML('<a><b>b1</b><b>b2</b><c><b>b3</b></c></a>')
puts doc
puts doc.xpath("/a/b")[1].inner_text
パースしたxml
<?xml version="1.0"?>
<a>
<b>b1</b>
<b>b2</b>
<c>
<b>b3</b>
</c>
</a>
結果
b2
・属性値を取得
コード
doc = Nokogiri::XML('<a><b>b1</b><b src="src_b2">b2</b><c><b>b3</b></c></a>')
puts doc
puts doc.xpath("/a/b")[1].attr("src")
パースしたxml
<?xml version="1.0"?>
<a>
<b>b1</b>
<b src="src_b2">b2</b>
<c>
<b>b3</b>
</c>
</a>
結果
src_b2
■変換
・値の変更
コード
doc = Nokogiri::XML('<a><b>b</b><c>c</c></a>')
puts doc
b = doc.at_css "b"
b.content = "bbbb"
puts doc
変換前
<?xml version="1.0"?>
<a>
<b>b</b>
<c>c</c>
</a>
変換後
<?xml version="1.0"?>
<a>
<b>bbbb</b>
<c>c</c>
</a>
・ノードの移動
コード
doc = Nokogiri::XML('<a><b>b</b><c>c</c></a>')
puts doc
b = doc.at_css "b"
c = doc.at_css "c"
b.parent = c
puts doc
変換前
<?xml version="1.0"?>
<a>
<b>b</b>
<c>c</c>
</a>
変換後
<?xml version="1.0"?>
<a>
<c>c<b>b</b></c>
</a>
・ノード移動2
コード
doc = Nokogiri::XML('<a><b>b</b><c>c</c></a>')
puts doc
b = doc.at_css "b"
c = doc.at_css "c"
c.add_next_sibling(b)
puts doc
変換前
<?xml version="1.0"?>
<a>
<b>b</b>
<c>c</c>
</a>
変換後
<?xml version="1.0"?>
<a>
<c>c</c>
<b>b</b>
</a>
・属性の追加
コード
doc = Nokogiri::XML('<a><b>b</b><c>c</c></a>')
puts doc
b = doc.at_css "b"
b['img'] = "bbb.img"
puts doc
変換前
<?xml version="1.0"?>
<a>
<b>b</b>
<c>c</c>
</a>
変換後
<?xml version="1.0"?>
<a>
<b img="bbb.img">b</b>
<c>c</c>
</a>
・ノードの追加
コード
doc = Nokogiri::XML('<a><b>b</b><c>c</c></a>')
puts doc
d = Nokogiri::XML::Node.new "d", doc
d.content = "ddddd"
c = doc.at_css "c"
c.add_next_sibling(d)
puts doc
変換前
<?xml version="1.0"?>
<a>
<b>b</b>
<c>c</c>
</a>
変換後
<?xml version="1.0"?>
<a>
<b>b</b>
<c>c</c>
<d>ddddd</d>
</a>
・ラップする
コード
doc = Nokogiri::XML('<a><b>b</b><c>c</c><d>d</d></a>')
puts doc
nodes = doc.css "b,c"
wrapper = nodes.wrap("<test></test>")
puts doc
変換前
<?xml version="1.0"?>
<a>
<b>b</b>
<c>c</c>
<d>d</d>
</a>
変換後
<?xml version="1.0"?>
<a>
<test>
<b>b</b>
</test>
<test>
<c>c</c>
</test>
<d>d</d>
</a>
こんな感じでいろいろできます。
トラブルシューティング
エラー
libexslt.so.0: cannot open shared object file: No such file or directory
対処法:libxsltをインストールする
sudo yum install libxslt