有没有比xsl:variable更好的方法来引用XPath表达式中的属性值?

时间:2013-11-21 05:13:11

标签: xslt xslt-2.0

我正在使用XSLT 2.0来转换一些XML。源XML看起来类似于:

<AnimalTest>
  <AnimalTypes>
    <AnimalType name="cat"/>
    <AnimalType name="dog"/>
  </AnimalTypes>
  <Animals>
    <Animal name="Sylvester" typeName="cat"/>
    <Animal name="Fido" typeName="dog"/>
    <Animal name="Tom" typeName="cat"/>
  </Animals>
</AnimalTest>

在处理AnimalType标记的XSL模板中,我想在XPath表达式中使用name的{​​{1}}属性。我能够实现这一目标的唯一方法是引入一个包含属性AnimalType的变量,并从XPath表达式中引用,如下所示:

@name

这有效,但我想知道我是否真的必须使用这个临时变量。有没有更好的方法来引用<xsl:template match="AnimalType"> <xsl:variable name="typename" select="@name"/> <xsl:apply-templates select="/AnimalTest/Animals/Animal[@typeName=$typename]"/> </xsl:template> 属性?这看起来像是绕道而行。

1 个答案:

答案 0 :(得分:3)

如果您真的不喜欢使用变量,可以使用 current()函数来引用当前上下文节点(在您的情况下为 AnimalType

<xsl:apply-templates select="/AnimalTest/Animals/Animal[@typeName=current()/@name]"/>

如果你有一个更复杂的表达式,使用变量虽然可以提高可读性,但你可能会在其他地方重复使用。

有一点需要注意的是他的宣言

<xsl:variable name="typename" select="@name"/>

与此声明不完全相同

<xsl:variable name="typename">
   <xsl:value-of select="@name" />
</xsl:variable>

虽然两个变量都包含相同的值。在后一种情况下(使用xsl:value-of),您将创建 name 属性值的副本。在前一种情况下,您直接引用该属性。因此,使用后一种格式效率会降低。

稍微提一下,您可以考虑在此处使用密钥按类型名称查找动物元素

<xsl:key name="AnimalByType" match="Animal" use="@typeName" />

这样,您的apply-templates表达式可以简化为以下

<xsl:template match="AnimalType">
   <xsl:apply-templates select="key('AnimalByType', @name)"/>
</xsl:template>