RubyプログラムにおけるXMLファイルの作成と解析のための方法
ビルダーでXMLを作成する
builderのインストール方法です。
gem install builder
require 'builder'
x = Builder::XmlMarkup.new(:target =>
$stdout, :indent => 1)
#":target => $stdout" parameter: indicates that the output
content will be written to the standard output console
#":indent => 1" parameter: the XML output form will be indented by
:xml,
:version =>'1.1',:encoding => 'gb2312'
x.comment! "book info"
x.library("shelf" => "Recent Acquisitions") {
x.section("name" => "ruby") {
x.book("isbn" => "0672310001"){
x.title "Programming Ruby"
x.author "Yukihiro "
x.description "Programming Ruby -
The Pragmatic Programmer's Guide"
}
}
}
p x #XMLを印刷する
RubyがXML出力を作成します。
< ?xml version="1.1" encoding="gb2312"? >
< ! --book info -->
< library shelf="Recent Acquisitions">
< section name="ruby">
< book isbn="0672310001">
< title>Programming Ruby< /title>
< author>Yukihiro < /author>
< description>Programming Ruby - The
Pragmatic Programmer's Guide
< /description>
< /book>
< /section>
< /library>
< inspect/>
#< IO:0x2a06ae8>
ReXMLによるXMLのパース
REXMLは全てrubyで書かれたプロセッサで、いくつかのAPIを持っているが、そのうちの2つは古典的にDOMライクとSAXライクで区別される。最初のものは、ファイル全体をメモリに読み込んで、階層的な形(つまりツリー)で保存するものである。もうひとつは "parse as you go" で、これはファイルが大きく、メモリが限られている場合に適しています。
次のbook.xmlを見てください。
引用
<library shelf="Recent Acquisitions">
<section name="Ruby">
<book isbn="0672328844">
<title>The Ruby Way</title>
<author>Hal Fulton</author>
<description>
The book you are now reading.
Ain't recursion grand?
</description>
</book>
</section>
<section name="Space">
<book isbn="0684835509">
<title>The Case for Mars</title>
<author>Robert Zubrin</author>
<description>Pushing toward a second home for the human
race.
</description>
</book>
<book isbn="074325631X">
<title>First Man: The Life of Neil A. Armstrong</title>
<author>James R. Hansen</author>
<description>Definitive biography of the first man on
the moon.
</description>
</book>
</section>
</library>
1 ツリーパース(別名:DOMライク)
rexml/document ライブラリを必要とし、REXML をインクルードする必要があります。
require 'rexml/document'
include REXML
input = File.new("books.xml")
doc = Document.new(input)
root = doc.root
puts root.attributes["shelf"] # Recent Acquisitions
doc.elements.each("library/section") { |e| puts e.attributes["name"] }
# Output:
# Ruby
# Space
doc.elements.each("*/section/book") { |e| puts e.attributes["isbn"] }
# Output:
# 0672328844
# 0321445619
# 0684835509
# 074325631X
sec2 = root.elements[2]
author = sec2.elements[1].elements["author"].text # Robert Zubrin
なお、xmlの属性と値はハッシュで表現されているので、attributes[]を使って必要な値を取り出すことができますし、要素の値はパスのような文字列か整数値で取得することが可能です。ここで、整数は0ベースではなく1ベースである。
2 ストリーム解析(別名:SAXライク解析)
ここでちょっとしたコツは、パース時にコールバックされるリスナークラスを定義することです。
require 'rexml/document'
require 'rexml/streamlistener'
include REXML
class MyListener
include REXML::StreamListener
def tag_start(*args)
puts "tag_start: #{args.map {|x| x.inspect}.join(', ')}"
end
def text(data)
return if data =~ /^\w*$/ # whitespace only
abbrev = data[0..40] + (data.length > 40 ? "... " : "")
puts " text : #{abbrev.inspect}"
end
end
list = MyListener.new
source = File.new "books.xml"
Document.parse_stream(source, list)
このモジュールはいくつかの空のコールバックメソッドを提供していますので、独自の機能を持たせるためにオーバーライドすることができます。パーサーがタグに入るとき、tag_start メソッドを呼び出します。textメソッドも同様ですが、データが読み込まれたときにコールバックされ、その出力は以下のようになります。
tag_start: "library", {"shelf"=>"Recent Acquisitions"}
tag_start: "section", {"name"=>"Ruby"}
tag_start: "book", {"isbn"=>"0672328844"}
tag_start: "title", {}
text : "The Ruby Way"
.........................................
3 XPath
REXMLは、XPathクラスを通じてXpathをサポートしています。また、DOM ライクと SAX ライクの両方をサポートしています。先ほどの xml ファイルと同様に、Xpath を使って次のようなことができます。
book1 = XPath.first(doc, "//book") # Info for first book found
p book1
# Print out all titles
XPath.each(doc, "//title") { |e| puts e.text }
# Get an array of all of the "author" elements in the document.
names = XPath.match(doc, "//author").map {|x| x.text }
p names
出力は以下のようなものです。
<book isbn='0672328844'> ... </>
The Ruby Way
The Case for Mars
First Man: The Life of Neil A. Armstrong
["Hal Fulton", "Robert Zubrin", "James R. Hansen"]
関連
-
Rubyを使ったFTPパスワードクラッキング
-
挿入ソートアルゴリズムのRuby実装と高度な双方向挿入ソートコード例
-
Rubyのgemパッケージ管理およびgemソース構築のチュートリアル
-
RubyのTimeオブジェクトの共通機能まとめ
-
Rubyのデザインパターン。プログラミングにおけるストラテジーパターンの活用
-
Ruby on Railsのパフォーマンスを最適化するためのいくつかの方法についての考察
-
Rubyにおけるコメントの使い方と中国語のエンコーディングについて解説します。
-
Rubyの基本的な環境変数の設定と一般的なインタープリタコマンド
-
Rubyで配列とハッシュテーブルを使う
-
Rubyのメソッドを検索して実行する
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
モンキーパッチのプログラミングスタイルとRubyでの利用について
-
Rubyのオブジェクト指向のアプローチによるプログラミング学習雑学
-
RubyでXMLデータ処理ライブラリREXMLを使うための手引き
-
Builderビルダーパターンを用いたRubyデザインパターンプログラミング例
-
デザインパターンのうち、ProxyパターンとDecorativeパターンを使ったRubyのコード例
-
Rubyの4つの比較関数(equal?, eql?, ==, ===)について解説します。
-
Rubyの基本文法チュートリアル
-
Ruby on Railsのルーティング設定に関するいくつかのアドバイス
-
Rubyのモジュールに関する基礎知識
-
Rubyのクラスとモジュールの書き方のスタイルガイド