Ruby-xml-xslt
Ruby-XML、XSLT、XPathチュートリアル
XMLとは何ですか?
拡張マークアップ言語(XML)は、HTMLやSGMLによく似たマークアップ言語です。 これは、World Wide Web Consortiumによって推奨されており、オープンスタンダードとして利用できます。
XMLは、オペレーティングシステムや開発言語に関係なく、プログラマが他のアプリケーションで読み取れるアプリケーションを開発できる、移植可能なオープンソース言語です。
XMLは、SQLベースのバックボーンを必要とせずに、少量から中量のデータを追跡するのに非常に役立ちます。
XMLパーサーのアーキテクチャとAPI
XMLパーサーには2つの異なるフレーバーがあります-
- * SAXライク(ストリームインターフェイス)*-ここで、目的のイベントのコールバックを登録し、パーサーにドキュメントを処理させます。 これは、ドキュメントが大きい場合やメモリに制限がある場合に便利です。ファイルをディスクから読み取るときに解析し、ファイル全体がメモリに保存されることはありません。
- * DOMに似た(オブジェクトツリーインターフェイス)*-これはWorld Wide Web Consortiumの推奨事項で、ファイル全体がメモリに読み込まれ、XMLドキュメントのすべての機能を表す階層(ツリーベース)形式で保存されます。
SAXは明らかに、大きなファイルを操作する場合、DOMほど速く情報を処理できません。 一方、DOMを排他的に使用すると、特に多くの小さなファイルで使用する場合、リソースを本当に殺す可能性があります。
SAXは読み取り専用ですが、DOMはXMLファイルの変更を許可します。 これら2つの異なるAPIは文字通り互いに補完するため、大規模なプロジェクトで両方を使用できない理由はありません。
Rubyを使用したXMLの解析と作成
XMLを操作する最も一般的な方法は、Sean RussellによるREXMLライブラリを使用することです。 2002年以来、REXMLは標準のRubyディストリビューションの一部となっています。
REXMLは、XML 1.0標準に準拠した純粋なRuby XMLプロセッサです。 これは_non-validating_プロセッサーであり、OASISのすべての非検証適合性テストに合格しています。
REXMLパーサーには、他の利用可能なパーサーよりも次の利点があります-
- Rubyで100%記述されています。
- SAXとDOMの両方の解析に使用できます。
- 軽量で、2000行未満のコードです。
- メソッドとクラスは本当に理解しやすいです。
- SAX2ベースのAPIおよび完全なXPathサポート。
- Rubyインストールで出荷され、個別のインストールは必要ありません。
私たちのすべてのXMLコードの例では、単純なXMLファイルを入力として使用しましょう-
<collection shelf = "New Arrivals">
<movie title = "Enemy Behind">
<type>War, Thriller</type>
<format>DVD</format>
<year>2003</year>
<rating>PG</rating>
<stars>10</stars>
<description>Talk about a US-Japan war</description>
</movie>
<movie title = "Transformers">
<type>Anime, Science Fiction</type>
<format>DVD</format>
<year>1989</year>
<rating>R</rating>
<stars>8</stars>
<description>A schientific fiction</description>
</movie>
<movie title = "Trigun">
<type>Anime, Action</type>
<format>DVD</format>
<episodes>4</episodes>
<rating>PG</rating>
<stars>10</stars>
<description>Vash the Stampede!</description>
</movie>
<movie title = "Ishtar">
<type>Comedy</type>
<format>VHS</format>
<rating>PG</rating>
<stars>2</stars>
<description>Viewable boredom</description>
</movie>
</collection>
DOMのような解析
最初に_tree fashion_でXMLデータを解析しましょう。 まず、 rexml/document ライブラリーを要求することから始めます。便宜上、REXMLをインクルードしてトップレベルのネームスペースにインポートすることがよくあります。
#!/usr/bin/ruby -w
require 'rexml/document'
include REXML
xmlfile = File.new("movies.xml")
xmldoc = Document.new(xmlfile)
# Now get the root element
root = xmldoc.root
puts "Root element : " + root.attributes["shelf"]
# This will output all the movie titles.
xmldoc.elements.each("collection/movie"){
|e| puts "Movie Title : " + e.attributes["title"]
}
# This will output all the movie types.
xmldoc.elements.each("collection/movie/type") {
|e| puts "Movie Type : " + e.text
}
# This will output all the movie description.
xmldoc.elements.each("collection/movie/description") {
|e| puts "Movie Description : " + e.text
}
これは、次の結果を生成します-
Root element : New Arrivals
Movie Title : Enemy Behind
Movie Title : Transformers
Movie Title : Trigun
Movie Title : Ishtar
Movie Type : War, Thriller
Movie Type : Anime, Science Fiction
Movie Type : Anime, Action
Movie Type : Comedy
Movie Description : Talk about a US-Japan war
Movie Description : A schientific fiction
Movie Description : Vash the Stampede!
Movie Description : Viewable boredom
SAXのような解析
同じデータ_movies.xml_を_stream指向の方法で処理するには、パーサーからの_callbacks_のターゲットとなるメソッドを持つ_listener_クラスを定義します。
注-小さなファイルにSAXのような構文解析を使用することは推奨されません。これは単なるデモの例です。
#!/usr/bin/ruby -w
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
xmlfile = File.new("movies.xml")
Document.parse_stream(xmlfile, list)
これは、次の結果を生成します-
tag_start: "collection", {"shelf"=>"New Arrivals"}
tag_start: "movie", {"title"=>"Enemy Behind"}
tag_start: "type", {}
text : "War, Thriller"
tag_start: "format", {}
tag_start: "year", {}
tag_start: "rating", {}
tag_start: "stars", {}
tag_start: "description", {}
text : "Talk about a US-Japan war"
tag_start: "movie", {"title"=>"Transformers"}
tag_start: "type", {}
text : "Anime, Science Fiction"
tag_start: "format", {}
tag_start: "year", {}
tag_start: "rating", {}
tag_start: "stars", {}
tag_start: "description", {}
text : "A schientific fiction"
tag_start: "movie", {"title"=>"Trigun"}
tag_start: "type", {}
text : "Anime, Action"
tag_start: "format", {}
tag_start: "episodes", {}
tag_start: "rating", {}
tag_start: "stars", {}
tag_start: "description", {}
text : "Vash the Stampede!"
tag_start: "movie", {"title"=>"Ishtar"}
tag_start: "type", {}
tag_start: "format", {}
tag_start: "rating", {}
tag_start: "stars", {}
tag_start: "description", {}
text : "Viewable boredom"
XPathとRuby
XMLを表示する別の方法はXPathです。 これは、XMLドキュメント内の特定の要素と属性を見つける方法を記述する一種の疑似言語であり、そのドキュメントを論理的な順序付けられたツリーとして扱います。
REXMLには、_XPath_クラスを介したXPathサポートがあります。 上記で見たように、ツリーベースの解析(ドキュメントオブジェクトモデル)を想定しています。
#!/usr/bin/ruby -w
require 'rexml/document'
include REXML
xmlfile = File.new("movies.xml")
xmldoc = Document.new(xmlfile)
# Info for the first movie found
movie = XPath.first(xmldoc, "//movie")
p movie
# Print out all the movie types
XPath.each(xmldoc, "//type") { |e| puts e.text }
# Get an array of all of the movie formats.
names = XPath.match(xmldoc, "//format").map {|x| x.text }
p names
これは、次の結果を生成します-
<movie title = 'Enemy Behind'> ... </>
War, Thriller
Anime, Science Fiction
Anime, Action
Comedy
["DVD", "DVD", "DVD", "VHS"]
XSLTとRuby
Rubyで使用できるXSLTパーサーは2つあります。 それぞれの簡単な説明をここに示します。
ルビー・サブロトロン
このパーサーは、高橋正義によって作成および管理されています。 これは主にLinux OS用に書かれており、次のライブラリが必要です-
- サブロット
- アイコン
- 海外駐在者
このモジュールは、 Ruby-Sablotron にあります。
XSLT4R
XSLT4RはMichael Neumannによって作成され、XMLの下のLibraryセクションのRAAにあります。 XSLT4Rはシンプルなコマンドラインインターフェイスを使用しますが、サードパーティのアプリケーション内で使用してXMLドキュメントを変換することもできます。
XSLT4Rを操作するにはXMLScanが必要です。これはXSLT4Rアーカイブに含まれており、100%Rubyモジュールでもあります。 これらのモジュールは、標準のRubyインストール方法(つまり、ruby install.rb)を使用してインストールできます。
XSLT4Rには次の構文があります-
ruby xslt.rb stylesheet.xsl document.xml [arguments]
アプリケーション内からXSLT4Rを使用する場合は、XSLTを含めて必要なパラメーターを入力できます。 ここに例があります-
require "xslt"
stylesheet = File.readlines("stylesheet.xsl").to_s
xml_doc = File.readlines("document.xml").to_s
arguments = { 'image_dir' => '/....' }
sheet = XSLT::Stylesheet.new( stylesheet, arguments )
# output to StdOut
sheet.apply( xml_doc )
# output to 'str'
str = ""
sheet.output = [ str ]
sheet.apply( xml_doc )
参考文献
- REXMLパーサーの詳細については、https://www.germane-software.com/software/rexml/[REXMLパーサードキュメント]の標準ドキュメントを参照してください。
- XSLT4Rはhttp://raa.ruby-lang.org/project/xslt4r/[RAA Repository]からダウンロードできます。