Ruby XML、XSLT、および XPath のチュートリアル



XML とは何ですか?

XML は eXtensible Markup Language を指します。

Extensible Markup Language は、標準ユニバーサル マークアップ言語のサブセットであり、電子ドキュメントをマークアップして構造化するために使用されるマークアップ言語です。

データのマーク付けとデータ型の定義に使用でき、ユーザーが独自のマークアップ言語を定義できるようになります。 これは World Wide Web トランスポートに最適であり、アプリケーションやベンダーに依存せずに構造化データを記述および交換するための統一されたアプローチを提供します。

詳細については、XML チュートリアルをご覧ください


XML パーサーの構造と API

XML パーサーには、DOM と SAX の 2 つの主要なタイプがあります。

  • SAX パーサーはイベント処理に基づいており、スキャン プロセス中に文法構造が見つかるたびに、この特定の文法構造のイベント ハンドラーが呼び出されます。イベントをアプリケーションに送信します。

  • DOM は、ドキュメントの階層構文構造を構築し、メモリ内に DOM ツリーを作成するドキュメント オブジェクト モデルの解析です。ドキュメントの解析が完了すると、DOM ツリーのノードがオブジェクトの形式で識別されます。ドキュメントの DOM ツリー全体がメモリ内に配置されます。


Ruby での XML の解析と作成

RUBY は、このライブラリ REXML ライブラリを使用して XML ドキュメントを解析できます。

REXML ライブラリは、純粋な Ruby 言語で書かれており、XML1.0 仕様に準拠しています。

Ruby バージョン 1.8 以降では、REXML が RUBY 標準ライブラリに含まれます。

REXML ライブラリのパスは次のとおりです: rexml/document

すべてのメソッドとクラスは REXML モジュールにカプセル化されます。

REXML パーサーには、他のパーサーに比べて次の利点があります:

  • 100% が Ruby で書かれています。

  • SAX および DOM パーサーで動作します。

  • これは軽量で、コードは 2000 行未満です。

  • メソッドとクラスは非常に理解しやすいです。

  • SAX2 API と完全な XPath サポートに基づいています。

  • 個別にインストールするのではなく、Ruby のインストールを使用してください。

以下は、movie.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 パーサー

まず XML データを解析しましょう。最初に rexml/document ライブラリを導入します。通常は REXML を配置できます。トップレベルで 名前空間に導入されます:

#!/usr/bin/ruby -w

require 'rexml/document'
include REXML

xmlfile = File.new("movies.xml")
xmldoc = Document.new(xmlfile)

# 获取 root 元素
root = xmldoc.root
puts "Root element : " + root.attributes["shelf"]

# 以下将输出电影标题
xmldoc.elements.each("collection/movie"){ 
   |e| puts "Movie Title : " + e.attributes["title"] 
}

# 以下将输出所有电影类型
xmldoc.elements.each("collection/movie/type") {
   |e| puts "Movie Type : " + e.text 
}

# 以下将输出所有电影描述
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-like Parsing:

SAX パーサー

は同じデータ ファイル movie.xml を処理します。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

XPath は XML ドキュメント内の情報を検索するための言語です (XPath チュートリアルを参照)。

XPath は XML パス言語であり、XML (標準ユニバーサル マークアップ言語のサブセット) ドキュメント内の特定の部分の位置を決定するために使用される言語です。 XPath は XML のツリー構造に基づいており、データ構造ツリー内のノードを検索する機能を提供します。

Ruby は、ツリーベースの解析 (ドキュメント オブジェクト モデル) である REXML の XPath クラスを通じて XPath をサポートします。

#!/usr/bin/ruby -w

require 'rexml/document'
include REXML

xmlfile = File.new("movies.xml")
xmldoc = Document.new(xmlfile)

# 第一个电影的信息
movie = XPath.first(xmldoc, "//movie")
p movie

# 打印所有电影类型
XPath.each(xmldoc, "//type") { |e| puts e.text }

# 获取所有电影格式的类型,返回数组
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 には 2 つの XSLT パーサーがあり、簡単に説明します。

Ruby-Sablotron

このパーサーは、Takahash 正義判事によって作成および保守されています。これは主に Linux オペレーティング システム用に書かれており、次のライブラリが必要です:

  • Sablot

  • Iconv

  • Expat

これらのライブラリは Ruby-Sablotron で見つけることができます。

XSLT4R

XSLT4R は Michael Neumann によって書かれています。 XSLT4R は、単純なコマンド ライン操作に使用され、サードパーティ アプリケーションで XML ドキュメントを変換するために使用できます。


XSLT4R には XMLScan 操作が必要で、100% Ruby モジュールである XSLT4R アーカイブが含まれています。これらのモジュールは、標準の 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 パーサーについては、REXML パーサーのドキュメントを参照してください。


  • XSLT4R は RAA ナレッジベースからダウンロードできます。