XML処理 REXMLの使い方

よく忘れるので。
こんなXMLを用意した場合の例。

<root>
    <a name="a1">
        <b>bbb1</b>
        <b>bbb2</b>
        <b>bbb3</b>
        <c>ccc1</c>
    </a>
    <a>
        <b>bbb4</b>
        <b>bbb5</b>
    </a>
    <a name="a3" price="100"></a>
</root>
必ずrequire
require 'rexml/document'
XML読み込み
doc = REXML::Document.new(open("hoge.xml"))
とりあえず全文dump
puts doc

#結果
<root>
    <a name='a1'>
        <b>bbb1</b>
        <b>bbb2</b>
        <b>bbb3</b>
        <c>ccc1</c>
    </a>
    <a>
        <b>bbb4</b>
        <b>bbb5</b>
    </a>
    <a name='a3' price='100'/>
</root>
ピンポイントで取得(1番目Aタグの子、1番目Bタグの値)

添え字を指定していないので1番目のものが取られる

puts doc.elements['root/a/b'].text

#結果
bbb1
添え字を指定した場合
puts doc.elements['root/a[2]/b[2]'].text

#結果
bbb5
全Aタグの全子要素bタグ値を全部表示
doc.elements.each('root/a/b') do |element|
  puts element.text
end

#結果
bbb1
bbb2
bbb3
bbb4
bbb5

これは「全Aタグの、それぞれ1つ目のBタグ」となる。
ループするのはAタグで、Bはループしていない。
そして、3つ目Aは子要素にBタグがないのでエラーになる。

doc.elements.each('root/a') do |element|
  puts element.elements['b'].text
end
1つ目Aタグのbタグ値全部表示
doc.elements.each('root/a[1]/b') do |element|
  puts element.text
end

#結果
bbb1
bbb2
bbb3
1つ前のタグと後ろのタグ
doc.elements.each('root/a[1]/b[2]') do |element|
  puts element.previous_element.text
end

#結果
bbb1

doc.elements.each('root/a[1]/b[2]') do |element|
  puts element.next_element.text
end

#結果
bbb3
タグ名取得
doc.elements.each('root/a[1]') do |element|
  puts element.name
end

#結果
a
タグ名取得(子要素)
doc.elements.each('root/a[1]') do |element|
  puts element.elements[4].name
end

#結果
c
子要素数表示
doc.elements.each('root/a[2]') do |element|
  puts element.elements.size
end

#結果
2
属性値取得
doc.elements.each('root/a[3]') do |element|
  puts element.attributes["name"]
end

#結果
a3
属性はHashで返る
hash = Hash.new
doc.elements.each('root/a[3]') do |element|
  hash = element.attributes
end
puts hash.size     #=>2
puts hash["name"]  #=>a3
属性が特定値の要素を持つタグの子要素値
doc.elements.each("root/a[@name='a1']/b") do |element|
  puts element.text
end

#結果
bbb1
bbb2
bbb3

#"root/[@name='a1']/b" という指定も可能。この場合はタグ名を限定しなくなる
特定の属性値を持つタグの、別の属性値
puts doc.elements["root/a[@name='a3']"].attributes['price']

#結果
100

参考