(続き)
■ key()
id(),idref()がDTDや、特別な属性名を必要とするのに対して、key()関数はそのような制約がありません.key()はXSL1.0からあり、<xsl:key>でキーを定義し、key()でキー値を指定してノードを取得する方法をとります.XSLT2.0では、<xsl:key>にコレーションを指定できるようになり、また、key()関数では検索のtopノードを指定できるようになりました.これは便利な機能です.
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>
<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: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>
<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()がテンポラリツリーにも使えるようになったのはすごいと思います.