皆さんはスタイルシートという言葉を聞くと、おそらく CSS スタイルシートを思い浮かべると思います。XSLT スタイルシートは通常、Web
サービス間でデータをマッピングする場合などの、XML の変換に使用されています。XSLT は XML の変換に非常によく適しているため、最上位レベルの <stylesheet> 要素のエイリアスとして <xsl:transform> が作成されました (しかし <xsl:transform> はほとんど使われていません)。このような XSLT 変換では、入力の構造と出力の構造とがまったく異なります。何よりもまず、名前空間が異なります。
一方、XSLT スタイルシートでは、入力の構造と出力の構造とは似ていますが、入力の方が単純です。一部のタグに対して簡単な内容が追加されますが、大半のタグは変更されずにそのまま出力にコピーされます。入力と出力の名前空間は同じです (HTML)。入力文書には XSLT スタイルシートに対するディレクティブ (脚注を作成するなど) が含まれる場合もあります。これらのディレクティブは別の名前空間に属しており、出力には含まれません。
この記事では、XSLT スタイルシートを使用して XHTML 文書に簡単な内容を追加する方法について説明します。そのために、ディレクティブの使い方、他のソース文書の一部を参照する方法、そしてマスター文書のリンクを使用してナビゲーションを行う方法を例として取り上げます。また、ページをインタープリター方式で処理する場合とコンパイル方式で処理する場合の違いについても説明します。
XSLT スタイルシートを使用しても JavaScript や CSS といった他の技術を使用できなくなるわけではありません。フォント、強調、色、マージン、等々を指定するには CSS が適しています。ただし、脚注など別の場所にある情報やモジュールを組み合わせたり、目次を生成したりするには、CSS は適していません。そのような場合に XSLT が登場します。XSLT は CSS を補完するものであり、CSS を置き換えるものではありません。
XSLT のコードは、実際には 1 つのファイルにまとめることができますが、この記事で取り上げる個々の例では簡潔にするために、必ず必要となる一部のコードを除いて別々の XSLT ファイルにしています。リスト 1 に必ず必要となるコードを示します。
リスト 1. 必ず必要となるコード (samples/common.xsl)
<s:stylesheet xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:a="http://sourceforge.net/projects/arbalo/" xmlns:s="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="a h" version="1.0" > <s:template match="h:head"> <s:copy> <s:apply-templates select="@*|node()"/> <meta http-equiv="content-type" content="text/html;charset=UTF-8" /> <link href="common.css" rel="stylesheet" type="text/css" /> </s:copy> </s:template> <s:template match="*"> <s:copy> <s:copy-of select="@*"/> <s:apply-templates/> </s:copy> </s:template> </s:stylesheet> |
XHTML の名前空間は、デフォルト名前空間および名前空間 h: として、2
回定義されています。デフォルト名前空間は、名前空間接頭辞の使用を避けなければならないような状況で出力の XHTML タグを作成するために使用され、h: は XPath 式で使用されます。
この記事では XSLT のバージョン 1.0 を使用します。現時点では XSLT 2.0 を解釈できるブラウザーはほとんどありませんが、サーバー上で XSLT が実行される場合には XSLT 2.0 を使用できる可能性があります。XSLT 2.0 には以下の機能も含まれています。
- XPath 2.0 (
if…then…elseや多くの組み込み関数) - 組み込みの XPath 関数やユーザー定義の XPath 関数
- グループ化機能
リスト 1 の XSLT は以下のようになっています。
s:template match="h: head"は CSS スタイルシートへのリンクを追加することによって、ソース文書の head セクションに簡単な内容を追加しています。XML のデフォルト・エンコードは UTF-8 ですが、一部のブラウザーではコンテンツを描画するためにコンテンツ・タイプを指定する必要があります。s:template match="*"はデフォルトのディープ・コピーです。原則的に、すべてのコンテンツがターゲット文書にコピーされます。このテンプレートがない場合には、タグのテキスト・コンテンツのみがターゲット文書にコピーされます。処理命令ノードはコピーされません。
この記事でこれから説明する例はすべて別々のファイルになっており、それらのファイルに common.xsl がインポートされます。
簡単な内容を追加することで、ソース文書の中では明示的に要求されていない機能が追加されます。その一例がリスト 1 に示した CSS スタイルシートへのリンクです。別の例を試してみましょう。この例では内部リンクに小さな矢印 (^ v) を追加し、リンク先がそのリンクよりも前方にあるのか後方にあるのかを示すことにします。リスト 2 にそのスタイルシートを示します。
リスト 2. スタイルシート (samples/linkUpDown.xsl)
<s:stylesheet xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:s="http://www.w3.org/1999/XSL/Transform" version="1.0" > <s:import href="common.xsl"/> <s:template match="h:a[starts-with(@href,'#')]"> <s:copy> <s:copy-of select="@*"/> <s:variable name="name" select="substring-after(@href,'#')"/> <s:choose> <s:when test="preceding::h:a[@name=$name]"> <s:text>^</s:text> </s:when> <s:when test="following::h:a[@name=$name]"> <s:text>v</s:text> </s:when> </s:choose> <s:apply-templates/> </s:copy> </s:template> </s:stylesheet> |
最初にリスト 1 の共通スタイルシートをインポートしています。template match により、('#' で始まる) 内部リンクとの突き合わせを行います。そのリンクが指すアンカーが前方にある場合には、そのリンクに上向きの矢印を追加します (リンクが指すアンカーが後方にある場合には下向きの矢印を追加します)。
s:copy-of と s:apply-templates により、該当するタグの属性と内容が確実に出力されます。
リスト 3 は、内部リンクを持ち、リスト 2 のスタイルシートによって簡単な内容が追加された文書の例を示しています。
リスト 3. ソース文書 (samples/linkUpDown.xsl)
<?xml-stylesheet href="linkUpDown.xsl" type="text/xsl"?> <html xmlns="http://www.w3.org/1999/xhtml"> <head/> <body> <a name="a"/> <p>This link goes <a href="vb">downward.</a></p> <br/> <p>Reduce the size of the window to verify the link really works.</p> <br/> <a name="b"/> <p>This link goes <a href="^a">upward.</a> </p> </body> </html> |
ターゲット文書もソース文書と同じように見えますが、リスト 4 のエントリーが追加されている点が異なります。
リスト 4. ターゲット文書 (samples/linkUpDown.xsl)
… <a href="#b">v downwards.</a> … … <a href="#a">^ upwards.</a> … |
スタイルシートに何をさせるのかを指示するディレクティブをソース文書の中に含めることができます。ディレクティブは名前空間が別であり (この記事の例では接頭辞が a:)、ターゲット文書にはコピーされません。
リスト 5 のスタイルシートでは、ソース文書の任意の場所にあるディレクティブ・タグ a:ref によって脚注が作成されます。
リスト 5. スタイルシート (samples/footnote.xsl)
<s:stylesheet
xmlns="http://www.w3.org/1999/xhtml"
xmlns:a="http://sourceforge.net/projects/arbalo/"
xmlns:h="http://www.w3.org/1999/xhtml"
xmlns:s="http://www.w3.org/1999/XSL/Transform"
version="1.0"
>
<s:import href="common.xsl"/>
<s:template match="h:body">
<s:copy>
<s:apply-templates select="@*|node()"/
<!-- put the footnotes at the end
if there is no a:references directive -->
<s:if test="not(descendant::a:references)">
<s:call-template name="references"/>
</s:if>
</s:copy>
</s:template>
<s:template match="a:ref">
<s:variable
name="number"
select="count(preceding::a:ref) + 1"/>
<a name="ref-{$number}"></a>
<a class="footnote" href="#reference-{$number}">
<s:value-of select="concat('v ',$number)"/>
</a>
</s:template>
<!-- if a:reference is missing, assume it at the end of the body -->
<s:template match="a:references" name="references">
<hr/>
<s:for-each select="//a:ref">
<s:variable name="number" select="count(preceding::a:ref) + 1"/>
<p>
<a name="reference-{$number}"></a>
<a class="footnote" href="#ref-{$number}">
<s:value-of select="concat(' ^',$number)"/>
</a>
<s:apply-templates/>
</p>
</s:for-each>
</s:template>
</s:stylesheet>
|
ソース文書に a:references ディレクティブがあると、references という名前のテンプレートによって、このディレクティブが検出された位置に脚注が挿入されます。a:references ディレクティブがない場合には、body
との突き合わせを行う最初のテンプレートによって同じ references
という名前のテンプレートが呼び出され、body の最後に脚注を追加します。どちらの場合も、脚注の内容が記載され、前方へのリンクが生成されて、そのリンクに上向き矢印が追加されます。
2 番目のテンプレートは a:ref との突き合わせを行い、脚注へのリンクを作成し、そのリンクに下向きの矢印を追加します。脚注には番号がふられます。この場合は脚注の内容は無視されます。
class="footnote" 属性の解決は XSLT 変換の後、XSLT スタイルシート common.xsl の中でリンクされている CSS スタイルシートによって行われます。
リスト 6 のソース文書は a:ref ディレクティブを使用して脚注を作成しています。
リスト 6. ソース文書 (samples/footnote.xml)
<?xml-stylesheet href="footnote.xsl" type="text/xsl"?> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:a="http://sourceforge.net/projects/arbalo/" > <head/> <body> <p> This example looks a little scientific <a:ref> From Latin <em>scientia</em> </a:ref> and academic <a:ref>From Greek akademia</a:ref>. </p> <p> Do you know why? <a:ref> It uses <em>footnotes</em>. </a:ref> </p> <p>Reduce size of window to verify links are generated.</p> </body> </html> |
ターゲット文書の最後には脚注の一覧が含まれています (リスト 7)。
リスト 7. ターゲット文書 (samples/footnote.html)
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://www.w3.org/1999/xhtml"
xmlns:a="http://sourceforge.net/projects/arbalo/">
<head><link type="text/css" rel="stylesheet" href="common.css"/></head>
<body>
<p>This example looks a little scientific
<a name="ref-1"/><a href="#reference-1" class="footnote">v 1</a>
and academic.
<a name="ref-2"/><a href="#reference-2" class="footnote">v 2lt;/a>
</p>
<p>Do you know why?
<a name="ref-3"/><a href="#reference-3" class="footnote">v 3</a>
</p>
<p>Reduce size of window to verify links are generated.</p>
br/><br/>
<hr/>
<p><a name="reference-1"/><a href="#ref-1" class="footnote"> ^1</a>
From Latin
<em>scientia</em>
</p>
<p><a name="reference-2"/>
<a href="#ref-2" class="footnote"> ^2</a>From Greek akademia</p>
<p><a name="reference-3"/><a href="#ref-3" class="footnote"> ^3</a>
It uses
<em>footnotes</em>.
</p>
</body>
</html>
|
他のソース文書の一部を参照することもできます。a:include ディレクティブによって別のソース文書の要素を含め、その要素を変換することができます (リスト 8)。
リスト 8. スタイルシート (samples/include.xsl の抜粋)
<s:stylesheet xmlns="http://www.w3.org/1999/xhtml" xmlns:a="http://sourceforge.net/projects/arbalo/" xmlns:s="http://www.w3.org/1999/XSL/Transform" version="1.0" > <s:import href="common.xsl"/> <s:template match="a:include"> <s:choose> <s:when test="0!=string-length(@src)"> <s:apply-templates select="document(@src)//*[@id=current()/@refid]"/> </s:when> <s:when test="not(@src) and //a:default[1]/@src"> <s:apply-templates select="document(//a:default[1]/@src)//*[@id=current()/@refid]"/> </s:when> <s:when test="0=string-length(@src) or not(//a:default[1]/@src)"> <s:apply-templates select="//*[@id=current()/@refid]"/> </s:when> </s:choose> </s:template> </s:stylesheet> |
ソース文書の a:include ディレクティブによって、任意のソース文書の要素の id が参照されます。その要素が含まれている文書の名前は src
属性で指定することができます。src 属性がない場合には a:default ディレクティブの src 属性が使用されます。どこにも
src 属性がない場合には、同じソース文書が使用されます。そのため、id を refid で参照することによって無限の再帰を防ぎます。
インポートされる要素は複合型の場合があり、インポートされた後で (apply-templates によって) 変換されます。リスト 9、リスト 10、リスト 11 に例を示します。
リスト 9. ソース文書 (samples/include.xml)
<?xml-stylesheet href="include.xsl" type="text/xsl"?> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:a="http://sourceforge.net/projects/arbalo/"> <head> <a:default src="includedY.xml"/> </head> <body> <p>The following text is included:</p> <a:include refid="x" src="includedX.xml"/> <a:include refid="y1"/> <p id="i">double</p> <a:include refid="y2"/> <a:include refid="i" src=""/> </body> </html> |
リスト 10. ソース文書の一部 (samples/includeY.xml)
<h2 id="y2">I'm the <em>included</em> h2</h2> <h1 id="y1">I'm the <em>included</em> h1</h1> |
リスト 11. ターゲット文書 (samples/include.html)
<body> <p>The following text is included:</p> <p id="x">I'm the <em>included</em> paragraph.</p> <h1 id="y1">I'm the <em>included</em> h1</h1> <p id="i">double</p> <h2 id="y2">I'm the <em>included</em> h2</h2> <p id="i">double</p> </body> </html> |
例えば、数ページで構成されるプレゼンテーションがあり、マスター文書には各ページの見出しとページ見出しへのリンクが含まれている、という場合を考えてみてください。こうした場合に完全なナビゲーションを作成することができます。つまり各ページからは、前のページに戻ることと次のページに進むことができる他に、別の任意のページに進むこともできます。この記事ではその詳細については説明しませんが、「参考文献」にはマスター文書を使用する HTML プレゼンテーションへのリンクを挙げてあります。.xml を .html で置き換えるとコンパイル後のプレゼンテーションが表示されます。整然とした .xml のソースをブラウザーで表示してみると、いかに大量の内容が生成されたかに驚くはずです。
インタープリター方式では、ページは XML (ファイル拡張子が .xml、コンテンツ・タイプが text/xml または application/xml) であり、処理命令の参照先の XSLT スタイルシートがブラウザーで実行されます。
コンパイル方式では、ページ要求の直前に開発環境またはサーバーで XML から変換された HTML (ファイル拡張子が .html、コンテンツ・タイプが text/xml) をブラウザーが認識します。有名な XSLT プロセッサーとして Xalan と Saxon があります。
今後はインタープリター方式が主流になるはずです。最近のブラウザーはすべて XSLT をサポートしており、またインタープリター方式には以下のような利点があります。
- テストの際、即座に結果を得ることができます。テスト対象の各ブラウザーで単純に F5 を押すと、ソース・ページや CSS、XSLT といったスタイルシートに対する変更が反映されます。
- クライアントに転送される情報量を減らすことができます。
- クライアントでは簡単な内容が追加される前の簡潔で整然とした Web ページを確認することができます。
ただし以下の欠点も考慮する必要があります。
- XSLT をサポートしない古いブラウザーがあるかもしれません。制御された環境 (イントラネット) にページを公開する場合には、この問題はありません。
- 最近の一部のブラウザーでは、XSLT スタイルシートが別のディレクトリーの別のスタイルシートを参照できないようにしています。
- XSLT を SVG や iframe といった他の機能と組み合わせると、一部のブラウザーで問題が発生する可能性があります。
- ほとんどのブラウザーは XSLT 2.0 やこれからリリースされる XSLT 3.0 をサポートしていないため、新しい機能を使用することができません。XPath 2.0 の
if () then … elseを使用することはできず、ユーザーが XPath 関数を定義することもできません。
コンパイル方式の場合もインタープリター方式の場合も、ページに対する他の変換 (CSS や JavaScript) は XSLT 変換の後で実行されます。
この記事では XSLT スタイルシートを使用して XHTML 文書に簡単な内容を追加する方法を説明しました。この記事の例を出発点として使用することで、皆さん独自の XSLT スタイルシートを作成することができます。
| 内容 | ファイル名 | サイズ | ダウンロード形式 |
|---|---|---|---|
| Article, and samples, as XML. 1 | xsl-stylesheets.zip | 29KB | HTTP |
注
- ダウンロード・ファイルには以下の内容が含まれています。
- XSLT スタイルシートを使用した、歴史に関するプレゼンテーションの例 (ドイツ語ですが、他の任意の言語に翻訳するためのリンクが XSLT フレームワークによって生成されます) http://zocher-regel.gmxhome.de/ArbaloSchlacht/11Drusus.xml
- 同じファイルですが、XHTML にコンパイルされています。http://zocher-regel.gmxhome.de/ArbaloSchlacht/11Drusus.html
- この記事で使用した XSLT フレームワークの説明。その説明対象となっている XSLT フレームワークを使用しています。http://home.arcor.de/juergen.regel/Arbalo/index.xml
- W3C の XML Path Language (XPath): http://www.w3.org/TR/xpath/
- W3C の XSL Transformations (XSLT): http://www.w3.org/TR/xslt
学ぶために
- developerWorks の Web development
ゾーン: Web ベースのさまざまなソリューションを解説した記事が豊富に用意されています。Web development 技術文書一覧に用意された、さまざまな技術記事やヒント、チュートリアル、技術標準、IBM Redbooks をご覧ください。
- さまざまな IBM 製品や IT 業界のトピックに焦点を絞った developerWorks
の Technical events and webcasts で最新情報を入手してください。
- IBM の研修コース「Introduction to XML and Related
Technologies」を通じて、XML の基礎および XML スキーマ、XSLT、XQuery 照会言語などの高度な技術に関するスキルを身につけてください。教室およびオンラインで受講することができます。
- 無料の developerWorks
Live! briefing に参加して、IBM の製品およびツールについての情報や IT 業界の動向についての情報を迅速に把握してください。
- developerWorks は Twitter を利用しています。今すぐ developerWorks のツイートをフォローしてください。
- developerWorks On demand
demos をご覧ください。初心者のための製品インストール方法やセットアップのデモから、上級開発者のための高度な機能に至るまで、多様な話題が解説されています。
- developerWorks の Technical events
and webcasts: 最新情報を入手してください。
製品や技術を入手するために
- IBM 製品の評価版: IBM
製品の評価版をダウンロードするか、あるいは IBM SOA
Sandbox のオンライン試用版で、DB2、Lotus、Rational、Tivoli、WebSphere などが提供するアプリケーション開発ツールやミドルウェア製品を試してみてください。
議論するために
- developerWorks コミュニティー: ここでは他の developerWorks ユーザーとのつながりを持てる他、開発者によるブログ、フォーラム、グループ、ウィキを調べることができます。
- Web
開発に関心を持つ他の developerWorks メンバーを見つけてください。