| この文書は、XSL Transformations (XSLT) 勧告の翻訳です。正式な版は、W3Cのサイトにある英語版であり、この翻訳ではありません。この翻訳は原文と技術的に等価なことを意図していますが、翻訳上の誤りが存在する可能性があります。
原文はつぎのURLで参照することができます。 http://www.w3.org/TR/1999/REC-xslt-19991116
|
Copyright © 1999 W3C® (MIT, INRIA, Keio), All Rights Reserved. 本文書には、W3C の責任範囲、商標、文書の使用、およびソフトウェアのライセンスに関する規定が適用される。
この仕様は XSLT のシンタックスとセマンティクスを定義する。XSLT とは、XML ドキュメントを別の XML ドキュメントに変換するための言語である。
XSLT は、XML 用のスタイルシート言語である XSL の一部として使用するために設計された。 XSL は XSLT の他に、フォーマットを指定するための XML のボキャブラリも含む。 XSL は XML ドキュメントのスタイルを指定する際に、そのドキュメントをフォーマットボキャブラリを使用する別の XML ドキュメントへ変換する方法を、XSLT を使用して記述する。
XSLT は XSL から独立して使用できるようにも設計されている。しかし、XSLT は 完全に汎用的な XML 変換用言語として使用するために設計されたわけではない。 むしろ設計の主眼は、XSL の一部として XSLT を 使用する際に必要となる変換処理を行うことにある。
この文書は、W3C メンバおよびその他の関係者が評価し、W3C 勧告として担当の責任者が承認したものである。 今後変更される可能性はなく、他の文書において参考資料として使用したり、あるいは基準となる参考文献として引用することができる。 勧告の策定にあたって W3C が担う役割は、この仕様を広く普及させることにある。 これにより Web の機能性と相互運用性を向上させることができる。
この仕様に関する正誤表は http://www.w3.org/1999/11/REC-xslt-19991116-errata で参照できる。
この仕様に関するコメントの宛先は xsl-editors@w3.org である。なお、コメントのアーカイブも利用できる。 XSL Transformationsを含む XSL に関する公開ディスカッションは、XSL-List メーリングリストで行われている。
この仕様の基準とバージョンは英語版のみであるが、 翻訳版を http://www.w3.org/Style/XSL/translations.html で参照できる。
W3C 勧告の一覧、およびその他の技術文書は http://www.w3.org/TR で入手できる。
この仕様は W3C のスタイルに関する活動 (W3C Style activity) の一環として作成されたものである。
この仕様は XSLT 言語のシンタックスとセマンティクスを定義するものである。 XSLT 言語による変換は、XML ネームスペース勧告 (Namespaces in XML Recommendation)[XML Names] に適合したウェルフォームド XML ドキュメント [XML] で表わされる。その XML ドキュメントには、XSLT で定義されているエレメントと XSLT では定義されていないエレメントのどちらも使用できる。 XSLT で定義されているエレメントは、特定の XML ネームスペースに所属することにより区別される ([2.1 XSLT ネームスペース] を参照)。この仕様では、この特定の XML ネームスペースを XSLT ネームスペースと呼ぶ。 従って、この仕様は XSLT ネームスペースのシンタックスとセマンティクスを定義するものである。
XSLT が表現する変換では、ソースツリーから結果ツリーへの変換処理上のルールを記述している。 この変換は、パターンをテンプレートに関連付けることによって実現する。 パターンはソースツリー内のエレメントと照合され、 テンプレートはインスタンス化されて結果ツリーの一部を生成する。 結果ツリーはソースツリーから独立している。 結果ツリーの構造は、ソースツリーの構造とまったく異なるものになることもある。 結果ツリーを構築する際には、ソースツリーのエレメントをフィルタしたり、エレメントの順序を変更したりできる。また、任意の構造を付加することも可能である。
XSLT が表現する変換をスタイルシートと呼ぶ。その理由は、XSLT を XSL のフォーマット用言語要素に変換する際に、この変換がスタイルシートとして機能するためである。
この文書では、XSLT スタイルシートを XML ドキュメントに関連付ける方法を規定しない。 XSL プロセッサは、[XML Stylesheet] で記述しているメカニズムをサポートしていることが望ましい。 このメカニズムまたは他のメカニズムが、1つの XML ドキュメントに同時に適用される複数の XSLT スタイルシートのシーケンスを生成した場合は、そのシーケンスに含まれる各メンバを順序どおりインポートした1つのスタイルシートを適用したときと同じ結果が得られるべきである ([2.6.2 スタイルシートのインポート] を参照)。
スタイルシートはテンプレートルールの集合を含んでいる。 テンプレートルールは2つの部分から成る。 1つはパターンであり、ソースツリーのノードと照合される。もう1つはインスタンス化が可能なテンプレートであり、結果ツリーの一部を構築する。 このような構成により、類似したソースツリー構造を持つ多様な文書に対してスタイルシートの適用が可能になる。
テンプレートは特定のソースエレメントに対してインスタンス化され、結果ツリーの一部を生成する。 テンプレートはリテラル結果エレメントの構造となるエレメントを含むことができる。 また、結果ツリーフラグメントを生成するインストラクションとなる XSLT ネームスペースのエレメントを含むことも可能である。 テンプレートをインスタンス化すると、各インストラクションが実行され、生成された結果ツリーフラグメントによる置き換えが行われる。 インストラクションは、子孫ソースエレメントを選択して処理することもある。子孫エレメントの処理では、適用可能なテンプレートルールを見つけ、そのテンプレートをインスタンス化することにより、結果ツリーフラグメントを生成する。 ただし、エレメントを処理するのは、インストラクションを実行により選択された場合だけである。 結果ツリーはルートノード用のテンプレートルールを見つけ、そのテンプレートをインスタンス化することにより構築される。
適用できるテンプレートルールの検索中に、所定のエレメントに対応できるパターンを持つテンプレートルールが複数見つかる場合がある。 このような場合でも、適用されるテンプレートルールは1つだけである。適用するテンプレートルールの決定方法については、[5.5 テンプレートルール競合時の解決] で解説している。
テンプレートは、1つだけでも強力な処理能力を持っている。たとえば、好きなだけ複雑な構造を生成することや、ソースツリー内の任意の場所から文字列の値を取り出すこと、ソースツリー内のエレメント出現回数に合わせて繰り返し構造を生成することなどが可能である。 結果ツリーの構造がソースツリーの構造から独立している単純な変換であれば、テンプレート1つだけでスタイルシートを構成することが可能であり、そのようなスタイルシートは完全な結果ツリーを得られるテンプレートとして機能する。 データを表わす XML ドキュメントの変換は、このような形式である場合が多い ([D.2 データ例] を参照)。 XSLT は、このようなスタイルシート用に簡略化したシンタックスを認めている ([2.3 スタイルシートとしてのリテラル結果エレメント] を参照)。
テンプレートをインスタンス化する際には、常にカレントノードとカレントノードリストを基準としてインスタンス化される。 カレントノードは、常にカレントノードリストのメンバである。 XSLT の操作の多くは、カレントノードと関連している。 カレントノードリストやカレントノードを変更するインストラクションは数種類しか存在しない ([5 テンプレートルール] および [8 繰り返し] を参照)。これらのインストラクションのいずれかをインスタンス化する際には、カレントノードリストは新しいノードのリストに変更され、新リストの各メンバが順番にカレントノードになる。インストラクションのインスタンス生成が終わると、カレントノードとカレントノードリストの内容は、インストラクションがインスタンス化される前の状態に戻る。
XSLT は [XPath] で定義された式言語を利用し、処理対象エレメントの選択、条件付きの処理、およびテキストの生成を行う。
XSLT は言語の拡張用に2つの「フック」を備えている。1つはテンプレートで使用するインストラクションエレメントの集合を拡張するフックであり、もう1つは XPath の式で使用する関数の集合を拡張するフックである。 これらのフックはどちらも XML ネームスペースを基盤としている。 このバージョンの XSLT では、フックの実装に関するメカニズムを定義していない。 [14 拡張] を参照のこと。
注: XSL 作業グループでは、この仕様の今後のバージョンまたは独立した仕様において、このメカニズムを定義する予定である。
XSLT で定義したエレメントのシンタックスを記述するためのエレメントシンタックス要約用ノテーションについては、[18 ノテーション] で解説している。
XSLT スタイルシートには、MIME メディア型の text/xml および application/xml[RFC2376] を使用すべきである。
XSLT スタイルシートには、あるメディア型が明示的に登録されるかもしれない。その場合、登録したメディア型も使用できる。
XSLT ネームスペースの URI は http://www.w3.org/1999/XSL/Transform である。
注: URI 内の 1999 は、W3C がこの URI を割り当てた年度を示している。
使用する XSLT のバージョンは、この数字ではなくアトリビュートにより指定される ([2.2 スタイルシートのエレメント] および [2.3 スタイルシートとしてのリテラル結果エレメント] を参照)。
XSLT プロセッサは XML ネームスペースのメカニズム [XML Names] を使用し、XML ネームスペースのエレメントとアトリビュートを認識しなければならない (must)。 XSLT ネームスペースのエレメントは、ソースドキュメント内ではなく、スタイルシート内でのみ認識される。 XSLT で定義したエレメントの全リストは [B エレメントのシンタックスの要約] に記載してある。 ベンダはエレメントやアトリビュートを追加し、XSLT ネームスペースを拡張してはならない (must)。 拡張を行う場所は XSLT ネームスペースではなく、別のネームスペース内でなければならない (must)。 インストラクション用エレメントを追加する際に使用するネームスペースは、[14.1 拡張エレメント] で解説している拡張エレメントのメカニズムを利用して識別されなければならない (must)。
この仕様では、XSLT ネームスペース内のエレメントを参照するプレフィックスとして xsl: を使用する。XSLT スタイルシートでは、そのプレフィックスを XSLT ネームスペースの URI にバインドするネームスペース宣言が存在すれば、どのようなプレフィックスも使用できる。
XSLT ネームスペースのエレメントは、アトリビュートの展開された名前 (expanded-name) が null 以外のネームスペース URI を持つ場合に限り、XSLT ネームスペースに所属しないアトリビュートを持ってもよい。 このようなアトリビュートが存在するために、XSLT エレメントとこの文書で定義する関数の動作を変更してはならない (must)。 従って、XSLT プロセッサはこのようなアトリビュートをいつでも無視できるし、そのネームスペース URI を認識できない場合には、エラーを生成せずにこれらのアトリビュートを無視しなければならない (must)。 このようなアトリビュートはユニークな識別子、最適化のヒント、ドキュメンテイションなどを指定できる。
このドキュメントでエレメント用に定義したアトリビュート以外に、null のネームスペース URI を持つ展開された名前が付けられたアトリビュート (プレフィックスのない名前が付けられたアトリビュート) が XSLT ネームスペースのエレメントに含まれる場合はエラーである。
注: XSLT のエレメント、アトリビュート、および関数の名前に関する表記規則は、小文字だけで名前を付けること、単語はハイフン (-) で区切ること、そして略語は XML や HTML などの関連言語のシンタックス内で記述済みの場合のみ使用すること、である。
<xsl:stylesheet
id = id
extension-element-prefixes = tokens
exclude-result-prefixes = tokens
version = number>
<!-- Content: (xsl:import*, top-level-elements) -->
</xsl:stylesheet>
<xsl:transform
id = id
extension-element-prefixes = tokens
exclude-result-prefixes = tokens
version = number>
<!-- Content: (xsl:import*, top-level-elements) -->
</xsl:transform>
スタイルシートは、XML ドキュメント内で xsl:stylesheet エレメントとして表される。
xsl:transform は、xsl:stylesheet の同義語として使用できる。
xsl:stylesheet エレメントには version アトリビュートを記述し、スタイルシートに必要な XSLT のバージョンを示さなければならない (must)。
このバージョンの XSLT では、アトリビュート値は 1.0 であるべきである。
この値が 1.0 以外の場合は、将来のバージョンと互換性のある (forwards-compatible) 処理モードが有効になる ([2.5 将来のバージョンと互換性のある処理] を参照)。
xsl:stylesheet エレメントは、以下の型のエレメントを含むことができる。
xsl:import
xsl:include
xsl:strip-space
xsl:preserve-space
xsl:output
xsl:key
xsl:decimal-format
xsl:namespace-alias
xsl:attribute-set
xsl:variable
xsl:param
xsl:template
xsl:stylesheet エレメントの子として現れるエレメントは、トップレベル (top-level) エレメントと呼ばれる。
以降にスタイルシートの構造の例を示す。省略記号 (...) のある場所は、アトリビュート値あるいはコンテンツが省略されていることを示している。
この例では、使用可能なエレメント型をそれぞれ1つずつ記述しているが、スタイルシートにはこれらのエレメントを1つも含めなくても、複数含めてもよい。
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:import href="..."/>
<xsl:include href="..."/>
<xsl:strip-space elements="..."/>
<xsl:preserve-space elements="..."/>
<xsl:output method="..."/>
<xsl:key name="..." match="..." use="..."/>
<xsl:decimal-format name="..."/>
<xsl:namespace-alias stylesheet-prefix="..." result-prefix="..."/>
<xsl:attribute-set name="...">
...
</xsl:attribute-set>
<xsl:variable name="...">...</xsl:variable>
<xsl:param name="...">...</xsl:param>
<xsl:template match="...">
...
</xsl:template>
<xsl:template name="...">
...
</xsl:template>
</xsl:stylesheet>
xsl:stylesheet エレメントの子の出現順序は、xsl:import エレメントとエラー回復の場合を除いて重要ではない。ユーザーはエレメントを自由に並べることができる。また、スタイルシートの生成ツールもエレメントの出現順序の制御機能を持つ必要はない。
さらに、エレメントの展開された名前が null 以外のネームスペース URI を持つ場合に限り、xsl:stylesheet エレメントは XSLT ネームスペースに所属しないエレメントを含んでもよい。
このようなトップレベルエレメントが存在しても、この文書で定義されたXSLT エレメントと関数の動作を変更してはならない (must)。たとえば、競合を解決するために異なるルールを使用する目的でトップレベルエレメントに xsl:apply-templates を指定することは許されない。
従って、XSLT プロセッサはこのようなトップレベルエレメントをいつでも無視できるし、ネームスペース URI を認識できない場合には、エラーを生成せずにこれらのトップレベルエレメントを無視しなければならない (must)。
これらのエレメントは以下のようなデータを提供できる。
拡張エレメントまたは拡張関数が使用する情報 ([14 拡張] を参照)
結果ツリーの処理に関する情報
ソースツリーの取得方法に関する情報
スタイルシートに関するメタデータ
スタイルシート用に構造化されたドキュメント
ルートノード用のテンプレート1つだけで構成するスタイルシートでは、簡略化したシンタックスを使用できる。
このスタイルシートは、リテラル結果エレメントのみで構成することができる ([7.1.1 リテラル結果エレメント] を参照)。
このようなスタイルシートは、そのリテラル結果エレメントを含む、マッチパターンが / のテンプレートルールを1つだけを含む xsl:stylesheet エレメントを持つスタイルシートと同等である。
以下に例を示す。
<html xsl:version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/xhtml1/strict">
<head>
<title>Expense Report Summary</title>
</head>
<body>
<p>Total Amount: <xsl:value-of select="expense-report/total"/></p>
</body>
</html>
この記述は以下の記述と同じ意味を持つ。
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/xhtml1/strict">
<xsl:template match="/">
<html>
<head>
<title>Expense Report Summary</title>
</head>
<body>
<p>Total Amount: <xsl:value-of select="expense-report/total"/></p>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
スタイルシートのドキュメントエレメントであるリテラル結果エレメントには、スタイルシートに必要な XSLT のバージョンを示す xsl:version アトリビュートを指定しなければならない (must)。このバージョンの XSLT では、アトリビュート値は 1.0 であるべきである。また、この値は Number でなければならない (must)。その他のリテラル結果エレメントについても、xsl:version アトリビュートを指定できる。
xsl:version アトリビュートの値が 1.0 以外の場合は、将来のバージョンと互換性のある (forwards-compatible) 処理モードが有効になる ([2.5 将来のバージョンと互換性のある処理] を参照)。
スタイルシートとして使用するリテラル結果エレメントのコンテンツとして許されるのは、スタイルシート内にリテラル結果エレメントが使われた場合と同様である。 従って、スタイルシートとして使用するリテラル結果エレメントは、トップレベルエレメントを含むことはできない。
XML ドキュメントを処理する際に、XSLT プロセッサを使用して XSLT スタイルシートとして処理する必要があるかどうかは、XML ドキュメント自体を調査しなければわからない場合もある。 簡略化したシンタックスを使用する場合には、この処理がより難しくなる。
注: たとえば、別の XML 言語 (AXL) もドキュメントエレメント上にaxl:versionと指定し、ある XML ドキュメントが AXL プロセッサによる処理が必要な AXL ドキュメントであることを指示している可能性もある。1つの文書にaxl:versionアトリビュートとxsl:versionアトリビュートの両者が含まれていると、その文書を XSLT プロセッサと AXL プロセッサのどちらで処理すべきかあいまいになる。
そのため、このような状況で使われる可能性がある XSLT スタイルシートには、簡略化したシンタックスを使用すべきではない。
たとえば、このような状況は、MIME メディア型を使ってメッセージの処理方法を決定する受信者に対して、text/xml または application/xml の MIME メディア型を持つメッセージとして XSLT スタイルシートが送信された場合に発生し得る。
内部 XSLT オブジェクトの名前は、QName として指定される。具体的には、名前付きテンプレート ([6 名前付きテンプレート] を参照)、モード ([5.7 モード] を参照)、アトリビュートの集合 ([7.1.4 名前付きアトリビュートの集合] を参照)、キー ([12.2 キー] を参照)、デシマルフォーマット (decimal-format) ([12.3 数値のフォーマット] を参照)、変数、またはパラメータ ([11 変数とパラメータ]) などである。 名前にプレフィックスがある場合、そのプレフィックスは、名前が現れるアトリビュートに対して有効なネームスペース宣言を使って URI リファレンスに展開される。 展開された名前 (expanded-name) は、名前のローカルパートと URI リファレンス (null もありうる) から構成され、オブジェクトの名前に使用される。 デフォルトのネームスペースは、プレフィックスのない名前には使用されない。
エレメントは次のいずれかの場合に該当すると、自分自身とそのアトリビュート、および自分の子孫とそれらのアトリビュートに対して将来のバージョンと互換性のある処理モードを有効にする。version アトリビュートの値が 1.0 以外の xsl:stylesheet エレメントの場合、リテラル結果エレメントであって xsl:version アトリビュートを持ち、その値が 1.0 以外のエレメントの場合、あるいは、リテラル結果エレメントであって xsl:version アトリビュートを持たず、簡略化したシンタックス ([2.3 スタイルシートとしてのリテラル結果エレメント] を参照) を使用するスタイルシートのドキュメントエレメントの場合である。
リテラル結果エレメントが xsl:version アトリビュートを持ち、その値が 1.0 の場合は、自分自身とそのアトリビュート、および自分の子孫とそのアトリビュートに対する将来のバージョンと互換性のある処理モードは無効になる。
将来のバージョンと互換性のある処理モードでエレメントを処理すると、以下の結果が得られる。
処理対象がトップレベルエレメントであって、XSLT 1.0 においてトップレベルエレメントとして使用できないエレメントであれば、そのエレメントはコンテンツとともに無視されなければならない (must)。
処理対象がテンプレート内のエレメントであって、XSLT 1.0 においてテンプレート内に現れてはならないエレメントであれば、エレメントをインスタンス化しない場合にエラーを通知してはならない (must)。また、エレメントをインスタンス化した場合、XSLTは [15 フォールバック] で解説しているようにエレメントのフォールバックを実行しなければならない (must)。
処理対象のエレメントが XSLT 1.0 で許されていないアトリビュートを持つ場合、または XSLT 1.0 で許されていない値を取るオプションのアトリビュートを持つ場合は、そのアトリビュートを無視しなければならない (must)。
従って、以下のスタイルシートには、この仕様で定義していない XSLT ネームスペースのエレメントが含まれるが、XSLT 1.0 プロセッサであれば、このスタイルシートをエラーを起こさず処理できなければならない (must)。
<xsl:stylesheet version="1.1"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:choose>
<xsl:when test="system-property('xsl:version') >= 1.1">
<xsl:exciting-new-1.1-feature/>
</xsl:when>
<xsl:otherwise>
<html>
<head>
<title>XSLT 1.1 required</title>
</head>
<body>
<p>Sorry, this stylesheet requires XSLT 1.1.</p>
</body>
</html>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
注: あるスタイルシートが 1.0 以降のバージョンの XSL に導入されているトップレベルエレメントに完全に依存する場合、そのスタイルシートのxsl:messageエレメントにterminate="yes"([13 メッセージ] を参照) を指定すると、以前のバージョンの XSL を実装する XSLT プロセッサがトップレベルエレメントを無視するときには必ず警告を発するようにできる。 以下に例を示す。<xsl:stylesheet version="1.5" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:important-new-1.1-declaration/> <xsl:template match="/"> <xsl:choose> <xsl:when test="system-property('xsl:version') < 1.1"> <xsl:message terminate="yes"> <xsl:text>Sorry, this stylesheet requires XSLT 1.1.</xsl:text> </xsl:message> </xsl:when> <xsl:otherwise> ... </xsl:otherwise> </xsl:choose> </xsl:template> ... </xsl:stylesheet>
ある式が将来のバージョンと互換性のあるモードで処理されるアトリビュートに現れる場合、XSLT プロセッサは式のエラーから次のように回復しなければならない (must)。
その式が XPath の文法上許可されたシンタックスに適合しない場合、式を実際に評価しないのであればエラーを通知してはならない (must)。
その式が、プレフィックスのない名前を持ち、XSLT ライブラリの一部でない関数を呼び出す場合、関数が実際に呼び出されないのであればエラーを通知してはならない (must)。
その式が、XSLT では許されない数量または型の引数を持つ関数を呼び出す場合、関数が実際に呼び出されないのであればエラーを通知してはならない (must)。
XSLT には、スタイルシートを結合するメカニズムが2種類ある。
<!-- Category: top-level-element -->
<xsl:include
href = uri-reference />
XSLT スタイルシートは xsl:include エレメントを記述することにより、別の XSLT スタイルシートを取り込むことができる。xsl:include エレメントは href アトリビュートを持っている。このアトリビュート値は、インクルードするスタイルシートを識別するための URI リファレンスである。相対 URI は、xsl:include エレメントのベース URIを基準に解決される ([3.2 ベース URI] を参照)。
xsl:include エレメントは、トップレベルエレメントとしてのみ使用できる。
このインクルード処理は、XML のツリーレベルで行われる。href アトリビュートの値によって位置を特定したリソースは、XML ドキュメントとしてパースされ、XML ドキュメント側の xsl:stylesheet エレメントの子が、インクルードするドキュメント側の xsl:include エレメントを置き換える。
テンプレートのルールや定義が含まれていても、それらの処理方法には影響を与えない。
インクルードされるスタイルシートでは、[2.3 スタイルシートとしてのリテラル結果エレメント] で解説している簡略化したシンタックスを使用してもよい。
インクルードされるスタイルシートは、xsl:stylesheet エレメントと同様に扱われる。
スタイルシートが自分自身を直接的または間接的にインクルードする場合は、エラーとなる。
注: スタイルシートを複数回インクルードする場合、定義の重複によってエラーを発生する可能性がある。 間接的にインクルードされている場合には、このような複数のインクルードは、より見つけづらくなる。 たとえば、スタイルシート B がスタイルシート A をインクルードし、スタイルシート C がスタイルシート A をインクルードしてから、スタイルシート D がスタイルシート B とスタイルシート C の両者をインクルードすると、A は D 内に間接的に2回インクルードされることになる。 B、C、および D のすべてが独立したスタイルシートとして使用される場合は、A からインクルードした内容を除くすべての B の内容を別のスタイルシート B' に分離し、B が B' と A をインクルードする形に変更する。同様に C を分離してから、D が A、B'、および C' をインクルードするように変更することで、エラーを回避できる。
<xsl:import
href = uri-reference />
XSLT スタイルシートに、xsl:import エレメントを使用して別の XSLT スタイルシートをインポートしてもよい。スタイルシートのインポートは、スタイルシートのインクルード ([2.6.1 スタイルシートのインクルード] を参照) と同様だが、インポートする側のスタイルシートに含まれる定義とテンプレートルールが、インポートされる側のスタイルシートに含まれる定義とテンプレートルールより優先される点が異なる。この点に関する詳細を次に解説する。
xsl:import エレメントは、href アトリビュートを持っている。このアトリビュート値は、インポートするスタイルシートを識別するための URI リファレンスである。
相対 URI は、xsl:import エレメントのベース URIを基準に解決される ([3.2 ベース URI] を参照)。
xsl:import エレメントは、トップレベルエレメントとしてのみ使用できる。xsl:import エレメントは、xsl:include エレメントを含め、xsl:stylesheet エレメントのすべての子よりも優先されなければならない (must)。
xsl:include でスタイルシートをインクルードした場合、インクルードされるドキュメント内の xsl:import エレメントはすべて、インクルードする側のドキュメント内に既存のすべての xsl:import エレメントの後ろに移動される。
以下に例を示す。
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:import href="article.xsl"/>
<xsl:import href="bigfont.xsl"/>
<xsl:attribute-set name="note-style">
<xsl:attribute name="font-style">italic</xsl:attribute>
</xsl:attribute-set>
</xsl:stylesheet>
xsl:import エレメントを含む1つのスタイルシートの処理中に出現した xsl:stylesheet エレメントは、1つのインポートツリーを形成するような形で扱われる。
インポートツリー内では、各 xsl:stylesheet エレメントが、スタイルシートに含まれる xsl:import エレメントごとに1つの import を子として持つ。
xsl:include エレメントはすべて、インポートツリーの構築以前に解決される。
ある xsl:stylesheet エレメントのインポートツリー内におけるインポートの優先順位は、同一ツリー内で深さ優先の走査で自分よりも後の順位になるような xsl:stylesheet エレメント (つまり、自分の import ツリー上の子よりも後にその xsl:stylesheet が処理される場合) 、より下位に定義される。
各定義と各テンプレートルールのインポートの優先順位は、それらを含む xsl:stylesheet エレメントによって決められる。
以下のような場合を想定する。
スタイルシート A が、スタイルシート B と C をこの順序でインポートする。
スタイルシート B がスタイルシート D をインポートする。
スタイルシート C がスタイルシート E をインポートする。
この場合、インポートの優先順位は、低い側から D、B、E、C、A となる。
注:xsl:importエレメントは、すべての定義とテンプレートの手前に現れなくてはならないため、xsl:importエレメントに遭遇した時点でインポートされるスタイルシートを処理する実装は、インポートの優先順位が高まる順に、定義とテンプレートに遭遇することになる。
通常の場合、インポートの優先順位の高い定義やテンプレートルールは、インポートの優先順位の低い定義やテンプレートルールよりも優先される。 詳細は、各種類の定義およびテンプレートルールについてそれぞれ定義されている。
スタイルシートが、自分自身を直接的または間接的にインポートする場合はエラーとなる。
これ以外の場合は、特定の URI を持つスタイルシートが複数の場所にインポートされても特別に扱われない。
インポートツリーは、インポートされた場所ごとに、別々の xsl:stylesheet を持つ。
注: xsl:apply-imports を使用した場合 ([5.6 テンプレートルールのオーバーライド (上書き)] を参照) の動作は、そのスタイルシートが最高のインポートの優先順位を持っている場所だけにインポートされた場合の動作とは異なることがある。
通常の場合、XSLT スタイルシートは、ドキュメントエレメントとして xsl:stylesheet エレメントを持つ完全な XML ドキュメントである。
ただし、XSLT スタイルシートを別のリソースに埋め込むこともできる。
スタイルシートの埋め込みには、次の2つの形式がある。
xsl:stylesheet エレメントが、ドキュメントエレメント以外の形で XML 文書内に現れる形式。
2つ目の形式の埋め込みが容易にできるように xsl:stylesheet エレメントには、ユニークな識別子を示す ID 型のアトリビュートを指定できる。
注: ここで説明した ID 型のアトリビュートを XPath の id 関数と同時に使用するには、このアトリビュートが ID 型であることが DTD 内で実際に宣言されていなければならない (must)。
以下の例は、ドキュメントに独自のスタイルシートを含むことを可能にするプロセッシングインストラクション xml-stylesheet [XML Stylesheet] の使用方法を示している。
URI リファレンスには、xsl:stylesheet エレメントの位置を特定するフラグメント識別子を備えた参照 URI を使用する。
<?xml-stylesheet type="text/xml" href="#style1"?>
<!DOCTYPE doc SYSTEM "doc.dtd">
<doc>
<head>
<xsl:stylesheet id="style1"
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:import href="doc.xsl"/>
<xsl:template match="id('foo')">
<fo:block font-weight="bold"><xsl:apply-templates/></fo:block>
</xsl:template>
<xsl:template match="xsl:stylesheet">
<!-- ignore -->
</xsl:template>
</xsl:stylesheet>
</head>
<body>
<para id="foo">
...
</para>
</body>
</doc>
注: ドキュメントに埋め込まれたスタイルシート、またはそのような埋め込まれたスタイルシート内にインクルードあるいはインポートされる可能性があるスタイルシートには、通常、xsl:stylesheet エレメントを無視するようなテンプレートルールを含める必要がある。
XSLT で使用するデータモデルには、XPath で使用するデータモデルの他に、この章で解説するデータモデルもある。 XSLT は、同一のデータモデルを使用するソースドキュメント、結果ドキュメント、およびスタイルシートドキュメント上で処理を行う。 同一のツリーを持つ2つの XML ドキュメントであれば、XSLT は同様に扱う。
スタイルシート内のプロセッシングインストラクションとコメントは無視される。 つまり、スタイルシートを表現するツリー内にプロセッシングインストラクションノードとコメントノードのどちらも持たないかのように、そのスタイルシートを扱うのである。
ルートノードの子に関する通常時の制約は、結果ツリーに対して緩和される。 結果ツリーでは、エレメントノードが子として持ちうるノードであれば、任意の順序で子ノードを持つことができる。 特に、結果ツリーはテキストノードの子や、任意の数のエレメントノードの子を持ってもよい。 XML 出力メソッド ([16 出力] を参照) を使って書き出された場合、結果ツリーがウェルフォームド XML ドキュメントにならない可能性もある。その場合でも結果ツリーは、常にウェルフォームドな外部一般パース対象エンティティではある。
ソースツリーがウェルフォームド XML ドキュメントをパースして生成された場合、このソースツリーのルートノードは、テキストノードの子は持たず、エレメントの子を1つだけ持つという通常時の制約を自動的に満たす。 DOM を使用するなど、他の方法でソースツリーを生成する場合には、結果ツリーの場合と同様に、ソースツリーに対しても通常時の制約が緩和される。
各ノードもベース URI と呼ばれる関連付けられた URI を持つ。ベース URI は、相対 URI を表すアトリビュート値を絶対 URI に解決するために使用される。 エレメントまたはプロセッシングインストラクションが外部エンティティに現れる場合、そのエレメントやプロセッシングインストラクションのベース URI は、その外部エンティティの URI である。その他の場合には、ベース URI は、ドキュメントのベース URI である。 ドキュメントノードのベース URI は、ドキュメントエンティティの URI である。 テキストノード、コメントノード、アトリビュートノード、またはネームスペースノードのベース URI になるのは、各ノードの親のベース URIである。
ルートノードは、ドキュメントの DTD で宣言されたパース対象外エンティティそれぞれに URI を提供するマッピング情報を持っている。 URI はエンティティ宣言内で指定されたシステム識別子および公開識別子 (public identifier) から生成される。 XSLT プロセッサはシステム識別子で指定された URI の代わりに、公開識別子を使用してエンティティの URI を生成することもできる。 XSLT プロセッサは、URI 生成に公開識別子を使用しない場合、システム識別子を使用しなければならない (must)。システム識別子が相対 URI である場合、エンティティ宣言を含むリソースの URI をベース URI として使い、相対 URI を絶対 URI に解決しなければならない (must)[RFC2396]。
ソースドキュメントやスタイルシートドキュメントのツリーが構築された後、XSLT が他の処理を行う前に、一部のテキストノードが削除される。 テキストノードが空白文字だけを含む場合を除けば、テキストノードは削除されない。 テキストノードを削除すると、ツリーからそのテキストノードが削除される。 削除処理は、空白を保存しなくてはならない (must) エレメント名の集合を、入力として取る。 削除処理は、スタイルシートとソースドキュメントの両方に適用されるが、空白を保存すべきエレメント名の集合は、スタイルシートとソースドキュメントのそれぞれについて決定される。
下記のいずれかに該当するテキストノードは保存される。
テキストノードの親のエレメント名が、空白を保存すべきエレメント名の集合内に存在する。
テキストノードが、空白以外の文字を少なくとも1つ含んでいる。 XML 内の空白文字は、#x20、#x9、#xD、または #xA である。
テキストノードの祖先エレメントが、値がpreserve の xml:space アトリビュートを持ち、その祖先エレメントよりも近い位置に、値がdefault の xml:space を持つ別の祖先エレメントがない。
これらの場合以外は、テキストノードを削除する。
xml:space アトリビュートは、ツリーから削除されない。
注: これは、xml:space アトリビュートがリテラル結果エレメントに指定されている場合には、結果に含まれることを意味する。
スタイルシートでは、空白を保存すべきエレメント名の集合を構成するのは、xsl:text だけである。
<!-- Category: top-level-element -->
<xsl:strip-space
elements = tokens />
<!-- Category: top-level-element -->
<xsl:preserve-space
elements = tokens />
ソースドキュメントでは、空白を保存すべきエレメント名の集合を、トップレベルエレメントである xsl:strip-space と xsl:preserve-space によって定義する。これらのエレメントはそれぞれ、空白で区切られた NameTest のリストを値に取る elements アトリビュートを持つ。
最初の段階では、空白を保存すべきエレメント名の集合には、すべてのエレメント名が含まれる。
xsl:strip-space エレメント内の NameTest とマッチしたエレメント名は、空白を保存すべきエレメント名の集合から削除される。
xsl:preserve-space エレメント内の NameTest とマッチしたエレメント名は、空白を保存すべきエレメント名の集合に追加される。
あるエレメントが NameTest にマッチするのは、そのエレメントに対して NameTest が XPath のノードテストとして真となる場合だけである。
xsl:strip-space エレメントと xsl:preserve-space エレメントとの間でマッチした内容が競合する場合、テンプレートルール競合時と同じ方法で解決する ([5.5 テンプレートルール競合時の解決] を参照)。
従って、特定のエレメント名に対して有効なマッチング結果を以下のように判定する。
はじめに、他のマッチング結果より低いインポートの優先順位を持つマッチング結果を無視する。
次に、マッチング結果に使用した NameTest のデフォルトの優先度が、他のマッチング結果のNameTest のデフォルトの優先度より低いものを無視する。
上記の判定後にも複数のマッチング結果が残る場合はエラーである。XSLT プロセッサは、エラーを通知してもよい。エラーを通知しない場合には、判定後に残ったマッチング結果からスタイルシートの最後方に現れるものを選択し、エラーから回復しなければならない (must)。
XSLT は、XPath [XPath] で定義する式言語を使用する。XSLT では、以下の例を含め、さまざまな用途に式を使用する。
式は、XPath の プロダクション Expr にマッチしなければならない (must)。
式は XSLT で定義するエレメントに関する特定のアトリビュート値として、アトリビュート値テンプレート内に中括弧 ({}) で囲んで記述される。
XSLT では、最も外側の式 (つまり、他の式の一部でない式) は、以下のようにコンテキストを取得する。
コンテキストノードはカレントノードになる。
コンテキストの位置 (position) は、カレントノードリストに含まれるカレントノードの位置になる。最初の位置を1で表す。
コンテキストサイズは、カレントノードリストのサイズになる。
変数のバインディングは、式が現れるアトリビュートを持つエレメントのスコープに含まれるバインディングである ([11 変数とパラメータ] を参照)。
ネームスペース宣言の集合は、式が現れるアトリビュートを持つエレメントのスコープに含まれるものと同じである。この集合には、XML ネームスペース勧告 (XML Namespaces Recommendation) [XML Names] が必要とする、暗黙的に示されたプレフィックス xml の宣言も含まれる。デフォルトのネームスペース (xmlns を用いて宣言されたもの) は、この集合の一部ではない。
関数のライブラリは、コア関数ライブラリ、[12 追加の関数] で定義された追加の関数と、[14 拡張] で解説している拡張関数から構成される。これら以外の関数の呼び出しを含む式はエラーである。
ソースノードのリストを処理すると、結果ツリーフラグメントが生成される。 結果ツリーは、ルートノードだけを含むリストを処理することによって構築される。 ソースノードのリストは、リスト内の各メンバを順に処理して生成された結果ツリーの構造を追加する形で処理されていく。 ノードの処理は、そのノードにマッチするパターンを持つテンプレートルールをすべて見つけ、その中から最適なテンプレートルールを選択することによって行われる。次に、選択したルールのテンプレートを、カレントノードとなっているノード、およびカレントノードリストとなっているソースノードのリストを使ってインスタンス化する。 テンプレートは通常、次に処理するソースノードのリストを選択するための命令を含んでいる。 このようなマッチング、インスタンス化、選択という処理行程は、処理対象に選ばれる新しいソースノードがなくなるまで続けられる。
この処理モデルを用いて処理した場合と同じ結果が得られるならば、実装はどのようにソースドキュメントを処理してもよい。
テンプレートルールは、パターンを使用して適用先のノードを識別する。 パターンは、テンプレートルール内で使用されるとともに、番号付け ([7.7 番号付け] を参照) とキーの宣言 ([12.2 キー] を参照) を行う際にも使用される。 パターンはノードに関する条件の集合を指定する。条件を満たすノードがそのパターンにマッチするノードであり、条件を満たさないノードがそのパターンにマッチしないノードとなる。 パターンのシンタックスは、式のシンタックスのサブセットである。 特に、一定の制約を満たすロケーションパスは、パターンとしても使用できる。 パターンとして使用可能な式は、評価されると常にノード集合型 (node-set) オブジェクトになる。 ノードがパターンにマッチするのは、パターンを式として使い、いくつかの候補になるコンテキストを評価した結果に、そのノードをメンバとして含む場合である。候補になるコンテキストとは、コンテキストノードが、照合対象となっているノードかその祖先ノードの1つであるようなコンテキストである。
以下にパターンの例を示す。
para は、すべての para エレメントにマッチする。
* は、すべてのエレメントにマッチする。
chapter|appendix は、すべての chapter エレメントおよびすべての appendix エレメントにマッチする。
olist/item は、親エレメントに olist を持つすべての item エレメントにマッチする。
appendix//para は、祖先エレメントに appendix を持つすべての para エレメントにマッチする。
/ は、ルートノードにマッチする。
text() は、すべてのテキストノードにマッチする。
processing-instruction() は、すべてのプロセッシングインストラクションにマッチする。
node() は、アトリビュートノードおよびルートノードを除くすべてのノードにマッチする。
id("W11") は、ユニーク ID として W11 を持つエレメントにマッチする。
para[1] は、親の para という子エレメントの中で最初である、すべての para エレメントにマッチする。
*[position()=1 and self::para] は、親に対して最初の子エレメントである、すべての para エレメントにマッチする。
para[last()=1] は、親に対して唯一の para という子エレメントである、すべての para エレメントにマッチする。
items/item[position()>1] は、親に items エレメントを持ち、この親の item という子エレメントの中で最初ではない、すべての item エレメントにマッチする。
item[position() mod 2 = 1] は、親の item という子エレメントの中で奇数番目である、すべての item エレメントにマッチする。
div[@class="appendix"]//p は、class アトリビュートを持ち、その値が appendix である div エレメントを祖先とする、すべての p エレメントにマッチする。
@class は、すべての class アトリビュートにマッチする (class アトリビュートを持つエレメントのことではない)。
@* は、すべてのアトリビュートにマッチする。
パターンは、Pattern の文法に適合しなければならない (must)。Pattern は、| で区切られたロケーションパスのパターンの集合である。
ロケーションパスのパターンとは、すべてのステップで child 基準点または attribute 基準点のみを使用するロケーションパスである。
パターンでは、descendant-or-self 基準点を使用してはならない (must) が、演算子 / と同様に演算子 // を使用してもよい。
ロケーションパスのパターンを、リテラルな引数を取る id 関数や key 関数の呼び出しで始めることができる。
パターンの述語には、ロケーションパスで述語を使う場合と同様に、任意の式を使用できる。
| [1] | Pattern | ::= | LocationPathPattern | |
| | Pattern '|' LocationPathPattern | ||||
| [2] | LocationPathPattern | ::= | '/' RelativePathPattern? | |
| | IdKeyPattern (('/' | '//') RelativePathPattern)? | ||||
| | '//'? RelativePathPattern | ||||
| [3] | IdKeyPattern | ::= | 'id' '(' Literal ')' | |
| | 'key' '(' Literal ',' Literal ')' | ||||
| [4] | RelativePathPattern | ::= | StepPattern | |
| | RelativePathPattern '/' StepPattern | ||||
| | RelativePathPattern '//' StepPattern | ||||
| [5] | StepPattern | ::= | ChildOrAttributeAxisSpecifier NodeTest Predicate* | |
| [6] | ChildOrAttributeAxisSpecifier | ::= | AbbreviatedAxisSpecifier | |
| | ('child' | 'attribute') '::' |
パターンの定義がノードにマッチするのは、そのコンテキストについてパターンを式として評価したときに、結果として得られるノード集合のメンバにノードを含むような、候補になるコンテキストが存在する場合に限られる。 ノードが照合される際に、候補となるコンテキストとは、照合対象のノードまたはそのノードの祖先であるコンテキストノードと、そのコンテキストノードだけを含むコンテキストノードリストを持つ。
たとえば、p がすべての p エレメントにマッチするのは、どの p の場合にも、 p エレメントの親をコンテキストとして式 p を評価したときに、その結果のノード集合にメンバとして p エレメントを含むからである。
注: 上記の説明は、p エレメントがドキュメントエレメントであっても、文書のルートがドキュメントエレメントの親であるためにあてはまる。
パターンのセマンティクスは式の評価の視点から間接的に指定されるが、パターンの意味は式の評価の視点で考えなくとも直接容易に理解できる。
パターン内の | は、選択肢を示している。
1つ以上の | で区切られた選択肢を持つパターンは、選択肢のいずれかがマッチすると、パターンとしてマッチする。
パターンが、/ または // で区切られた StepPattern (ステップパターン) の連続によって構成されている場合、パターンの照合は右から左に向かって行われる。
パターンがマッチするのは、右端の StepPattern がマッチし、残りのパターンにも適切なエレメントがマッチする場合だけである。区切り記号が / であれば、親だけが適切なエレメントである。区切り記号が // であれば、すべての祖先が適切なエレメントとなる。
child 基準点を使用する StepPattern は、ノードに対する NodeTest が真であり、そのノードがアトリビュートノードでない場合にマッチする。
attribute 基準点を使用する StepPattern は、ノードに対する NodeTest が真であり、そのノードがアトリビュートノードならばマッチする。
[] が記述されている場合には、コンテキストノードとして照合されるノードと、コンテキストノードリストとして NodeTest にマッチするコンテキストノードの兄弟について、StepPattern 内に含まれる最初の PredicateExpr が評価される。ただし、照合されるノードがアトリビュートノードの場合は異なり、照合されるアトリビュートとして同じ親を持ち、NameTest にマッチするすべてのアトリビュートがコンテキストノードリストとなる。
以下に例を示す。
appendix//ulist/item[position()=1]
上記の記述は、以下の条件がすべて真となる場合にのみ、ノードにマッチする。
NodeTest item がそのノードに対して真であり、そのノードがアトリビュートではないこと。つまり、そのノードが item エレメントである場合。
そのノードをコンテキストノードとし、そのノードのitem エレメントである兄弟をコンテキストノードリストとして、 PredicateExpr である position()=1 を評価すると真になる場合。
そのノードが、appendix//ulist にマッチする親を持つ場合。これは、その親が祖先エレメントに appendix を持つ ulist エレメントの場合に真となる。
<!-- Category: top-level-element -->
<xsl:template
match = pattern
name = qname
priority = number
mode = qname>
<!-- Content: (xsl:param*, template) -->
</xsl:template>
テンプレートルールは、xsl:template エレメントによって指定される。
match アトリビュートは、ソースノードやルールの適用先ノードを識別する Pattern である。
match アトリビュートは、xsl:template エレメントが name アトリビュートを含む場合を除いて必須である ([6 名前付きテンプレート] を参照)。
match アトリビュートの値が VariableReference を含む場合はエラーとなる。
xsl:template エレメントのコンテンツは、テンプレートルールを適用したときにインスタンス化されるテンプレートである。
たとえば、ある XML ドキュメントが以下の記述を持つとする。
This is an <emph>important</emph> point.
以下のテンプレートルールは、上記の emph エレメントにマッチして、font-weight プロパティが bold のフォーマッティングオブジェクト fo:inline-sequence を生成する。
<xsl:template match="emph">
<fo:inline-sequence font-weight="bold">
<xsl:apply-templates/>
</fo:inline-sequence>
</xsl:template>
注: この仕様の記述例では、ネームスペースhttp://www.w3.org/1999/XSL/Formatを示すためにプレフィックスfo:を使用している。これは [XSL] で定義するフォーマッティングオブジェクトのネームスペースである。
次の項で解説しているように、xsl:apply-templates エレメントはソースエレメントの子を再帰的に処理する。
<!-- Category: instruction -->
<xsl:apply-templates
select = node-set-expression
mode = qname>
<!-- Content: (xsl:sort | xsl:with-param)* -->
</xsl:apply-templates>
以下の例では、1つのchapter エレメントに対して1つのブロックを作成し、次に直下の子を処理する。
<xsl:template match="chapter">
<fo:block>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
select アトリビュートがない場合、 xsl:apply-templatesインストラクションは、テキストノードを含むカレントノードのすべての子を処理する。ただし、[3.4 空白の削除] で解説しているとおり、削除したテキストノードは処理しない。
あるエレメントについて、空白だけのノードの削除が有効になっていない場合は、エレメントのコンテンツに含まれるすべての空白をテキストとして処理する。従って、position 関数が返すのと同様に、子エレメント間の空白は、ある子エレメントの位置を決定する際にカウントされる。
select アトリビュートを使用すると、すべての子を処理するのではなくて、式で選択したノードだけを処理できる。
select アトリビュートの値は、式である。
その式は評価した結果、ノード集合でなくてはならない (must)。
選択したノード集合の処理は、ソート ([10 ソート] を参照) の指定がなければドキュメント順に行われる。
以下の例では、author-group の子であるすべての author を処理している。
<xsl:template match="author-group">
<fo:inline-sequence>
<xsl:apply-templates select="author"/>
</fo:inline-sequence>
</xsl:template>
以下の例では、author-group の子である author のすべての given-nameを処理している。
<xsl:template match="author-group">
<fo:inline-sequence>
<xsl:apply-templates select="author/given-name"/>
</fo:inline-sequence>
</xsl:template>
以下の例では、book エレメントの子孫エレメントであるすべての heading を処理している。
<xsl:template match="book">
<fo:block>
<xsl:apply-templates select=".//heading"/>
</fo:block>
</xsl:template>
また、カレントノードの子孫でないエレメントも処理できる。以下の例では、department エレメントが子エレメント group および子孫エレメント employee を持つと仮定する。従業員の部署を見つけ、次に department の子である group を処理する。
<xsl:template match="employee">
<fo:block>
Employee <xsl:apply-templates select="name"/> belongs to group
<xsl:apply-templates select="ancestor::department/group"/>
</fo:block>
</xsl:template>
複数の xsl:apply-templates エレメントを1つのテンプレート内で使用すると、再順序付けを簡略化できる。以下の例では、2つの HTML テーブル (table) を作成する。1つ目のテーブルには国内販売高 (domestic sales)、2つ目のテーブルには海外販売高 (foreign sales) のデータを挿入する。
<xsl:template match="product">
<table>
<xsl:apply-templates select="sales/domestic"/>
</table>
<table>
<xsl:apply-templates select="sales/foreign"/>
</table>
</xsl:template>
注: マッチする子孫が2つ存在し、その一方が他方の子孫となっている可能性もある。 この場合も、特別には扱われずに、 両方の子孫とも通常どおり処理される。以下のようなソースドキュメントの例を示す。<doc><div><div></div></div></doc>このルールでは、<xsl:template match="doc"> <xsl:apply-templates select=".//div"/> </xsl:template>は、外側のdivエレメントと内側のdivエレメントの両方を処理する。
注: 通常、xsl:apply-templatesはカレントノードの子孫のノードだけを処理するために、使用される。 このようにxsl:apply-templatesを使用することにより、終端のない処理ループ (non-terminating processing loop) が発生することはありえない。 ただし、カレントノードの子孫でないエレメントの処理にxsl:apply-templatesを使用すると、終端のない処理ループが発生する可能性もある。 以下に例を示す。<xsl:template match="foo"> <xsl:apply-templates select="."/> </xsl:template>実装側でこのようなループを検知できる場合もあるが、実装が検知できない終端のないループに、スタイルシートが入り込む可能性もある。 これは、サービス上のセキュリティリスクを否定することを示すかもしれない。
1つのソースノードが、複数のテンプレートにマッチする場合もある。 使用するテンプレートルールの決定方法を以下に示す。
最初に、マッチするテンプレートルールのうちインポートの優先順位の最も高いテンプレートルールよりも、優先順位の低いものをすべて候補から外す。
次に、マッチしたテンプレートルールのうち、優先度の最も高いテンプレートルールよりも、優先度の低いものをすべて候補から外す。
テンプレートルールの優先度は、テンプレートルール上の priority アトリビュートが指定する。
優先度の値は実数 (プラスまたはマイナス) であり、またオプションの先頭に付けるマイナス記号 (-) を持つプロダクション Number にマッチしていなければならない (must)。
デフォルトの優先度は、以下のように計算される。
パターンに | で区切られた複数の候補を含む場合、そのテンプレートは、候補それぞれに1つのテンプレートが存在するテンプレートの集合と同様に扱われる。
パターンが、ChildOrAttributeAxisSpecifier で始まる QName 形式の場合、または ChildOrAttributeAxisSpecifier で始まる processing-instruction (Literal) 形式の場合、優先度は0になる。
パターンが、ChildOrAttributeAxisSpecifier で始まる NCName:* 形式の場合、優先度は -0.25 になる。
上記以外に、パターンが ChildOrAttributeAxisSpecifier で始まる NodeTest だけで構成されている場合、優先度は -0.5 になる。
その他の場合、優先度は 0.5 になる。
上記の基準から、最も頻出するパターン (特定の型と、特定の展開された名前を持つノードをテストするパターン) の優先度は0になる。これよりもテスト範囲が広いパターン (特定の型と、特定のネームスペース URI が指定された展開された名前を持つノードをテストするパターン) の優先度は -0.25 になる。さらにテスト範囲が広いパターン (特定の型を持つノードだけをテストするパターン) の優先度は -0.5 になる。最も頻出するパターンよりも特化したパターンの優先度は 0.5 になる。
この処理の後に、マッチしたテンプレートルールが複数残る場合はエラーである。 XSLT プロセッサは、エラーを通知してもよい。エラーを通知しない場合には、マッチしたテンプレートルールの残りの中からスタイルシートの最後方に現れるものを選択して、エラーから回復しなければならない (must)。
<!-- Category: instruction -->
<xsl:apply-imports />
インポートしたスタイルシートのテンプレートルールをオーバーライド (上書き) する ([5.5 テンプレートの競合解決]) ために使用するテンプレートルールでは、xsl:apply-imports エレメントを使ってオーバーライドされたテンプレートルールを呼び出すことができる 。
スタイルシート処理中は常に、カレントテンプレートルールが存在する。
マッチするパターンがテンプレートルールを選択すると、ルール内のテンプレートをインスタンス化している間は、そのテンプレートルールがカレントテンプレートルールになる。
xsl:for-each エレメントをインスタンス化すると、xsl:for-each エレメントのコンテンツをインスタンス化している間は、カレントテンプレートルールは null になる。
xsl:apply-imports は、カレントテンプレートルールを含むスタイルシートエレメントにインポートされたテンプレートルールだけを使って、カレントノードを処理する。ノードはカレントテンプレートルールのモードで処理される。
カレントテンプレートルールが null のときに xsl:apply-imports をインスタンス化した場合はエラーとなる。
たとえば、スタイルシート doc.xsl に、example エレメント用のテンプレートルールを含むと仮定する。
<xsl:template match="example"> <pre><xsl:apply-templates/></pre> </xsl:template>
別のスタイルシートは、doc.xsl をインポートして example エレメントの扱いを以下のように変更できる。
<xsl:import href="doc.xsl"/>
<xsl:template match="example">
<div style="border: solid red">
<xsl:apply-imports/>
</div>
</xsl:template>
両者を合わせると、example エレメントは以下の形式のエレメントに変換される。
<div style="border: solid red"><pre>...</pre></div>
モードを使用すると、エレメントを複数回処理し、毎回異なる結果を得ることができる。
xsl:template と xsl:apply-templates の両者とも、オプションとして mode アトリビュートを使用できる。
mode アトリビュートの値は QName であり、QName は [2.4 修飾名] で解説しているように展開される。
xsl:template が match アトリビュートを持たない場合には、mode アトリビュートを持ってはならない (must)。
xsl:apply-templates エレメントに mode アトリビュートがある場合、このエレメントは mode アトリビュートに同じ値を持つ xsl:template エレメントのテンプレートルールだけに適用される。xsl:apply-templates エレメントに mode アトリビュートがない場合には、このエレメントは mode アトリビュートを持たない xsl:template エレメントのテンプレートルールだけに適用される。
スタイルシート内の明示的なテンプレートルールの中にマッチするパターンがなくても、再帰的に処理を継続させることを可能とする、組み込みテンプレートルールがある。 このテンプレートルールは、エレメントノードとルートノードの両方に適用できる。 組み込みテンプレートルールと同等の記述を以下に示す。
<xsl:template match="*|/"> <xsl:apply-templates/> </xsl:template>
各モードにも、スタイルシート内の明示的なテンプレートルールの中にマッチするパターンがなくても、同一モードでの処理を再帰的に継続できるようにする組み込みテンプレートルールがある。
このテンプレートルールは、エレメントノードとルートノードの両方に適用できる。 モード m 用の組み込みテンプレートルールと同等の記述を以下に示す。
<xsl:template match="*|/" mode="m"> <xsl:apply-templates mode="m"/> </xsl:template>
テキストノードとアトリビュートノードについても、テキストをコピーする以下のような組み込みテンプレートルールが存在する。
<xsl:template match="text()|@*"> <xsl:value-of select="."/> </xsl:template>
プロセッシングインストラクションおよびコメント用の組み込みテンプレートルールは、何も実行しない。
<xsl:template match="processing-instruction()|comment()"/>
また、ネームスペースノード用の組み込みテンプレートルールも、何も実行しない。 ネームスペースノードにマッチしうるパターンは存在しないため、ネームスペースノードが適用するテンプレートルールは組み込みテンプレートルールだけである。
組み込みテンプレートルールは、スタイルシートの前に暗黙的にインポートされたかのように扱われるため、他のすべてのテンプレートルールよりも低いインポートの優先順位を持つ。 従って、スタイルシート作成者は、明示的なテンプレートルールを定義することにより、組み込みテンプレートルールをオーバーライドできる。
<!-- Category: instruction -->
<xsl:call-template
name = qname>
<!-- Content: xsl:with-param* -->
</xsl:call-template>
テンプレートは、名前で呼び出すこともできる。name アトリビュートを持つ xsl:template エレメントは、名前付きテンプレートを指定する。
name アトリビュートの値は QName であり、QNameは [2.4 修飾名] で解説しているように展開される。
xsl:template エレメントが name アトリビュートを持つ場合、match アトリビュートを指定してもしなくてもよい。
xsl:call-template エレメントは、名前でテンプレートを呼び出すため、呼び出すテンプレートを識別するための name アトリビュートを持たなければならない。
xsl:call-template は、xsl:apply-templates と異なり、カレントノードやカレントノードリストを変更しない。
xsl:template エレメントの match アトリビュート、mode アトリビュート、および priority アトリビュートは、xsl:call-template エレメントによるテンプレートの呼び出しに影響を与えない。
同様に、xsl:template エレメントの name アトリビュートも、xsl:apply-templates エレメントによるテンプレートの呼び出しに影響を与えない。
スタイルシートに、同じ名前で同じインポートの優先度を持つテンプレートを複数含む場合はエラーである。
この章では、結果ツリーに直接ノードを生成するインストラクションについて解説する。
テンプレート内では、XSLT ネームスペースに属さない拡張エレメント ([14.1 拡張エレメント] を参照) 以外のスタイルシート内のエレメントは、インスタンス化されて同一の展開された名前 (expanded-name) を持つエレメントノードを生成する。 このエレメントのコンテンツはテンプレートであり、そのテンプレートは、生成されたエレメントノードのコンテンツを付与するためにインスタンス化される。 生成されたエレメントノードは、スタイルシートツリー内のエレメントノードに存在する、XSLT ネームスペース内に名前を持つアトリビュート以外の、アトリビュートを持つことになる。
生成されたエレメントノードは、スタイルシートツリー内のエレメントノードに存在するネームスペースノードのコピーも持つことになる。ただしこれは、文字列値が XSLT ネームスペース URI (http://www.w3.org/1999/XSL/Transform) であるすべてのネームスペースノード、拡張ネームスペースとして宣言されたネームスペース URI ([14.1 拡張エレメント] を参照)、または除外するネームスペース (excluded namespace) として指定されたネームスペース URI には該当しない。
ネームスペース URI は、xsl:stylesheet エレメントに exclude-result-prefixes アトリビュートを指定するか、またはリテラル結果エレメントに xsl:exclude-result-prefixes アトリビュートを指定することにより、除外するネームスペースとして指定される。
これら2つのアトリビュート値は、ネームスペースのプレフィックスを空白で区切ったリストである。
各プレフィックスにバインドされたネームスペースは、除外ネームスペースとして指定される。
exclude-result-prefixes アトリビュート、または xsl:exclude-result-prefixes アトリビュートを持つエレメントのプレフィックスにバインドされたネームスペースが存在しない場合は、エラーである。
ネームスペースのプレフィックスのリストに #default を含めることにより、デフォルトのネームスペース (xmlns で宣言されたもの) を除外ネームスペースとして指定してもよい。
あるネームスペースを除外ネームスペースとして指定すると、exclude-result-prefixes または xsl:exclude-result-prefixes アトリビュートを持つエレメントをルートとするスタイルシートのサブツリー (subtree) 内部に有効となる。ある xsl:stylesheet エレメントをルートとするサブツリーには、そのxsl:stylesheet エレメントの子によってインポートされたスタイルシートやインクルードされたスタイルシートは含まれない。
注: スタイルシートが、ソースツリーの位置を指定するためだけにネームスペース宣言を使用する場合、exclude-result-prefixes アトリビュートにプレフィックスを指定すると、結果ツリー内に余分なネームスペース宣言を生成しないようにできる。
リテラル結果エレメントのアトリビュート値は、アトリビュート値テンプレートとして処理される。
このテンプレートには、中括弧 ({}) 内に記述した式を含めることができる。
結果ツリー内のネームスペース URI を指定するために使用するスタイルシートツリー内のネームスペース URI は、リテラルネームスペース URI と呼ばれる。 この URI に該当するものを以下に示す。
そのスタイルシートに含まれるリテラル結果エレメントの展開された名前のネームスペース URI。
そのスタイルシートに含まれるリテラル結果エレメント上に指定されているアトリビュートの展開された名前のネームスペース URI。
そのスタイルシートに含まれるリテラル結果エレメントのネームスペースノードの文字列値。
<!-- Category: top-level-element -->
<xsl:namespace-alias
stylesheet-prefix = prefix | "#default"
result-prefix = prefix | "#default" />
スタイルシートでは、xsl:namespace-alias エレメントを使用し、1つのネームスペース URI を他のネームスペース URI の エイリアス であると宣言できる。
あるリテラルネームスペース URI が、他のネームスペース URI へのエイリアスになることを宣言している場合、結果ツリー内のそのネームスペース URI は、リテラルネームスペース URI そのものではなく、そのリテラルネームスペース URI がエイリアスとして指しているネームスペース URI になる。
xsl:namespace-alias エレメントは、stylesheet-prefix アトリビュートが指定するプレフィックスにバインドされているネームスペース URI が、result-prefix アトリビュートが指定するプレフィックスにバインドされているネームスペース URI へのエイリアスであると宣言する。
従って、stylesheet-prefix アトリビュートは、スタイルシート内に現れるネームスペース URI を指定し、result-prefix アトリビュートが、その指定に対応して結果ツリー内に現れるネームスペース URI を指定することになる。
プレフィックスの代わりに、#default を使ってデフォルトのネームスペース (xmlns で宣言されたもの) を指定してもよい。
1つのネームスペース URI が、複数の異なるネームスペース URI へのエイリアスになることを宣言されると、最高のインポートの優先順位を持つ宣言が使用される。
このような宣言が複数存在する場合はエラーである。
XSLT プロセッサは、エラーを通知してもよい。エラーを通知しない場合には、最高のインポートの優先順位を持つ宣言の中からスタイルシートの最後方に現れるものを選択し、エラーから回復しなければならない (must)。
リテラル結果エレメントを、XSLT ネームスペース URI を使用するエレメント、アトリビュート、またはネームスペースノードを生成するために使用する場合、スタイルシートはエイリアスを使用しなければならない (must)。 たとえば、以下のようなスタイルシートは、
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:axsl="http://www.w3.org/1999/XSL/TransformAlias">
<xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>
<xsl:template match="/">
<axsl:stylesheet>
<xsl:apply-templates/>
</axsl:stylesheet>
</xsl:template>
<xsl:template match="block">
<axsl:template match="{.}">
<fo:block><axsl:apply-templates/></fo:block>
</axsl:template>
</xsl:template>
</xsl:stylesheet>
以下の形式のドキュメントから XSLT スタイルシートを生成する。
<elements> <block>p</block> <block>h1</block> <block>h2</block> <block>h3</block> <block>h4</block> </elements>
注: XSLT ネームスペース URI 以外のネームスペースについても、エイリアスを使用しなければならない場合もある。たとえば、デジタル署名を扱うネームスペースに属するリテラル結果エレメントは、汎用のセキュリティソフトウェアによる XSLT スタイルシートの誤処理を引き起こす可能性がある。ネームスペースのエイリアスを使用することにより、このような誤処理が発生する可能性を回避できる。
xsl:element を用いたエレメントの生成
<!-- Category: instruction -->
<xsl:element
name = { qname }
namespace = { uri-reference }
use-attribute-sets = qnames>
<!-- Content: template -->
</xsl:element>
xsl:element エレメントは、計算処理された名前を使ってエレメントを生成できる。生成されたエレメントの展開された名前は、必須の name アトリビュートとオプションの namespace アトリビュートによって指定される。
xsl:element エレメントのコンテンツは、生成されたエレメントのアトリビュートおよび子を生成するためのテンプレートである。
name アトリビュートは、アトリビュート値テンプレートとして処理される。
アトリビュート値テンプレートをインスタンス化した結果の文字列が、QName でない場合はエラーである。
XSLT プロセッサは、エラーを通知してもよい。エラーを通知しない場合には、xsl:element エレメントのインスタンス化の結果が、xsl:element エレメントのコンテンツをインスタンス化して生成される一連のノードになるようにすることにより、エラーから回復しなければならない (must)。ただし、この一連のノードは、最初にある (単数または複数の) アトリビュートノードを含まない。
namespace アトリビュートが存在しない場合、QName は、xsl:element エレメントに対して有効なネームスペース宣言 (デフォルトのネームスペース宣言でもよい) を使用して、展開された名前に展開される。
また、namespace アトリビュートが存在する場合も、アトリビュート値テンプレートとして処理される。
アトリビュート値テンプレートをインスタンス化した結果の文字列は、URI リファレンスであるべきである。
文字列がシンタックス上正しくない URI リファレンスとなっても、エラーではない。
文字列が空であった場合、エレメントの展開された名前は null のネームスペース URI を持つ。
その他の場合、文字列は生成されたエレメントの展開された名前のネームスペース URI として使用される。
name アトリビュートが指定した QName のローカルパートは、生成されるエレメントの展開された名前のローカルパートとして使用される。
XSLT プロセッサは、生成されたエレメントを XML として出力するためのプレフィックスを選択する際に、name アトリビュートに指定した QName のプレフィックスを使用してもよい。ただし、これは必須ではない。
xsl:attribute を用いたアトリビュートの生成
<!-- Category: instruction -->
<xsl:attribute
name = { qname }
namespace = { uri-reference }>
<!-- Content: template -->
</xsl:attribute>
xsl:attribute エレメントを使用すると、スタイルシートのリテラル結果エレメントまたは xsl:element などのインストラクションによって生成される結果エレメントに、アトリビュートを追加できる。生成されるアトリビュートの展開された名前は、必須の name アトリビュートおよびオプションの namespace アトリビュートによって指定される。
xsl:attribute エレメントをインスタンス化すると、所属する結果エレメントノードにアトリビュートノードが追加される。
xsl:attribute エレメントのコンテンツは、生成されたアトリビュートの値のためのテンプレートである。
name アトリビュートは、アトリビュート値テンプレートとして処理される。
アトリビュート値テンプレートをインスタンス化した結果の文字列が、QName でない場合、または文字列 xmlns になる場合はエラーである。
XSLT プロセッサは、エラーを通知してもよい。エラーを通知しない場合には、結果ツリーにアトリビュートを追加しないことにより、エラーから回復しなければならない (must)。
namespace アトリビュートが存在しない場合、QNameは xsl:attribute エレメントに対して有効なネームスペース宣言 (デフォルトのネームスペース宣言を除く) を使用して、展開された名前に展開される。
また、namespace アトリビュートが存在する場合も、アトリビュート値テンプレートとして処理される。
これをインスタンス化した結果の文字列は、URI リファレンスであるべきである。
この文字列がシンタックス上正しくない URI リファレンスとなっても、エラーではない。
文字列が空であった場合、アトリビュートの展開された名前は null のネームスペース URI を持つ。
その他の場合、文字列は生成されるアトリビュートの展開された名前のネームスペース URI として使用される。
name アトリビュートが指定した QName のローカルパートは、生成されるアトリビュートの展開された名前のローカルパートとして使用される。
XSLT プロセッサは、生成したアトリビュートを XML として出力するためのプレフィックスを選択する際に、name アトリビュートに指定した QName のプレフィックスを使用してもよい。ただし、これは必須ではなく、プレフィックスが xmlns の場合には使用してはならない (must)。
以下の例は、実行してもエラーではないが、ネームスペース宣言は出力されない。
<xsl:attribute name="xmlns:xsl" namespace="whatever">http://www.w3.org/1999/XSL/Transform</xsl:attribute>
エレメントにアトリビュートを追加すると、そのエレメントの既存の同一の展開された名前を持つアトリビュートを、置き換えることができる。
以下の場合は、すべてエラーである。
エレメントに子を追加した後に、そのエレメントにアトリビュートを追加すること。このような場合、実装はエラーを通知してもよいし、アトリビュートを無視してもよい。
エレメントでないノードにアトリビュートを追加すること。このような場合、実装はエラーを通知してもよいし、アトリビュートを無視してもよい。
xsl:attribute エレメントのコンテンツをインスタンス化する際に、テキストノード以外のノードを生成すること。このような場合、実装はエラーを通知してもよいし、エラー原因のノードを無視してもよい。
注:xsl:attributeが改行 (newline) 付きのテキストノードを含む場合には、XML の出力にキャラクターリファレンスを含まなければならない (must)。 以下に例を示す。<xsl:attribute name="a">x y</xsl:attribute>この記述から以下の出力が得られるa="x
y"(または同等のキャラクターリファレンス)。 XML の出力は、以下の形にはなりえない。a="x y"これは、XML 1.0 では、アトリビュート値が含む改行文字はスペースに正規化するが、改行文字を表すキャラクターリファレンスは正規化しないと規定しているためである。 データモデル内のアトリビュート値は、正規化した後のアトリビュート値を表している。 ツリー内のアトリビュート値に現れた改行が、キャラクターリファレンスとしてではなく、改行文字として出力された場合、XML を再びパースして生成されたツリー内のアトリビュート値には、改行ではなく1個のスペースを含むことになる。つまり、ツリーが正しく出力されなかったことになる。
<!-- Category: top-level-element -->
<xsl:attribute-set
name = qname
use-attribute-sets = qnames>
<!-- Content: xsl:attribute* -->
</xsl:attribute-set>
xsl:attribute-set エレメントは、名前が付けられたアトリビュートの集合を定義する。
name アトリビュートでは、アトリビュートの集合の名前を指定する。
name アトリビュートの値は QName であり、QNameは [2.4 修飾名] で解説しているように展開される。
xsl:attribute-set エレメントのコンテンツは、集合内のアトリビュートを指定する0個以上の xsl:attribute エレメントから構成される。
アトリビュートの集合を使用するには、xsl:element エレメント、xsl:copy エレメント [7.5 コピー] を参照)、または xsl:attribute-set エレメントの use-attribute-sets アトリビュートを指定すればよい。
use-attribute-sets アトリビュートの値は、空白で区切られたアトリビュートの集合の名前からなるリストである。
名前はそれぞれ QName として指定され、QName は [2.4 修飾名] で解説しているように展開される。
use-attribute-sets アトリビュートの指定は、名前付きアトリビュート値の集合が含む各アトリビュートに対応する xsl:attribute エレメントを、 use-attribute-sets アトリビュートを持つエレメントのコンテンツの先頭に追加することと同じである。追加の順序は、use-attribute-sets アトリビュートにおいてアトリビュートの集合の名前を指定する順序と同じである。
xsl:attribute-set エレメントに use-attribute-sets アトリビュートを指定した際に、アトリビュートの集合が直接的または間接的に自分自身を使用する結果になる場合は、エラーである。
リテラル結果エレメントで xsl:use-attribute-sets を指定しても、アトリビュートの集合を使用できる。
xsl:use-attribute-sets アトリビュートの値は、空白で区切られたアトリビュートの集合の名前からなるリストである。
xsl:use-attribute-sets アトリビュートは、 xsl:element に use-attribute-sets アトリビュートを使用する場合と同じ効果を持ち、かつ以下のような追加ルールを持つ。このルールでは、リテラル結果エレメント自体に指定されているアトリビュートは、 実際の xsl:attribute エレメントの手前かつ xsl:use-attribute-sets アトリビュートによって暗黙的に指定された xsl:attribute エレメントの後の位置に、xsl:attribute エレメントによって指定されたかのように扱われる。
従って、リテラル結果エレメントについては、最初に、xsl:use-attribute-sets アトリビュートで名前が付けられたアトリビュートの集合に含まれるアトリビュートが、アトリビュート内にリストされている順序で追加される。次に、リテラル結果エレメントで指定されているアトリビュートが追加される。最後に、xsl:attribute エレメントで指定されているエレメントが追加される。
エレメントにアトリビュートを追加すると、追加先エレメントに存在する同じ名前を持つ既存のアトリビュートが置き換わるため、アトリビュートの集合で指定されているアトリビュートを、リテラル結果エレメント自体で指定されているアトリビュートによってオーバーライドできる。
xsl:attribute-set エレメントに含まれる各 xsl:attribute エレメント内部のテンプレートは、アトリビュートの集合を使用するごとにインスタンス化される。このインスタンス化では、use-attribute-sets アトリビュートまたは xsl:use-attribute-sets アトリビュートを持つエレメントのインスタンス化で使用するものと同一のカレントノードとカレントノードリ