テンプレートルールを複数定義する

テンプレートルールは複数定義することができます。

前回のサンプルでは、XML文書全体(「/」要素)に適用されるテンプレートルールのみを作成しましたが、2つ以上のテンプレートルールが含まれるスタイルシートを作成することも可能です。

複数のテンプレートルール

単純なスタイルシートであれば、XML文書全体に適用されるテンプレートルールのみひとつでも十分事足りるのですが、複雑なスタイルシートを作成する場合は、ある要素で別のテンプレートルールとした方が簡潔に記述できる場合が多々あります。

テンプレートから別のテンプレートルールを呼ぶ

テンプレートから別のテンプレートルールを呼ぶサンプル(①)は以下になります。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="UTF-8" />
    <xsl:template match="/">
        <html>
        <head>
        <title><xsl:text>ゲーム所持リスト</xsl:text></title>
        <link rel="stylesheet" type="text/css" href="sample02.css"/>
        </head>
        <h1 class="sample"><xsl:text>ゲーム所持リスト</xsl:text></h1>
        <table class="sample">
        <tr>
            <th>ゲームタイトル</th>
            <th><xsl:text>購入日</xsl:text></th>
            <th><xsl:text>購入価格</xsl:text></th>
        </tr>
        <xsl:apply-templates select="ゲーム所持リスト" />
        </table>
        </html>
    </xsl:template>
    <xsl:template match="ゲーム所持リスト">
        <xsl:for-each select="ゲーム情報">
        <tr>
            <td><xsl:value-of select="ゲームタイトル" /></td>
            <td><xsl:value-of select="購入日" /></td>
            <td><xsl:value-of select="購入価格" /></td>
        </tr>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

XSLTスタイルシートが呼ばれると、まず初めに「/」要素に適用されるテンプレートルールが処理されます。ここまでは前回のサンプルと変わりません。ただ、そのテンプレートには、次の記述が新しく登場しています。

<xsl:apply-templates select="ゲーム所持リスト" />

赤字で記述している<xsl:apply-templates>要素のselect属性には”ゲーム所持リスト”が指定されています。この”ゲーム所持リスト”は、青字の<xsl:template>要素のmatch属性で示している”ゲーム所持リスト”に対応しています。その青字部分には別のテンプレートルールが定義されています。この場合、<xsl:apply-templates>要素が処理されると青字のテンプレートが処理されることになります。

<xsl:apply-templates>要素の書式
<xsl:apply-templates select=”○○○” />

  ~

<xsl:template match=”○○○” [name = “テンプレート名”]>
テンプレートとして出力する各種要素、スタイル
</xsl:template>

<xsl:apply-templates>要素のselect属性と<xsl:template>要素のmatch属性が関連付き、互いにマッチしたテンプレートが呼び出されます。また、<xsl:apply-templates>要素は<xsl:stylesheet>要素の配下にいくつでも記述できます。

なお、前述しましたが、複数テンプレートルールを定義した際も、一番初めに処理される変換対象部分は必ずXML文書全体を示す「/」要素に適用されるテンプレートルールになります。

つまり、上記サンプルでは以下のような順番で処理されます。

①<html>開始タグ、<head>タグ、<title>タグ、<h1>タグを作成する。
②「xsl:apply-templates」を処理する。
select属性で指定したXML文書部分を新しい変換対象とし、次のテンプレートルールの選択および処理を行う。つまり、XML文書の中から「ゲーム所持リスト」要素を新しい変換対象として選び、スタイルシートの中から「ゲーム所持リスト」要素に該当するパターンをもつテンプレートルールを探し出し、そのテンプレートを処理する。

③<html>終了タグを作成する。

という流れになります。
記述方法に少しクセがありますが、よく見ていくと、C言語でいう関数の呼び出しと同じ流れですね。
複数のテンプレートルール

<xsl:apply-template>要素が処理されると、他のテンプレートの処理に移り、そのテンプレートでの処理が終わったらまた元の位置に戻ってくるというわけです。

テンプレートはパターンによって複数回処理される

<xsl:apply-templates>要素のselect属性で指定した要素が複数存在したらどのように処理されるのでしょうか。例えば以下のXSLTスタイルシートを見てください。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="UTF-8" />
    <xsl:template match="/">
        <html>
        <head>
        <title><xsl:text>ゲーム所持リスト</xsl:text></title>
        <link rel="stylesheet" type="text/css" href="sample03.css"/>
        </head>
        <h1 class="sample"><xsl:text>ゲーム所持リスト</xsl:text></h1>
        <table class="sample">
        <tr>
            <th>ゲームタイトル</th>
            <th><xsl:text>購入日</xsl:text></th>
            <th><xsl:text>購入価格</xsl:text></th>
        </tr>
        <xsl:apply-templates select="ゲーム所持リスト/ゲーム情報" />
        </table>
        </html>
    </xsl:template>
    <xsl:template match="ゲーム所持リスト/ゲーム情報">
        <tr>
            <td><xsl:value-of select="ゲームタイトル" /></td>
            <td><xsl:value-of select="購入日" /></td>
            <td><xsl:value-of select="購入価格" /></td>
        </tr>
    </xsl:template>
</xsl:stylesheet>

このXSLTスタイルシートを適用した場合の出力結果は、サンプル①とまったく同じになります。その理由について考えてみましょう。

<xsl:apply-template>要素のselect属性では「ゲーム所持リスト/ゲーム情報」を指定しています。ここで今回のサンプルで使用している変換元のXML文書には「ゲーム情報」要素が3つあることに着目してください。

このような場合、3つの「ゲーム情報」要素について、それぞれに対してテンプレートルールが選択され処理されます。

その結果、3行分の結果が出力されます。

<xsl:for-each>要素によって繰り返しているサンプル①よりも簡潔に記述できていることがわかると思います。このようなことが、テンプレートルールを複数定義することのメリットです。

さて、ここまでのサンプルで出てきた<xsl:apply-template>要素や<xsl:for-each>要素では、XML文書の中から処理対象となるXML文書部分を指定しています。この指定は、XPathという仕様に従っています。次回はそのXPathについて詳しく見ていきます。