XSLTの最初のバージョンは非常に厳密でした。1つの入力と、1つの出力しか無いのです(ただし、1つ以上のテンプレート・ファイルを持つことはできました)。XSLT 2.0では、入力は相変わらず1つに制限していますが、出力システムは、もっと柔軟になっています。XSLT 2.0では、xsl:result-documentディレクティブを使って、複数の出力ファイルを持つことができます。この新しいタグには2つ、重要な属性があります。これを表1に示します。
表1. xsl:result-documentの属性
| 属性 | 説明 |
|---|---|
href
| ファイル名、または完全修飾された出力ファイルのURL |
format
| 使うべきフォーマットの名前であり、対応するxsl:outputディレクティブで定義されます |
私はこのディレクティブをテストするために、一連のテスト結果を含む1つのXMLファイルを用意しました(リスト1)。
リスト1. 入力XMLファイル
<?xml version="1.0" encoding="UTF-8"?>
<tests>
<testrun run="test1">
<test name="foo" pass="true" />
<test name="bar" pass="true" />
<test name="baz" pass="true" />
</testrun>
<testrun run="test2">
<test name="foo" pass="true" />
<test name="bar" pass="false" />
<test name="baz" pass="false" />
</testrun>
<testrun run="test3">
<test name="foo" pass="false" />
<test name="bar" pass="true" />
<test name="baz" pass="false" />
</testrun>
</tests>
|
これは、ごく単純なものです。各テスト実行の中には名前の付いた一連のテストがあり、それぞれが、テストが成功したかどうかを示すパス・フラグを持っています。
まず、最初にすべきことは、各テスト結果に対してファイルを作ることです。リスト2はXSLテンプレートを示しています。
リスト2. 各テストに対してファイルを作るコード
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="text"/>
<xsl:output method="html" indent="yes" name="html"/>
<xsl:template match="/">
<xsl:for-each select="//testrun">
<xsl:variable name="filename"
select="concat('output1/',@run,'.html')" />
<xsl:value-of select="$filename" /> <!-- Creating -->
<xsl:result-document href="{$filename}" format="html">
<html><body>
<xsl:value-of select="@run"/>
</body></html>
</xsl:result-document>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
|
まずファイルの先頭から、幾つか、注意すべき事があります。スタイルシート・タグのversion属性は、xsl:result-documentタグが使えるように、2.0に設定されます。その後を見ると、スタイルシート自体は、出力タイプとしてtextに設定されていることが分かります。これは、HTMLファイルがHTMLフォーマットを持つようにしたいのであれば、第2の名前付きフォーマットを、htmlタイプで定義する必要がある、ということを意味します。私はこのフォーマットをxsl:result-documentタグの中で使っています。
そこからは、xsl:for-eachループを使って、testrunタグまで繰り返します。こうしたタグのそれぞれに対し、variableタグを使って新しい$filename変数を作り、出力ディレクトリー名(output1)と実行名、そして .htmlファイルを1つのパスに連結させます。
こうした上で、$filename変数を持つvalue-ofタグを使って、私がどんなファイルを作っているのかをユーザーに対して伝えます。その後でxsl:result-documentタグを使って新しい文書を開き、HTMLを出力します。リスト3は、このエンジンをサンプル・データファイルに対して実行した場合の出力を示しています。
リスト3. Saxonをサンプル・データファイルに対して実行した場合の出力
Creating output1/test1.html
Creating output1/test2.html
Creating output1/test3.html
|
xsl:result-documentタグの中身が、このテンプレートの他の部分と同じように評価されるのは、少し直感に反するように思えるかもしれませんが、実際、同じように評価されるのです。そして、テンプレート・コンテキスト内の変数が全て利用できるのです。
これを示すために、xsl:result-documentタグ内のコードをアップグレードし、テスト結果に関する情報を、より多く示すようにします(リスト4)。
リスト4. テンプレートからの、改善されたHTML出力
<xsl:result-document href="{$filename}" format="html">
<html><head>
<title>Test results - <xsl:value-of select="@run"/></title>
</head><body>
<xsl:value-of select="@run"/> <!-- Run -->
<table>
<tr><td>Test</td><td>Pass</td></tr>
<xsl:for-each select="test">
<tr><td>
<xsl:value-of select="@name" />
</td><td>
<xsl:value-of select="@pass" />
</td></tr>
</xsl:for-each>
</table>
</body></html>
</xsl:result-document>
|
この出力のHTML結果をリスト5に示します。
リスト5. アップグレードされたHTML出力
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test results - test1</title>
</head>
<body>
<!-- Run: test1-->
<table>
<tr>
<td>Test</td>
<td>Pass</td>
</tr>
<tr>
<td>foo</td>
<td>true</td>
</tr>
<tr>
<td>bar</td>
<td>true</td>
</tr>
<tr>
<td>baz</td>
<td>true</td>
</tr>
</table>
</body>
</html>
|
最後に、出力テスト結果それぞれを指す、インデックス・ファイルを追加します。そのために、私は別のxsl:result-documentタグを使って出力をハードコード化し、インデックス・ファイルになるようにします(リスト6)。
リスト6. インデックス・ファイルを作るコード
<!-- Creating the index -->
<xsl:result-document href="output3/index.html" format="html">
<html><head><title>Test Index</title></head>
<body>
<xsl:for-each select="//testrun">
<a href="{@run}.html"><xsl:value-of select="@run" />
</a><br/>
</xsl:for-each>
</body>
</html>
</xsl:result-document>
|
このセクションは、各テスト・ケースに対してHTMLファイルを作るxsl:for-eachループの直後に置きます。リスト7は、サンプルのデータ・セットに対するインデックス・ファイルを示しています。
リスト7. インデックス・ファイル
<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=UTF-8">
<title>Test Index</title>
</head>
<body><a href="test1.html">test1</a><br>
<a href="test2.html">test2</a><br>
<a href="test3.html">test3</a><br></body>
</html>
|
xsl:result-documentディレクティブを使うことにより、1つのデータ・ソースから複数のファイルを、1つのXSLテンプレートを使って出力できるようになります。この機能はXSLT 1.xの非標準的拡張でしたが、XSLTテンプレートを書く人達にとって、新たな世界を開くものです。
- W3CのXSL標準のサイトを見てください。ここはXSL技術やXSL標準に関する手軽な情報源です。
- W3CのXPathページを見てください。ここではXPathのバージョンと標準に関する情報を提供しています。
- XSLプロセッサーとして一般的な、Saxonをダウンロードしてください。著者も、この記事を書くためにこれを使いました。
- Michael Kay著によるXSLTのバイブル、XSLT 2.0 Programmer's Referenceを読んでください。素晴らしい入門書であり、貴重な参考書でもあります。
- そこを見たら、Michael Kay著によるXPath 2.0 Programmer's Referenceも見てください。W3Cを書いた人による、究極的な参考書です。
- Jack D. Herrington著によるCode Generation in Actionを読んでください。データベース・アクセスに限らず、幅広い種類の対象向けのコード生成に関して網羅しています。
-
developerWorksのXMLゾーンには、XML関係の資料が豊富に取り揃えられています。
-
XMLおよび関連技術においてIBM認証開発者になる方法については こちら を参照してください。