XSLT 2.0で便利になった機能(22) Nodeをサーチする関数 (その2)

(続き)
 
■ key()
id(),idref()がDTDや、特別な属性名を必要とするのに対して、key()関数はそのような制約がありません.key()はXSL1.0からあり、<xsl:key>でキーを定義し、key()でキー値を指定してノードを取得する方法をとります.XSLT2.0では、<xsl:key>にコレーションを指定できるようになり、また、key()関数では検索のtopノードを指定できるようになりました.これは便利な機能です.
例えば今回紹介したid()の入力データに対して次のようなキーを定義したとします.
 
<xsl:key name="trans" match="transaction" use="@tid"/>
 
これに対して次のテンプレート
 
<xsl:template match="/">
    <xsl:message>key('trans','tr_005',/shipping-list/shipping[2])/@name="<xsl:value-of select="key('trans','tr_005',/shipping-list/shipping[2])/@name"/>"</xsl:message>
</xsl:template>
 
は、以下を出力します.3番目のtopノードパラメータとしてshipping[2]を指定しているので"banana"が表示されます.
 
key('trans','tr_005',/shipping-list/shipping[2])/@name="banana"
 
id()と異なり、xsl:key要素とkey()の組み合わせは自由度が高いのが特徴ですね.
また余談ですが、テンポラリツリーで本当にkey()が使えるのか試してみました.上記と同じキー定義で、次のようにします.
 
<xsl:key name="trans" match="transaction" use="@tid"/>
<xsl:variable name="tempTree" as="document-node()">
    <xsl:document>
        <shipping-list>
            <shipping month="9">
                <transaction tid="tr_001" name="melon"  count="20"/>
                <transaction tid="tr_002" name="apple"  count="40"/>
                <transaction tid="tr_003" name="orange" count="10"/>
                <transaction tid="tr_005" name="pear"   count="30"/>
            </shipping>
            <shipping month="10">
                <transaction tid="tr_011" name="grape"  count="20"/>
                <transaction tid="tr_012" name="apple"  count="40"/>
                <transaction tid="tr_013" name="orange" count="10"/>
                <transaction tid="tr_005" name="banana" count="30"/>
            </shipping>
        </shipping-list>
    </xsl:document>
</xsl:variable>
 
これに対して、以下のテンプレートは
 
<xsl:template match="/">
    <xsl:message>key('trans','tr_011',$tempTree)/@name="<xsl:value-of select="key('trans','tr_011',$tempTree)/@name"/>"</xsl:message>
</xsl:template>
 
次を出力します.
 
key('trans','tr_011',$tempTree)/@name="grape"
 
<xsl:key>, key()がテンポラリツリーにも使えるようになったのはすごいと思います.