忘れていましたが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>
<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>
<!-- 目的の処理 -->
</xsl:if>
<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"
>
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="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>
<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>
<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>
<!-- 目的の処理 -->
</xsl:if>
だけでできてしまうのですから、お涙頂戴ものですね.テンポラリツリー、ぜひ活用したいものです.