XSLT2.0で便利になった機能(4) テンポラリツリーへのアクセス

忘れていましたがXSLT2.0で当たり前になった機能に、テンポラリなツリーを格納した<xsl:variable>をXPath式で参照できるようになったことがあります.この機能、なんの苦もなく使えてしまうので、XSLT1.0の時の苦労を忘れてしまいます.
 
ちょっと復習してみますと、<xsl:variable>は、select属性があるときはその内容に応じた型を持っていました.
 
<xsl:variable name="langJa" select="'ja'"/>  → string
 
<xsl:variable name="isJa" select="$PRM_LANG='ja'"/> →boolean
 
<xsl:variable name="levelMax" select="3"/> →number
 
select属性がないときはテンポラリなツリー、すなわちRTF(Result Tree Fragment)でした.
 
<xsl:variable name="langJa">ja</xsl:variable>
 
だと、"ja"はstringではなく、テキストノードになります.
 
<xsl:variable name="langs">
    <xsl:element name="lang">
        <xsl:text>en</xsl:text>
    </xsl:element>
    <xsl:element name="lang">
        <xsl:text>ja</xsl:text>
    </xsl:element>
</xsl:variable>
 
この例だと、$langs変数は2つの要素を持ちます.
 
くやしいことにXSLT1.0では、次のような書き方ができませんでした.
 
<xsl:if test="string($langs/lang[1])='ja'">
    <!-- 目的の処理 -->
</xsl:if>
 
これでは不便なのでXSLTベンダーは、各種の拡張関数を用意してくれていました.私は幾種類ものXSLTプロセッサで動くスタイルシートを書くため、次のような変数を用意していました.
 
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:exsl="http://exslt.org/common"
  xmlns:msxsl="urn:schemas-microsoft-com:xslt"
  xmlns:xalan="http://xml.apache.org/xalan"
  exclude-result-prefixes="exsl msxsl xalan"
>
<xsl:variable name="Msxsl" select="'msxsl'"/>
<xsl:variable name="Xalan" select="'xalan'"/>
<xsl:variable name="Exslt" select="'exslt'"/>
<xsl:variable name="Saxon" select="'saxon'"/>
<xsl:variable name="nodesetImplementer">
  <xsl:choose>
    <xsl:when test="function-available('msxsl:node-set')">
      <xsl:value-of select="$Msxsl"/>
    </xsl:when>
    <xsl:when test="function-available('xalan:nodeset')">
      <xsl:value-of select="$Xalan"/>
    </xsl:when>
    <xsl:when test="function-available('exsl:node-set')">
      <xsl:value-of select="$Exslt"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="''"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:variable>
 
$nodesetImplementerで、どの拡張関数をつかえるかがわかります.これで、
 
<xsl:choose>
    <xsl:when test="$nodesetImplementer=$Xalan">
        <xsl:if test="string(xalan:nodeset($langs)/lang[1])='ja'">
            <!-- 目的の処理 -->
        </xsl:if>
    <xsl:when>
    <xsl:when test="$nodesetImplementer=$Exslt">
        <xsl:if test="string(exsl:node-set($langs)/lang[1])='ja'">
            <!-- 目的の処理 -->
        </xsl:if>
    <xsl:when>
    <xsl:when test="$nodesetImplementer=$Msxsl">
        <xsl:if test="string(msxsl:node-set($langs)/lang[1])='ja'">
            <!-- 目的の処理 -->
        </xsl:if>
    <xsl:when>
    <xsl:otherwise>
        <!-- サポート外XSLTプロセッサ -->
    </xsl:otherwise>
</xsl:choose>
 
と書くことができます.ここまで苦労したのが、XSLT2.0ではたった
 
<xsl:if test="string($langs/lang[1])='ja'">
    <!-- 目的の処理 -->
</xsl:if>
 
だけでできてしまうのですから、お涙頂戴ものですね.テンポラリツリー、ぜひ活用したいものです.