XSLT2.0の感覚

Written byがいすと

4 ユーザー定義関数

XSLTにおいても、他のプログラミング言語と同じく、ソースが大きくなればなるほど、メンテナンスを容易にするために処理を部分に分割する必要があります。そのために、XSLT1.0では名前付きテンプレート(xsl:template name)を使います。

ある文字列にカッコを付加する(fooを(foo)にする)ルーチンを考えます。XLST1.0で実装すると以下のようになります。

<xsl:template name="AddParentheses">
  <xsl:param name="s"/>
  <xsl:value-of select="concat('(',$s,')')"/>
</xsl:template>

<xsl:template name="Foo">
  <output>
    <xsl:call-template name="AddParentheses">
      <xsl:with-param name="s" select="'foofoo'"/>
    </xsl:call-template>
  </output>
</xsl:template>

[result]
<output>(foofoo)</output>

名前付きFooテンプレートから、AddParenthesesテンプレートを呼び出しています。パラメータとなる文字列はwith-paramで渡し、paramで受け取っています。

XSLT2.0では、新たにxsl:functionというエレメントが用意されました。これは、XPathの組み込み関数と同じように、返値のある関数を作成できる機能です。返値はvalue-of, copy-ofなどではなく、新設されたxsl:returnエレメントで定義します。

例として、上記の例のAddParenthesesをxsl:functionで定義してみましょう。

<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:mp="http://www.din.or.jp/~toruj"
  exclude-result-prefixes="mp">

<xsl:function name="mp:AddParentheses">
  <xsl:param name="s"/>
  <xsl:result select="concat('(',$s,')')"/>
</xsl:function>

xsl:functionは適当なnamespaceを明示する必要があるので注意してください。この例ではこのホームページのアドレスをURIとするnamespace mpを定義し、過剰なnamespaceの出力をexclude-result-prefixesで抑制しています。

では定義した関数を呼び出してみましょう。呼び出しは組み込みのXPath関数と同じように行います。

<xsl:template name="Foo">
  <output>
    <xsl:value-of select="mp:AddParentheses('foofoo')"/>
  </output>
</xsl:template>


[result]
<output>(foofoo)</output>

名前付きテンプレートの欠点として、そのテンプレートが何らかのnodeの操作を行うのか、それとも単に値を出力するだけのかをうまく区別できないことがあげられます。後者にあたるテンプレートをxsl:functionにすることで、両者を区別できるという点ではメリットがあるのではないでしょうか。とはいえ、この時点で関数プログラミングと手続きプログラミングがごっちゃになっている気がするのは私だけでしょうか?