Qu'ils mangent de la X'ruby(クリスマスリリースがないならクリスマスRubyを作ればいいじゃない)

この記事はRuby Advent Calendar2009の最終日です。昨日は@tomoya55さんでした。



メリークリスマス! = Merry Xmas! ≒ Merry Xml! ということで、XMLRubyの話をします。
TokyuRuby会議*1でこんなことを言った人がいました。
Rubyは90年代のいいとこ取り言語だけど、Scalaは2000年代のいいとこ取り言語だ」
これを聞いた敬虔なRubyistの皆さんはもちろん「2000年代いいとこ取りの結果がXMLかよ!」って思ったと思うんですが

/* http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk/docs/examples/xml/phonebook/phonebook.scala */
package phonebook ;
object phonebook {
  val labPhoneBook = 
    <phonebook>
      <descr>
        This is the <b>phonebook</b> of the 
        <a href="http://acme.org">ACME</a> corporation.
      </descr>
      <entry>
        <name>Burak</name> 
        <phone where="work">  +41 21 693 68 67</phone>
        <phone where="mobile">+41 79 602 23 23</phone>
      </entry>
    </phonebook>;
  // ... snip ...

とはいえXMLリテラルって言う発想は正直なかったし、機能はともかくその素っ頓狂な見た目がやっぱり羨ましかったりするわけです。
そんな素敵リテラルを指を加えて眺めるだけだった日々は昨日でおしまいです。そう、今日はクリスマス。目が覚めると良い子にしていたみんなの枕元のRubyにはXMLリテラルが入っていたのです!!

phone_book = <?xml>
  <phonebook>
    <descr>
      This is the <b>phonebook</b> of the 
      <a href="http://acme.org">ACME</a> corporation.
    </descr>
    <entry>
      <name>Burak</name> 
      <phone where="work">  +41 21 693 68 67</phone>
      <phone where="mobile">+41 79 602 23 23</phone>
    </entry>
  </phonebook>
</xml>

puts phone_book.class.name
#=> REXML::Document

puts phone_book.elements["//phone[@where='mobile']"].text
#=> +41 79 602 23 23

puts phone_book.elements["//descr/a"].attribute('href')
#=> http://acme.org

X'rubyではヒアドキュメントのように*2<?識別子>から</識別子>までの間をREXML::Documentオブジェクトにして返します。無論、開始と終了のところの識別子は任意。まぁxmlにしとくのが無難というかおすすめだけど。
REXMLは使いにくいから嫌だという人はString#xmlを上書きしましょう。Nokogiriを使いたければこんな感じで。

require 'nokogiri'
class String
  def xml
    Nokogiri.parse(self)
  end
end

あとこんな感じに式展開も可能。

message = 'hello'
greeting = <?xml>
  <greeting>
    #{message}
  </greeting>
</xml>

ということで、今年もクリスマスに新しいRubyがリリースされ、伝統と格式は守られました。
http://github.com/technohippy/xruby
それではみなさん、良いお年を。

*1:みなさんそろそろ忘れているかもしれないですが、大事なことなので注記しておきますね。TokyuRubyKaigiとは私がカリスマになったKaigiです

*2:っていうかparse.yのヒアドキュメントのところをあらかたコピペしてでっち上げてるんだけど