XSL は「Web における SGML」と考えることのできる XML (Extensible Markup Language) を使用してマークアップされた文書のためのスタイル・シート言語です。XSLT は、ある XML ソース文書が、XSL フォーマット・ボキャブラリーを使用する別の XML 文書にどのように変換されるかを記述するために使用します。しかし、それだけではなく XSLT は他の一般的な変換にも使用されます。この演習では、XML 文書を Web ブラウザーで表示可能な HTML 文書に変換するという、最も実際的なタスクを取り上げます。
この演習は "XSLT 勧告" のセクション 5.1 "Processing Model" (参考文献を参照) を実践するものです。そのセクションの内容をすぐに理解できると期待しないでください。しかし、この記事の演習を完了したら、もう一度そのセクションに戻ってみてください。以下の引用文の内容を最初よりも理解できるようになっているはずです。
"ソース・ノードのリストを処理すると結果ツリー・フラグメントが生成されます。結果ツリーは、ルート・ノードだけを含むリストを処理することによって構築されます。ソース・ノードのリストの各メンバーを順番に処理して生成される結果ツリーの構造を追加することによって処理が進んで行きます。あるノードの処理は、そのノードに適合するパターンを持つテンプレート・ルールをすべて見つけ、その中から最適なテンプレート・ルールを選ぶことによって行われます。それから、選択したテンプレート・ルールを、現行のノードとなっているノードと、そのノードを現行のノードとし、ソース・ノードのリストを現行ノード・リストとして使用し、インスタンス化します。テンプレートは通常、処理するソース・ノードのリストを選択するための命令を含んでいます。このようなマッチング、インスタンス化、選択という処理は、処理対象として選ばれる新しいソース・ノードがなくなるまで繰り返し行われます。"
XSLT の主な機能は以下のとおりです。
- 再帰的である。
- 解析してソース・ツリーに展開された XML ソース文書を操作する。
- ソース・ツリーの結果ツリーへの変換を指定する。
- 結果ツリーを、指定されたフォーマットの結果ファイルにコピーする。
紙を使うこの演習では、これらの機能それぞれを実践します。
この演習の中で出て来る用語には、その定義へのリンクが設定されています。
以下に示すのは、この演習で使用するサンプルの XML 文書です。
<chapter id="cmds"> <chaptitle>FileCab</chaptitle> <para>This chapter describes the commands that manage the <tm>FileCab</tm>inet application.</para> </chapter> |
最初の要素 <chapter> が文書全体を囲んでいる点に注目してください。このため、これがこの文書インスタンスの文書要素となります。さらにこれは、解析された XML 文書の常に最上位のノードとなるように定義されているルート・ノードの子ともなります。
以下は、XSL 処理の最初の段階として、ソースの XML 文書が解析された後、どのように表わされるかを示した図です。
図 1. Source XML document in first stage of XSL processing
この文書の解析されたソース・ツリーを表示する別の方法については、ツリーをたどるの定義を参照してください。
2 枚の色の付いた用紙 (サイズ 8 1/2" x 11") をそれぞれ 4 等分にカットします。そして、4 等分にカットしてできた紙片 8 枚をそれぞれ半分に折ります。
図 2. Cut the sheet into quarters, then fold each quarter in half across the long side
各紙片の表面の上部に横線を引きます。そして、線の上側に、その紙片のラベルを書いてください。ラベルはサンプル文書のソース・ツリー・ビューに示されている各ノードの名前にします (概念: ソース文書のツリー表示を参照)。これらラベルを付けられた紙片は、XSL スタイル・シートを構成するテンプレート・ルールを表します。
図 3. Representative template rules
次に白いコピー用紙 1 枚を 8 等分にカットします。(これで、演習に必要な紙片が用意できました。) この紙片のどちらかの面に、各要素または属性に対応するテキスト部分を書きます。これらの紙片は、ソース文書のテキストまたは文字の内容を表します。これで、解析ツリー表示 (概念: ソース文書のツリー表示の絵を参照) に基づいた、段落ノードの内容を表すテキスト紙片を用意できました。
図 4. View of the three text portions of the paragraph
折りたたんだ紙片 (白い用紙のテキスト紙片ではなく) を小さな箱、鉢、または袋に入れます。これは、XSL スタイル・シート全体を表すものです。これをさらに完全なものにしたい場合、コンテナーの表面に以下のテキストをラベルとして付けてください。
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/xhtml1/strict"> |
裏面に以下をラベルとして付けてください。
</xsl:stylesheet> |
上記の例では、xmlns が名前スペース、または他の XML ボキャブラリーからの要素の修飾子を宣言します。示されている URL は、コロン (:) の右側にあるものに関する詳細な情報の参照先を示しています。それで、xmlns:xsl 行は、xsl: で始まるマークアップの定義情報が掲載されている URL を示しています。次の行 xmlns は、スタイル・シートのデフォルトのマークアップに関する詳細な情報の参照先を示しており、有効な XHTML となるようにします。
色付きの用紙から作った紙片は、それぞれテンプレート・ルールを表しており、ソース・ツリーの各ノード (通常は要素) に対して行いたい処理を定義します。この紙片の外側の表面と裏面は、この要素の開始タグと終了タグを表します。
この紙片自体は、子要素に対応するテンプレートの中身 (<chapter> 要素の子 <chaptitle> および <para> の中にある) を表します。これは、XSL 処理の再帰的な性質を表しています。ソース・ツリーのルート・ノードから始めて、各ノードに適切なテンプレート・ルールがあるかどうかが検査され、あれば、そのルールが呼び出されます。その後、新しいノードの子の検査が続けられます。要素のその子ノードを処理するときには、その要素に適応した同じテンプレートを毎回適用します。このため、この再帰的なアクションは apply-templates と呼ばれます。
要素の子ノードまたはその内容の処理を省略したい場合は、「apply-templates」の呼び出しを終了してください。たとえば、空の要素のテンプレートの呼び出しなどでは、そのような呼び出しを行っても意味がありません。子要素のノードがないからです。同じように、機密情報が入っていることを示す属性が要素に入っている場合、「apply-templates」呼び出しによって参照しなければ、その内容を除去できます。
この演習を行って結果ツリーを作成する際に、サンプルの XML 文書を参照してください。ソース・ツリーと結果ツリーを区別するには、結果ツリー用のマークアップをすべて大文字で作成してください (たとえば、<b> の代わりに <B> を使用します)。
ルート・ノードのテンプレート (スラッシュ (/) によって示される) から始めます。ルート・ノードのテンプレートが存在する場合、必ず最初に処理されます。この演習の目的はサンプルの XML 文書を、Web ブラウザーで表示できる HTML 文書に変換することであるため、このテンプレート・ルールは、結果としての HTML のための開始マークアップおよび終了マークアップ、さらに結果全体に適用されるコメントまたはメタデータを生成する重要なものです。この紙片の外側表面のラベルの下に "<HTML>"、外側裏面に "</HTML>" と書いてください。残りの文書も再帰的に処理したいので、紙片の内側の中ほどに「apply-templates」と書きます。これで、これは文書のルート・ノードの完全なテンプレート・ルールを表します。テンプレート・ルールは、外側表面、内側、外側裏面がそれぞれ下記のようになります。
図 5. How your template rule might look
次に、<chapter> 要素に関して、紙片の表面の "chapter" ラベルの下に以下を書き込みます。
<HEAD> <TITLE>My result doc</TITLE> </HEAD> <BODY> |
残りの文書も再帰的に処理したいので、ここでも紙片の内側の中ほどに「apply-templates」と書きます。裏側には以下を書き込みます。
</BODY> |
これで、2 番目のテンプレート・ルールは完成しました。
ソース文書のツリー表示の図にある、残りの要素ノードに関しても、同様の方法で処理します。それぞれの紙片またはテンプレート・ルールの内側には、必ず「apply-templates」と書いてください。
残りのテンプレート・ルールに関して行う事柄を以下に示します。
- id: この項目のテンプレート・ルールの作業を開始している場合、ここでは保留にしておいてください。ソース文書内のすべてを結果文書で何かに変換する必要があるわけではありません。属性は通常、構造よりもプロパティーを表しますし、この演習の目的も踏まえて、ここでは 1 対 1 の構造変換だけを扱うことにします。
- chaptitle: これは H1 見出しとそれに続く罫線に変換します (ここでは、XHTML に準拠した形式で
<HR/>を使用します)。 - para: これは整形式 HTML の段落 (
<P>と</P>) に変換します。 - tm: この要素の中身は HTML の太字マークマップ (
<B>と</B>) で囲んで、強調表示されるようにします。さらに、この紙片の外側裏面に<SUP>(TM)</SUP>を書き加えてください。これは、テンプレートを使用して生成されるテキストを要素の中身の隣に挿入できることを示す例です。
ソース・ツリーにある各要素ノードについてテンプレート・ルールを定義したら、その紙片を集め、スタイル・シートを入れた容器 (箱または袋) に入れます。そしてそれらをかき混ぜます。これでスタイル・シートでのルールについて特別な順序はなくなります。ただし、後で編集のためにそれらを編成する場合は別です。
これで、ソース文書を変換する準備ができました。
XML パーサーは、ソース文書をソース・ツリーに変換し、次いでそれを XSL スタイル・シートを読み込み、効果的に検索できるようにテンプレート・ルールを編成します。続いて、XSL プロセッサーは、ルート・ノードから始めてソース・ツリーを「たどり」、各ノードを対応するテンプレート・ルールに適合させようとします。このような適合が行われると、テンプレートが結果ツリーにコピーされます。ソース・ツリー全体が網羅されるまで、処理が続けられます。最後に、XSL プロセッサーは結果ツリーをたどり、そこで検出したものを、xsl:stylesheet の入れ物のxmlns 属性によって指定される構文を使用して、出力ファイルまたはストリームにコピーします。
図 6. XSL processing sequence
これから、XSL 処理の順序を模倣した演習を行います。
概念: ソース文書のツリー表示の絵は、ノードとプロパティーの内部構造に解析された XML ソース文書を表しています。
XSL プロセッサーは、スタイル・シート内のテンプレート・ルールを検出し、解析し、編成します。容器の中からテンプレート・ルールの紙片を取り出し、それらをラベルが見えるように並べます。これは、上記の図の中で、ルール・ベースを作成する部分に当たります。
次に、プロセスの apply-templates 部分をモデル化します。
テンプレートの適用を開始するには、ルート・ノードのテンプレート・ノードを見つけ、それを取ります。次いでそれを開き、内側に書かれている指示が apply-templates であるのを見ます。これは、ツリーの次のノードchapter に進み、それに適合するテンプレート・ルールがあるかどうかを確認する必要があることを意味します。適合するテンプレート・ルールが見つかりましたか ? では、その紙片を取り、最初の紙片に挟んでください。これは、ソース・ツリーの構造に基づいて結果ツリーを再帰的に組み立てていくことを意味します。
ソース・ツリーの各ノードについて、同じ処理を繰り返します。chapter テンプレート・ルールには、apply-templates 指示があり、次のノードchaptitle に進みます。続いて、そのテンプレート・ルールの紙片を見つけ、それを前述のテンプレートに挟みます。それからその内側を調べます。再び apply-templates とあるので、chaptitle の次の子に進みます。この例では、「FileCab」と書かれた白い紙片になります。その紙片をchaptitle テンプレートの中に入れます。
ソース・ツリーの絵に従って、ソース・ツリーの最初の分岐の末端まで来ました。この位置では子は見つかりませんし、適用するルールもありません。そのため、ツリーを戻ってchaptitle の次の兄弟要素paraに進みます。そのテンプレートを見つけ出し、同じ処理を続けます。
para テンプレート・ルールの処理は、ソース・ツリーのpara ノードの分岐に対応して、以下の絵のようにテンプレートとテキストが集められます。
図 7. The result of processing the para template rule
作業が終了した時点で、1 つにまとまった厚いroot テンプレートができあがるはずです。その中には、ソース文書に基づく結果ツリーと、スタイル・シートのテンプレート・ルールに記述した変換が入っています。
できあがったこの小冊子をばらばらにして、結果ツリー・ビューを組み立てるステップを繰り返し何度か行ってください。これらのステップはこの解説の主要なポイントですから、是非習得してください。
組み立てられた結果ツリーを、本を読むときのようにページごとにめくってください。色つきの紙片の表面と裏面に書き込まれている内容すべて (ラベルは除く) を、個々の用紙に順番に書き留めていきます。色つきの紙片それぞれの裏面に終了タグが指定されていることを忘れないようにしましょう。順番にそれらを見つけながら、白い紙のテキスト・ページの内容も写していきます。
いかがですか ? これで、実際に生じるのと同じ方法で、XSL 変換を完了することができました。そんな馬鹿なとおっしゃるかもしれませんね。では、次のセクションを見てみましょう !
紙片のテンプレート・ルールを同等な XSL スタイル・シートに置き換える
これから、これらの紙片テンプレートを実際の XSL スタイル・シートに移しかえます。白紙を 1 枚用意するか、先の HTML の演習の出力紙を裏返して書き込んでください。
ラベルを付けた色つきの紙片を分類します。これらはそれぞれ、結果の変換に関する適合パターンと、対応するテンプレートとを持つテンプレート・ルールです。
XSL スタイル・シートを作成するために、まずテンプレートのコンテナーに付けた下記のラベルを写します。
<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="__label__"> __first_page_content__ <xsl:apply-templates/> __last_page_content__ </xsl:template> - 紙片のラベルを、示されている match 属性の
__label__フィールドに書き写します。(ルート・テンプレートについては、実際 XSL では root という名前に代えて、略記の「/」 (ファイル・パスの場合のようですね) を使用します。) - 最初のページの内容を、テンプレートの中で示されている
__first_page_content__の位置に書き写します。 - 最後のページの内容を
__last_page_content__の位置に書き写します。テンプレートで apply-templates 呼び出しが省略されていると、上記のように
<xsl:apply-templates/>マークアップは転記しません。 - 並べられている残りの色つきの紙片についても同じ作業を行ってください。白い紙片はソース文書の部分を表しており、変換ルールの一部ではありませんので色つきの折り畳んだ紙片の情報だけを転記します。
コンテナーに書き込んだ下記の終了マークアップでスタイル・シートを終了します。
</xsl:stylesheet> |
おめでとうございます ! これで、規格に準拠し、実際に機能する XSL スタイル・シートを作成できました。
上記の作業を実際の XSL アプリケーションで試してみたいと思う場合、PC で以下の作業を行ってください。最初の 2 つのファイルの作成には、Windows のメモ帳などの単純なエディターが適しています。
- サンプルのソース文書を
test.xmlという名前のファイルに入力します。このファイルを分かりやすい名前のディレクトリー (たとえば、c:\testxml) に保管します。 - スタイル・シートを
myview.xslという名前のファイルに入力します。このファイルを先ほどと同じディレクトリーに保管します。 - 一般的な XSL 変換プログラムをダウンロードします。Windows をお使いであれば、XT を使用できます。James Clark の Web サイト (参考文献を参照) に行き、そこで 「XT packaged as a Win32 executable」リンクを見つけてください。MS-DOS プロンプトで、このファイルをパスが通っているディレクトリーに unzip します。(Saxon または Xalan などの他のプロセッサーを使用する場合は、それらのツールに付属しているセットアップの指示および起動の指示に従ってください。)
- サンプル・ファイルを保管したディレクトリーに移動 (たとえば、
cd testxml) し、下記のコマンド (この場合は XT のもの) を実行してスタイル・シートをテストします。c:\testxsl>xt test.xml myview.xsl myresult.htm
しばらくすると、処理が完了し、ディレクトリーの中に結果ファイルmyresult.htmが作成されるはずです。 - 最後に、このファイルをブラウザーで開き、どのように表示されるかを確認します。
これで、演習は完了です。XSL 処理モデルについて新しい理解を得たところで、この演習の最初の方で掲載されていた "XSLT 勧告" からの引用文を再度読んでみてください。処理モデルに関するその説明を、最初よりもずっと理解できるようになっているに違いありません。あなたは XSL を「ハンズオン」で経験したのですから !
この記事の中で使用された用語および句が定義されています。
属性 (attribute). 要素のプロパティー。属性は、スタイル、セキュリティー・レベル、意図または役割、あるいはデータ型の指定などを付与する場合に使用される。
子 (child). 別ノードの中にあるノード。
現行ノード (current node). 特定のテンプレート・ルールに適合しているノード。現行ノードのコンテキストには、それ自体、その先祖 (親、祖父母など)、兄弟、および子が含まれる。
文書要素 (document element). XML 文書またはフラグメントの最外部の要素。
要素 (element). XML 文書の中の構造の部分。要素には開始タグ、内容、そして終了タグがある。要素の開始タグには、要素全体に適用される、属性と呼ばれる別のプロパティーが含まれる。
生成されるテキスト (generated text). 文書の変換されたノードに挿入されるデータ。たとえば、章ごとに分類されている本では、~ 章 という語が、印刷される章タイトルの一部として生成される。
適合パターン (match pattern). ソース文書の中の、要素の名前、属性、または他の有効な XPath 対象。
ノード (node). 文書の中の、要素、属性、またはテキスト項目。これらは、互いにネストされた構造の一部を表す。このネストされている構造は、木がいくつかの節 (ノード) で枝分かれしている様としてイメージできる。
親 (parent). 現行ノードを含むノード。
解析 (parsing). 文書の内容 (通常はテキストとイメージ) と、マークアップ (タグ名および構文、または "<" および ">" 文字) を分けていく処理。
再帰 (recursion). 文書ツリー構造において、ノードのすべての子および孫が処理されるまで同じ処理を繰り返し呼び出し、ツリーの各ノードに処理を適用していくこと。この代わりに、ほとんどの人が文書に関して考える方法は順次処理である。
結果ツリー (result tree). ソース構造から変換した後の文書を表すもの。結果ツリーが XSL 処理アプリケーションによってそのファイル・フォーマットに書き込まれるときに、意図する結果フォーマットの構文が適用される。
ルート要素 (root element). 解析された XML 文書の中で暗黙的に最高レベルであるノード。解析されたインスタンスの文書要素になる要素を必ずしも予測できるわけではないが、予備的な処理またはセットアップ処理に使用できるルート・ノードは必ず存在する。
ルート・ノード (root node). 解析された文書すべての開始地点。ルート・ノードの次が文書要素となるが、これはすべての文書で同じではない。解析された文書すべてにはルート・ノードがあるため、変換での中心のノードとなる。
兄弟 (sibling). 別のノードの中にいくつかのノードがある場合のそれらのノードの 1 つ。
ソース・ツリー (source tree). 解析された後の文書を表すもの。XML 構文 ("<" および ">" 区切り文字) は除かれている。文書のツリー構造は、以下のように図示される。

ストリーム (stream). 1 つの操作から別の操作に渡されて処理されるデータ。ストリーム・メディアの例として、サーバーからのデータであり、Web ブラウザーで再生されるオーディオ・ファイルをあげることができる。
テンプレート (template). 結果ツリーに写すために、マークアップまたは内容を置き換えるもの。
テンプレート・ルール (template rule). スタイル・シートは一連のテンプレート・ルールによって構成される。各テンプレート・ルールには、ソース文書内の要素またはノードに関連づける適合パターンがある。テンプレート・ルールには、ルールの結果インスタンスと関連づけられる、マークアップまたは生成されるテキストのテンプレートが入っている。テンプレートには、ノードの子の処理に関する再帰呼び出し (<xsl:apply-templates/>)、異なる名前付きテンプレートの呼び出し、またはソース・ツリーにある他のノードの特定の値の照会などをオプションで含めることができる。
ツリーをたどる (walking a tree). ツリーの一番左からノードを枝の末端までたどり、次いで新しい枝に移動して末端までたどり、さらに新しい枝へと順番にすべてのノードを移動していくこと。この例のツリーをたどると、検出されるノードは以下のようになる。
root:
.. chapter:
.... id: "cmds"
....chaptitle: "FileCab"
....para:
......"This chapter..."
......tm: "FileCab"
......"inet applica..."
整形式 (well-formed). 特定の基準に合う XML 文書 (インスタンス とも呼ばれる)。たとえば、文書には必ず各文書要素ごとに開始タグと終了タグがある (例:<b>Hello</b>)。中身を必要としない要素は、タグの末尾がスラッシュとなる空開始タグによって表される (HTML での水平けい線<hr/> など)。さらに、要素は適切にネストされる (<b><i>Hi</i></b>)。部分的に重ねることはできない (<b><i>Hi</b></i>)。このような文書は整形式 文書であり、XML ブラウザーまたは処理システムによって使用できる。整形式 (well-formed). 特定の基準に合う XML 文書 (インスタンス とも呼ばれる)。たとえば、文書には必ず各文書要素ごとに開始タグと終了タグがある (例:<b>Hello</b>)。中身を必要としない要素は、タグの末尾がスラッシュとなる空開始タグによって表される (HTML での水平けい線<hr/> など)。さらに、要素は適切にネストされる (<b><i>Hi</i></b>)。部分的に重ねることはできない (<b><i>Hi</b></i>)。このような文書は整形式 文書であり、XML ブラウザーまたは処理システムによって使用できる。
- この演習は、XSLT Recommendation のセクション 5.1Processing Model を実践したものです。
- 実際の XSL アプリケーションで試してみるには、XSL 変換の Java プログラム XT をJames Clark の Web サイトからダウンロードしてください。
- ノードの関係に関する詳細については、W3C Web サイトのXPath を参照してください。
Don Day 氏は IBM のアドバイザリー・ソフトウェア・エンジニアです。氏は 15 年間、IBM の Information Development コミュニティーのための出版ツールの開発とサポートにあたってきました。氏は IBM の e-business Operating Systems Solutions の分野の Information Design and Development、および IBM Corporate User Technology のために XML の専門知識を提供してきました。氏は、W3C XSL Working Group での IBM の代表者であり、W3C CSS Working Group でも現在 IBM の代表者の 1 人です。氏は、New Mexico State University において、English と Journalism での文学士号、さらに Technical and Professional Communication (Computer Science の副専攻科目) での文学修士号を取得しています。