スタイルシートをモジュール化するXSLTスタイルシート書き方講座(応用編1)

» 2001年12月19日 00時00分 公開
[奥井康弘, 吉田稔, 青木秀起株式会社日本ユニテック]

XSLTがW3C勧告となってから早2年がたち、XSLT機能を内蔵したツールも充実してきました。XSLTの利用目的として、XML文書をHTML化して“見せる”ためだけでなく、データの“変換”機能がビジネスで活用されるようになっています。「XSLTスタイルシート書き方講座」の新シリーズ「応用編」では、ビジネスへの応用を意識した、複雑で柔軟なデータ変換機能について考えてみましょう。

モジュール化する、とはどういうことか?

 応用編の第1回は、「XSLTスタイルシートのモジュール化」です。大規模で複雑なスタイルシートをいくつかのモジュールに分割すれば、開発や保守が簡単になります。また共通して使う機能をモジュールとして切り分ければ、部品として流用できるので開発効率を上げることができます。今回は、複数のXSLTスタイルシートを組み合わせるための機能を説明します。

モジュール化の利点とは?

 まず下のイメージ図をご覧ください。

図1 スタイルシートのモジュール化によってできること 図1 スタイルシートのモジュール化によってできること

 複雑で大きなスタイルシートを1ファイルにまとめて作成すると、開発するのも変更などの保守を行うのも大変です。しかし、図1のように、スタイルシートをいくつかのモジュールに分割すれば、開発や保守もかなり楽になります。図1では、A氏とB氏に分割してスタイルシートの開発を依頼し、それらをメインのスタイルシートに取込んでいます。こうすれば開発や改変などの保守を複数の人が分担して行うことができます。また、このように開発されたモジュール化スタイルシートをほかの部課で利用することも可能になります。

 例えば、製品開発第1課で開発した製品データベースのスタイルシートを、第3営業部で流用することもできるようになります。さらに、XSLTの機能をフル活用すれば、改変を効率的に行うことができます。というのも、改変したい部分だけを元のスタイルシートに上書きするかのように読込めるのです。

includeとimport

 これらを実現するのが、今回ご紹介する以下の2つの要素です。

  1. インクルード (xsl:include)
  2. インポート (xsl:import)

 この2つの要素を使ってどのようにスタイルシートを取込むのでしょうか。両者の機能上の違いはどこにあるのでしょうか。使い分けることにより何が可能になるのでしょうか。順に解説いたします。

スタイルシートの取込み
── xsl:includeとxsl:importの共通機能

<xsl:include>の書き方

 スタイルシートの中でxsl:include要素またはxsl:import要素を書くと、参照先スタイルシートを取込むことができます。xsl:includeを例に取ると、書き方は以下のとおりです。

xsl:includeの書き方
<xsl:include href=インクルードされるスタイルシートのURI参照/>
(注)href属性は必須


 参照先スタイルシートは、スタイルシートとして完全な形をしていなければなりません。つまり、xsl:stylesheet要素を持っていなければなりません。従って参照先スタイルシートを取込むとは、正確にいうと参照先スタイルシートのxsl:stylesheet要素の子要素以下がxsl:include要素に置き換えられるということです。

図2 xsl:stylesheetの子要素以下がインクルードされる 図2 xsl:stylesheetの子要素以下がインクルードされる

スタイルシート取込みの例

 スタイルシートがどのように取込まれるかイメージをつかんでいただくため、リスト1に示す書評のXMLデータ“reviews.xml”を使った例を示しましょう。このXMLデータをWeb表示させるためのXSLTスタイルシート“web-sheet.xsl”をリスト2に示します。

<?xml version="1.0" encoding="shift_jis"?>
<?xml:stylesheet type="text/xsl" href="web-sheet.xsl"?>
<reviews>
  <book>
    <title>詳説-XML Schema</title>
    <price>2500</price>
    <review>世界標準スキーマ言語のすべてを網羅。待望の一冊!</review>
  </book>
  <book>
    <title>Webサービス構築のためのSOAP入門</title>
    <price>2000</price>
    <review>アプリケーション間通信プロトコルSOAPの入門書。</review>
  </book>
  <book>
    <title>XQuery概説</title>
    <price>1500</price>
    <review>2001年6月に草案が出たばかりのXML照会言語の概要を知るのに好適。</review>
  </book>
</reviews>
リスト1 書評のXMLデータ“reviews.xml”

<?xml version="1.0" encoding="Shift_jis"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:include href="booklist.xsl"/>
  <xsl:template match="/">
    <html>
      <body>
        <xsl:apply-templates/>
      </body>
    </html>
  </xsl:template>
  <xsl:template match="reviews">
    <h2>書評一覧</h2>
    <xsl:apply-templates/>
  </xsl:template>
</xsl:stylesheet>
リスト2 適用されるXSLTスタイルシート“web-sheet.xsl”

 リスト2で、ほかのXSLTスタイルシートをインクルードしているところを以下に抜き出しました。

<xsl:include href="booklist.xsl"/>

参照されているスタイルシート“booklist.xsl”

 上記の例では、書評一覧の本体は別のスタイルシート“booklist.xsl”を参照しています。こうしておくことで、書評一覧を表や個条書きのような別の形式に変えたい場合に、参照元のスタイルシートを変更することなく、参照先スタイルシートを変えるだけで済むので簡単です。その参照先スタイルシート“booklist.xsl”を、リスト3に示します。

<?xml version="1.0" encoding="Shift_jis"?>
  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="book">
      <ul>
        <xsl:apply-templates/>
      </ul>
    </xsl:template>
    <xsl:template match="title">
      <li>
        <xsl:value-of select="."/>
      </li>
    </xsl:template>
    <xsl:template match="price">
      <li>
        <xsl:value-of select="."/>
      </li>
    </xsl:template>
    <xsl:template match="review">
      <li><xsl:value-of select="."/>
    </li>
  </xsl:template>
</xsl:stylesheet>
リスト3 個条書きで表示する場合の参照先スタイルシート“booklist.xsl”

実際に取込まれた結果を見る

 リスト1に示したXMLデータにリスト2のスタイルシートを適用した結果をInternet Explorerで表示した画面を示します。前回までの記事と同様、MSXML3.0がインストールされている環境での実行結果です。

画面1 IE5.0による書評一覧の表示結果 画面1 IE5.0による書評一覧の表示結果

xsl:includeとxsl:importを記述する位置

 xsl:include要素もxsl:import要素も、xsl:stylesheet要素の子要素でなければなりません。例えば、リスト4に示したような位置にxsl:include要素を書くことができます。

注:xsl:stylesheet要素の子要素のことを「トップレベル要素」といいます。

<?xml version="1.0" encoding="shift_jis"?>
<xsl:stylesheet xmlns:xsl="http://……>
  <xsl:include href="http://www.AAA.co.jp/dev/parts/part1.xsl"/>
  <xsl:template match="/">
    <html>
      <xsl:apply-templates />
    </html>
  </xsl:template>
  ……
リスト4 xsl:includeの正しい位置

 一方、リスト5の位置はエラーになります。ルート要素であるxsl:stylesheet要素の子要素xsl:template要素の、さらに子要素としてxsl:include要素が記述されていて、トップレベル要素になっていないからです。

<?xml version="1.0" encoding="shift_jis"?>
<xsl:stylesheet xmlns:xsl="http://……>
  <xsl:template match="/">
    <xsl:include href="http://www.AAA.co.jp/dev/parts/part1.xsl"/>
    <html>
      <xsl:apply-templates />
    </html>
  </xsl:template>
    ……
リスト5 xsl:includeの誤った位置

 なお、自分自身をインクルードすることはエラーになります。また同じスタイルシートを2度以上インクルードすることもエラーになります。参照先のスタイルシートがさらに別のスタイルシートを参照していく深い階層構造の場合、インクルードの重複に注意する必要があります。

xsl:importはxsl:includeとどこが異なるか?

 先ほどはxsl:includeの例を見ましたが、こんどはxsl:importについて解説していきます。xsl:importは、以下の2つの点でxsl:includeとは異なっています。

(1)取込むスタイルシートに優先順位が付けられる
xsl:includeは単なる置き換えなので、 複数のスタイルシートが競合してしまうことがあり得ます。しかし、xsl:importの場合、参照元スタイルシートと参照先スタイルシートの間に重複がある場合、参照元スタイルシートの定義やテンプレートルールが優先されます。3つ以上のスタイルシートがインポートされる場合の優先順位については、W3CによるXSLT 1.0の勧告を参照してください。

(2)位置に関する制約がある
xsl:import要素は、xsl:stylesheet要素の子要素の先頭に位置しなければなりません。一方、xsl:include要素は、トップレベル要素であれば任意の場所に置くことができます。リスト6のスタイルシートでは、xsl:import要素が正しい位置にきています。

<?xml version="1.0" encoding="shift_jis"?>
<xsl:stylesheet xmlns:xsl="http://……>
  <xsl:import href="http://www.AAA.co.jp/……
  <xsl:include href="http://www.BBB.co.jp/……
  <xsl:include href="http://www.CCC.co.jp/……
  <xsl:template match="/">
  ……

リスト6 xsl:importの正しい位置

 一方、リスト7の位置はエラーになります。xsl:import要素に先行するxsl:include要素が1つあるからです。

<?xml version="1.0" encoding="shift_jis"?>
<xsl:stylesheet xmlns:xsl="http://……>
  <xsl:include href="http://www.BBB.co.jp/……
  <xsl:import href="http://www.AAA.co.jp/……
  <xsl:include href="http://www.CCC.co.jp/……
  <xsl:template match="/">
  ……

リスト7 xsl:importの誤った位置

スタイルシートの保守性を高める
── xsl:include要素とxsl:import要素の組み合わせ

 例に使っている「書評一覧」の本のタイトルをもっと分かりやすい見出しにして、下線を引きたいとしましょう。既存のスタイルシートをコピーして一部を改変して新しいスタイルシートを作成することもできますが、保守性からいってそれは好ましくありません。将来、既存のスタイルシートに修正が入った場合、新しい方のスタイルシートにも同じ修正をいれなければならなくなるからです。むしろ既存のスタイルシートをいったん読込んだ後、改変したい部分だけを上書きする仕組みがあると便利です。xsl:import要素とxsl:include要素を組み合わせるとそれが実現できます。

既存のスタイルシートに上書きする

 まず改変したいテンプレートルールをリスト8に示すスタイルシート“modified.xsl”に集めます。それからリスト9のように、xsl:import要素で元のスタイルシート全体(リスト3)をいったん参照します。続いてxsl:include要素で改変する部分だけのスタイルシート(リスト8)を読込みます。

 するとxsl:include要素で読込んだスタイルシート(リスト8)の方が優先度が高いため、重複するテンプレートはリスト8のテンプレートで上書きされたかのようになります。こうして保守性の高いスタイルシートを書くことができました。リスト9のスタイルシートの適用結果を画面2に示します。

<?xml version="1.0" encoding="Shift_jis"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="title">
    <h3>
      <u>
         <xsl:value-of select="."/>
      </u>
    </h3>
  </xsl:template>
</xsl:stylesheet>

リスト8 改変する部分だけを集めたスタイルシート“modified.xsl”

<?xml version="1.0" encoding="Shift_jis"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:import href="booklist.xsl"/>
  <xsl:include href="modified.xsl"/>
  <xsl:template match="/">
    <html>
      <body>
        <xsl:apply-templates/>
      </body>
    </html>
  </xsl:template>
  <xsl:template match="reviews">
    <h2>書評一覧</h2>
    <xsl:apply-templates/>
  </xsl:template>
</xsl:stylesheet>
リスト9 xsl:import要素とxsl:include要素を組み合わせたスタイルシート“web-sheet.xsl”

画面2 IE5.0による書評一覧の表示結果 画面2 IE5.0による書評一覧の表示結果

 今回は、XSLTのモジュール化手法を使って保守性の高いスタイルシートの書き方を説明しました。次回は、複数のXMLデータを処理する方法や相互参照の仕方を取り上げます。

本記事は、日本ユニテック発行のXMLテクノロジー総合情報誌「Digital Xpress」に掲載された、XSLT特集「XSLTの実力を探る!」の内容をもとに、加筆修正したものです。



Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。