2
<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>

有没有更直接的方法?

4

2 回答 2

2

I. 使用这个 XPath 2.0 单线

/*/choice/*[name() = /*/choices/*/name()][1]

当此 XPath 表达式针对以下 XML 文档(提供的文档,但已更正为格式良好的 XML 文档)进行评估时:

<t>
    <choices>
        <sic  />
        <corr />
        <reg  />
        <orig />
    </choices>
    <choice>
        <corr>Red</corr>
        <sic>Blue</sic>
    </choice>
</t>

选择了正确的元素

<corr>Red</corr>

二、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>

三、使用键

<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>

建议读者尝试了解这一切是如何“工作”的:)

于 2012-10-11T23:57:28.177 回答
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 &lt;</xsl:text>
  <xsl:value-of select="name( $first-choice)" />
  <xsl:text>&gt;</xsl:text>
</xsl:template>

</xsl:stylesheet>

...生成此输出文本...

Red, the value of <corr>

除了 XSLT 2.0

在 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]
于 2012-10-11T23:52:54.050 回答