Rubyインタプリタには、このページで紹介しているNQXMLではなく、REXMLが採用されました。REXMLの使い方はRubyでXML (REXML)を参照。
RubyでXML文書を読み書きしてみる。
Rubyの標準ライブラリにはXMLパーサーは含まれていない。Rubyで使えるXMLパーサーには,次のものがある。
このうち,NQXMLはpure-Rubyで,メンテナンスもされているようなので,これを使ってみる。
次のようなXML文書をスキャンしてみる。
<?xml version="1.0" encoding="EUC-JP"?> <?ruby class Foo def fn(x) x * 2 end end ?> <!DOCTYPE hoge> <hoge> <foo atr="2" bar="<">This is a pen.</foo> Plain. 日本語 <!-- コメント --> <content xml:lang="ja"> <![CDATA[<cdata>テスト]]> < コンテント ! ! </content> <br /> </hoge> <!-- コメント -->
タグ,文字データのほか,XML宣言,文書型宣言,処理命令,CDATAセクションを含み,実体参照,文字参照も使っている。
NQXMLでXML文書を読むとき,イテレータを使う方法と,DOMを使う方法がある。まずはイテレータから。
4| require 'nqxml/streamingparser' 5| 6| parser = nil 7| File.open("xmlsample.xml", "r") {|f| 8| parser = NQXML::StreamingParser.new(f) 9| } 10| i = 0 11| parser.each {|entity| 12| str = entity.to_s.strip 13| next if entity.instance_of?(NQXML::Text) && str == "" 14| i += 1 15| print "#{i}: #{str} #<#{entity.class}>\n" 16| }
で,実行結果。
1: <?xml version="1.0" encoding="EUC-JP"?> #<NQXML::XMLDecl> 2: <?ruby class Foo def fn(x) x * 2 end end ?> #<NQXML::ProcessingInstruction> 3: <!DOCTYPE hoge> #<NQXML::Doctype> 4: <hoge> #<NQXML::Tag> 5: <foo bar="<" atr="2"> #<NQXML::Tag> 6: This is a pen. #<NQXML::Text> 7: </foo> #<NQXML::Tag> 8: Plain. 日本語 #<NQXML::Text> 9: <!-- コメント --> #<NQXML::Comment> 10: <content xml:lang="ja"> #<NQXML::Tag> 11: <cdata>テスト #<NQXML::Text> 12: < コンテント ! ! #<NQXML::Text> 13: </content> #<NQXML::Tag> 14: <br> #<NQXML::Tag> 15: </br> #<NQXML::Tag> 16: </hoge> #<NQXML::Tag> 17: <!-- コメント --> #<NQXML::Comment>
XML文書内で次の表の左に挙げる項目が出現したときに,右に挙げるクラスのオブジェクトがブロックに渡される。
項目 | クラス |
---|---|
文字データ,CDATAセクション,参照 | NQXML::Text |
開始タグ,終了タグ,空要素タグ | NQXML::Tag |
XML宣言 | NQXML::XMLDecl |
文書型宣言 | NQXML::Doctype |
処理命令 | NQXML::ProcessingInstruction |
コメント | NQXML::Comment |
CDATAセクション,実体参照(<など),文字参照(!,!)は,あらかじめ展開されて文字データとして扱われる。参照は文字データに埋め込まれるが,CDATAセクションは独立したオブジェクトとなる。
属性値に含まれる参照も展開される。
空要素タグは,開始タグと終了タグに展開され,二つのオブジェクトとなる。
タグの要素名は,NQXML::Tag#nameメソッドで,属性はNQXML::Tag#attrsで取り出す。属性は,開始タグはHash(属性がないときは{}),終了タグはnilが返る。