今野 英明
平成26年6月2日
XSLT スタイルシートは,XML 文書をどのような形に変換するかを,XSLT で記したものである 1。 なお,以下では XSLT スタイルシートを,単にスタイルシートと呼ぶことがある。
次の例は,前回の資料で紹介した,
変換対象となる XML 文書から,
XML 宣言やタグ等を除いた文字データ部分をすべて出力するスタイルシートである。
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" encoding="UTF-8" /> <xsl:template match="/"> <xsl:value-of select="/" /> </xsl:template> </xsl:stylesheet>
XSLT スタイルシート自体も整形式の XML 文書なので,スタイルシートにも XML の用語(XML 宣言や要素,属性等)や規則が当てはまることは紹介済みである。 それに加え,XSLT には独自の規則や役割を持つ要素があるので,上記のスタイルシートを元にこれらを説明する。
XSLT スタイルシートには xsl:sytlesheet 要素が必要である。 この要素の内容 (この次の行から終了タグ </xsl:stylesheet> の前まで) は,XSLT の規則に従って記述しなければならず, ここに記述される xsl: で始まる名前の要素には, XSLT に固有の意味や役割がある。
xsl:stylesheet 要素の子要素を,XSLT の用語でトップレベル要素 (top-level element) という。 トップレベル要素として記述できる要素は限定されており, この資料では xsl:output と xsl:template 要素のみを用いる。
xsl:output 要素は,変換結果の出力形式を定める。 ここでは出力形式を text 形式2, 出力の文字コードを UTF-8 としている。
xsl:template 要素は,変換元の XML 文書の中の
1. を指定するのが xsl:template 要素の match 属性であり, 属性値である / はルートノード(変換元の XML 文書全体)を指している。
2. は xsl:template 要素の内容として記述する。 この記述をテンプレートという。
テンプレートには,XSLT により意味が定められている要素や, その他の出力したい文字データ等を書いていく。
テンプレート内に記述した文字データは,基本的にはそのまま出力されるが, 空白文字(ブランクや改行)のみからなる文字データは出力されない。 出力の細かな振る舞いは xsl:output 要素の method 属性の指定によって変わる。
なお, 一つのスタイルシート内に match 属性値の異なる xsl:template 要素を複数記述することが可能であるが, 扱いが煩雑となるため, この資料で扱うスタイルシートでは, 属性 match="/" の xsl:template 要素を一つだけ記述することとする。
前回扱ったとおり,xsl:value-of 要素を用いると,変換対象となる XML 文書から, select 属性で指定したものを取り出すことができる。
XSLT スタイルシートでは,ロケーションパスをテンプレート内で使うが, その際の (初期の) カレントノードは xsl:template 要素の match 属性によって決まる。 例えば,<xsl:template match="/"> で始まるテンプレート内の初期カレントノードはルートノードである。 従って, このテンプレートでは / と . は等価であり, <xsl:value-of select="/" /> と <xsl:value-of select="." /> の出力は同じである。
テンプレート内にカレントノードを変更する XSLT の要素があれば, その中ではカレントノードに応じて相対ロケーションパスの基点が変わる 3。
<?xml version="1.0" ?> <ref> <book isbn="1111"> <title>Title1</title> <author>Author1</author> </book> <book> <title>Title2</title> <author>Author2</author> </book> <web> <title>Title3</title> </web> </ref>から
Title1 Title2のような出力を得るための XSLT テンプレートの書き方を紹介する。 このような出力はノードセット /reb/book に''反復処理''を施すことで得られる。
次に示すのは xsl:for-each を使ったスタイルシートの例である。
<?xml version="1.0" ?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" encoding="UTF-8" /> <xsl:template match="/"> <xsl:for-each select="/ref/book"> <xsl:value-of select="title" /> <xsl:value-of select="author" /> </xsl:for-each> </xsl:template> </xsl:stylesheet>これを XML 文書例に適用すると,次の出力が得られる4。
Title1Author1Title2Author2以下では,上記のスタイルシートのうち, xsl:for-each の動作に関わる部分について説明する。
出力を具体的に記述する部分(テンプレート)の始まり。
属性 match="/" の指定により, ルートノード (/) がカレントノードになるため, テンプレート内の初期の 相対ロケーションパスの基点 は / になる。
xsl:for-each 要素は, select 属性で指定されたノードの集まり(ノードセット) の中の各ノードを逐次カレントノードにしながら, 終了タグ </xsl:for-each> の前まで(要素の内容) に記述された処理を繰り返して行うものである。
XML 文書例を処理する場合, /ref/book は二つのノードに対応するので, xsl:for-each 要素の内容は 2 回反復処理される。
なお, この開始タグが現れた段階でのカレントノードは 直前の xsl:template 要素により / であるため, select 属性値を 相対ロケーションパスの ref/book や ./ref/book としても動作は変わらない。
xsl:for-each 要素による繰り返しの対象部分。 XML 文書例に対しては,次の動作が起きる。
このとき,xsl:value-of の select 属性値である title と author(相対ロケーションパスでの指定) は,絶対ロケーションパスでの /ref/book[1]/title および /ref/book[1]/author に等しい。
従って,xsl:value-of 要素によって, それらの文字列値である Title1 と Author1 が出力される。
反復 1 回目と同様に,xsl:value-of によって, /ref/book[2]/title および /ref/book[2]/author の文字列値である Title2 と Author2 が出力される。
xsl:for-each 要素の終了タグ。 xsl:for-each 要素が終わると,カレントノードは以前のもの (このスタイルシートでは xsl:template で指定された / )に戻る。 そのため,この後に相対ロケーションパスを含むテンプレート記述があれば, その起点は再度 / になる。
<xsl:for-each select="/ref/book"> <xsl:sort order="descending"/> <xsl:value-of select="title" /> <xsl:text> </xsl:text> <xsl:value-of select="author" /> <xsl:text> </xsl:text> </xsl:for-each>に変更して,XML 文書例を処理すると,出力は次のとおりとなる。
Title2 Author2 Title1 Author1この出力を得るために行っているテンプレート内の処理について,以下に記す。
例えば,先の <xsl:sort order="descending"/> は, 出力される文字列値が辞書の逆順(降順)になるように, xsl:for-each が処理するノードの順序を並べ換えるものである。
xsl:order 要素の動作を指定する属性は幾つかあり, order 属性は並べ換えの順を指定するものである。 属性値には ascending (昇順)か descending (降順)を指定する (order 属性を略すと昇順になる)。
他の属性としては,並べ換えに使うキーを指定する select 属性があり, <xsl:sort select="author" order="descending"/> とすれば,author ノードの文字列値が降順になるように, 処理順序の並べ換えが行われる。
テンプレートに記述した空白や改行を出力したければ, xsl:text 要素が使える。 例えば,内容が空白文字である xsl:text 要素
<xsl:text> </xsl:text>や
<xsl:text> </xsl:text>をテンプレート内に書けば,空白や改行を出力できる。