ノードをサーチする機能を持った関数について紹介します.
■ id()
id()は、xs:stringをパラメータとして、それをID値とする要素を返します.XSLT2.0ではこれに、ドキュメントノードを表すnode()がパラメータとして追加されました.復習になりますが、id()関数を有効とするためには、属性がIDとして定義されていることをXSLTプロセッサに知らせてやらねばなりません.つまりDTDが必要でした.例えば、
id()は、xs:stringをパラメータとして、それをID値とする要素を返します.XSLT2.0ではこれに、ドキュメントノードを表すnode()がパラメータとして追加されました.復習になりますが、id()関数を有効とするためには、属性がIDとして定義されていることをXSLTプロセッサに知らせてやらねばなりません.つまりDTDが必要でした.例えば、
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE shipping-list [
<!ELEMENT shipping-list (shipping*) >
<!ELEMENT shipping (transaction+) >
<!ATTLIST shipping month CDATA #REQUIRED>
<!ELEMENT transaction EMPTY >
<!ATTLIST transaction tid ID #REQUIRED
name CDATA #REQUIRED
count CDATA #REQUIRED>
]>
<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>
<!DOCTYPE shipping-list [
<!ELEMENT shipping-list (shipping*) >
<!ELEMENT shipping (transaction+) >
<!ATTLIST shipping month CDATA #REQUIRED>
<!ELEMENT transaction EMPTY >
<!ATTLIST transaction tid ID #REQUIRED
name CDATA #REQUIRED
count CDATA #REQUIRED>
]>
<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>
というような入力XMLデータ(validではありません)に対して、
<xsl:template match="/">
<xsl:message>id('tr_003')/@name="<xsl:value-of select="id('tr_003')/@name"/>"</xsl:message>
</xsl:template>
<xsl:message>id('tr_003')/@name="<xsl:value-of select="id('tr_003')/@name"/>"</xsl:message>
</xsl:template>
のようなテンプレートは、id('tr_003')/@name="orange" と表示します.またtidがユニークでない場合、id('tr_005')/@name="pear"を表示します.このような場合、最初のものが採用されるように「寛容」な仕様になっています.
XSLT2.0によって追加された、2番目のパラメータにより、document()またはdoc()で複数の入力がある場合に、どちらでも自由に選択できるようになりました.
余談ですがテンポラリツリーでこの機能を試してみました.
<xsl:variable name="tempTree" as="document-node()">
<xsl:document>
<shipping-list>
<shipping month="9">
<transaction xml:id="tr_001" name="melon" count="20"/>
<transaction xml:id="tr_002" name="apple" count="40"/>
<transaction xml:id="tr_003" name="orange" count="10"/>
<transaction xml:id="tr_005" name="pear" count="30"/>
</shipping>
<shipping month="10">
<transaction xml:id="tr_011" name="grape" count="20"/>
<transaction xml:id="tr_012" name="apple" count="40"/>
<transaction xml:id="tr_013" name="orange" count="10"/>
<transaction xml:id="tr_005" name="banana" count="30"/>
</shipping>
</shipping-list>
</xsl:document>
</xsl:variable>
<xsl:document>
<shipping-list>
<shipping month="9">
<transaction xml:id="tr_001" name="melon" count="20"/>
<transaction xml:id="tr_002" name="apple" count="40"/>
<transaction xml:id="tr_003" name="orange" count="10"/>
<transaction xml:id="tr_005" name="pear" count="30"/>
</shipping>
<shipping month="10">
<transaction xml:id="tr_011" name="grape" count="20"/>
<transaction xml:id="tr_012" name="apple" count="40"/>
<transaction xml:id="tr_013" name="orange" count="10"/>
<transaction xml:id="tr_005" name="banana" count="30"/>
</shipping>
</shipping-list>
</xsl:document>
</xsl:variable>
これに対して、
<xsl:template match="/">
<xsl:message>id('tr_011',$tempTree)/@name="<xsl:value-of select="id('tr_011',$tempTree)/@name"/>"</xsl:message>
</xsl:template>
<xsl:message>id('tr_011',$tempTree)/@name="<xsl:value-of select="id('tr_011',$tempTree)/@name"/>"</xsl:message>
</xsl:template>
■ idref()
idref()は、xs:stringをパラメータとして、それをIDREF, IDREFS値とするノードを返します.XSLT1.0ではこの関数はありませんでした.XSLT2.0では、id()と同様にドキュメントノードを表すnode()がパラメータとしてあります.
idref()は、xs:stringをパラメータとして、それをIDREF, IDREFS値とするノードを返します.XSLT1.0ではこの関数はありませんでした.XSLT2.0では、id()と同様にドキュメントノードを表すnode()がパラメータとしてあります.
例えば家族を表現する次のようなXMLデータがあるとします
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE family [
<!ELEMENT family (person*) >
<!ELEMENT person (name,(spouse|child|parent)*) >
<!ATTLIST person id ID #REQUIRED>
<!ELEMENT name (#PCDATA)>
<!ELEMENT spouse EMPTY>
<!ATTLIST spouse ref IDREF #REQUIRED>
<!ELEMENT child EMPTY>
<!ATTLIST child ref IDREFS #REQUIRED>
<!ELEMENT parent EMPTY>
<!ATTLIST parent ref IDREFS #REQUIRED>
]>
<family>
<person id="p_001">
<name>Akio Ito</name>
<spouse ref="p_002"/>
<child ref="p_004"/>
</person>
<person id="p_002">
<name>Mie Ito</name>
<spouse ref="p_001"/>
<child ref="p_004"/>
</person>
<person id="p_003">
<name>Yukie Ito</name>
<spouse ref="p_004"/>
<child ref="p_005 p_006 p_007"/>
</person>
<person id="p_004">
<name>Toshikazu Ito</name>
<parent ref="p_001 p_002"/>
<spouse ref="p_003"/>
<child ref="p_005 p_006 p_007"/>
</person>
<person id="p_005">
<name>Kouichiro Ito</name>
<parent ref="p_003 p_004"/>
</person>
<person id="p_006">
<name>Tomomi Ito</name>
<parent ref="p_003 p_004"/>
</person>
<person id="p_007">
<name>Natumi Ito</name>
<parent ref="p_003 p_004"/>
</person>
</family>
<!DOCTYPE family [
<!ELEMENT family (person*) >
<!ELEMENT person (name,(spouse|child|parent)*) >
<!ATTLIST person id ID #REQUIRED>
<!ELEMENT name (#PCDATA)>
<!ELEMENT spouse EMPTY>
<!ATTLIST spouse ref IDREF #REQUIRED>
<!ELEMENT child EMPTY>
<!ATTLIST child ref IDREFS #REQUIRED>
<!ELEMENT parent EMPTY>
<!ATTLIST parent ref IDREFS #REQUIRED>
]>
<family>
<person id="p_001">
<name>Akio Ito</name>
<spouse ref="p_002"/>
<child ref="p_004"/>
</person>
<person id="p_002">
<name>Mie Ito</name>
<spouse ref="p_001"/>
<child ref="p_004"/>
</person>
<person id="p_003">
<name>Yukie Ito</name>
<spouse ref="p_004"/>
<child ref="p_005 p_006 p_007"/>
</person>
<person id="p_004">
<name>Toshikazu Ito</name>
<parent ref="p_001 p_002"/>
<spouse ref="p_003"/>
<child ref="p_005 p_006 p_007"/>
</person>
<person id="p_005">
<name>Kouichiro Ito</name>
<parent ref="p_003 p_004"/>
</person>
<person id="p_006">
<name>Tomomi Ito</name>
<parent ref="p_003 p_004"/>
</person>
<person id="p_007">
<name>Natumi Ito</name>
<parent ref="p_003 p_004"/>
</person>
</family>
これに対して
<xsl:variable name="idref" select="idref('p_003')"/>
は、"p_003"をIDREF, IDREFSとして持つ属性ノード(この場合は@ref)を返します.ですから、
<xsl:template match="/">
<xsl:variable name="idref" select="idref('p_003')"/>
<xsl:for-each select="$idref">
<xsl:message>no=<xsl:value-of select="position()"/> name="<xsl:value-of select="parent::*/parent::person/name"/>"</xsl:message>
</xsl:for-each>
</xsl:template>
<xsl:variable name="idref" select="idref('p_003')"/>
<xsl:for-each select="$idref">
<xsl:message>no=<xsl:value-of select="position()"/> name="<xsl:value-of select="parent::*/parent::person/name"/>"</xsl:message>
</xsl:for-each>
</xsl:template>
は、次を出力します.
no=1 name="Toshikazu Ito"
no=2 name="Kouichiro Ito"
no=3 name="Tomomi Ito"
no=4 name="Natumi Ito"
no=2 name="Kouichiro Ito"
no=3 name="Tomomi Ito"
no=4 name="Natumi Ito"
(続く)