<choices>
<sic />
<corr />
<reg />
<orig />
</choices>
<choice>
<corr>Red</corr>
<sic>Blue</sic>
<choice>
我想选择<choice>
中的第一个元素,其名称与<choices>
中任何元素的名称相匹配。
如果name(node-set)返回的是名称列表而不是第一个节点的名称,我可以使用
select="choice/*[name() = name(choices/*)][1]"
但它没有(至少不在1.0中),所以我将字符串连接起来并使用contains():
<xsl:variable name="choices.str">
<xsl:for-each select="choices/*">
<xsl:text> </xsl:text><xsl:value-of select="concat(name(),' ')"/>
</xsl:for-each>
</xsl:variable>
<xsl:apply-templates select="choice/*[contains($choices.str,name())][1]"/>
得到我想要的东西:
Red
,<corr>
有更简单的方法吗?
答案 0 :(得分:2)
<强>予。使用此XPath 2.0单行:
/*/choice/*[name() = /*/choices/*/name()][1]
当针对以下XML文档评估此XPath表达式(提供的那个,但已更正为成为格式良好的XML文档):
<t>
<choices>
<sic />
<corr />
<reg />
<orig />
</choices>
<choice>
<corr>Red</corr>
<sic>Blue</sic>
</choice>
</t>
选择了正确的元素:
<corr>Red</corr>
<强> II。 XSLT 1.0(没有密钥!):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vNames">
<xsl:for-each select="/*/choices/*">
<xsl:value-of select="concat(' ', name(), ' ')"/>
</xsl:for-each>
</xsl:variable>
<xsl:template match="/">
<xsl:copy-of select=
"/*/choice/*
[contains($vNames, concat(' ', name(), ' '))]
[1]"/>
</xsl:template>
</xsl:stylesheet>
当在同一个XML文档(上面)上应用此转换时,再次选择正确的元素(并将其复制到输出中):
<corr>Red</corr>
<强> III。使用密钥:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kChoiceByName" match="choice/*"
use="boolean(/*/choices/*[name()=name(current())])"/>
<xsl:template match="/">
<xsl:copy-of select="/*/choice/*[key('kChoiceByName', true())][1]"/>
</xsl:template>
</xsl:stylesheet>
对同一个XML文档(上图)应用此转换时,会生成相同的正确结果:
<corr>Red</corr>
建议读者尝试了解这一切是如何起作用的:)
答案 1 :(得分:1)
你可以像这样使用key()函数......
输入此文档时
<t>
<choices>
<sic />
<corr />
<reg />
<orig />
</choices>
<choice>
<corr>Red</corr>
<sic>Blue</sic>
</choice>
</t>
...作为此XSLT 1.0样式表的输入提供......
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="kChoices" match="choices/*" use="name()" />
<xsl:template match="/">
<xsl:variable name="first-choice" select="(*/choice/*[key('kChoices',name())])[1]" />
<xsl:value-of select="$first-choice" />
<xsl:text>, the value of <</xsl:text>
<xsl:value-of select="name( $first-choice)" />
<xsl:text>></xsl:text>
</xsl:template>
</xsl:stylesheet>
...生成此输出文字......
Red, the value of <corr>
在XSLT 2.0中,您可以使用以下备选方案来计算$ first-choice变量......
选项1:
(*/choice/*[for $c in . return ../../choices/*[name()=name($c)]])[1]
选项2:
(*/choice/*[some $c in ../../choices/* satisfies name($c)=name()])[1]