理解`apply-templates`匹配

时间:2010-01-26 10:33:19

标签: xslt

我是否认为apply-templates声明应与所有模板相匹配,而这些模板可能会应用于选择?

例如,给定以下xml片段:

<doc>
  <foo bar="1" baz="2">boz</foo>
</doc>

和以下样式表:

<xsl:template match="/">
  <xsl:apply-templates select="foo" mode="xyz" />
</xsl:template>

<xsl:template mode="xyz" match="foo[bar='1']">
  abc
</xsl:template>

<xsl:template mode="xyz" match="foo[baz='2']">
  def
</xsl:template>

我希望输出为:

abc
def

这是对的吗?

3 个答案:

答案 0 :(得分:6)

不,您不会同时获得两个输出,因为只会选择一个模板。 如果有多个可能的模板,请参阅this page了解有关冲突解决的规则。

修复样式表后(类似于Rubens的做法,但使用相同的模式),这通常会导致xslt文件中的最后一个模板被应用,因此输出将为def。这是因为两个模板具有相同的优先级,如果您的xslt处理器没有因错误而停止,则标准要求它应用最后一个:

  

如果这会留下多个匹配的模板规则,则会出错。 XSLT处理器可能会发出错误信号;如果它没有发出错误信号,它必须通过从剩下的匹配模板规则中选择样式表中最后出现的那个来恢复。

答案 1 :(得分:4)

如果您 希望您的模板与两个属性相匹配,那么您只需要调整match XPATH选择属性并将关系置于谓词中的foo;而不是在foo 元素上匹配两个具有相同特异性(具有相同优先级)的冲突模板。

<?xml version="1.0" encoding="UTF-8"?>
  <xsl:stylesheet
   version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" encoding="UTF-8"/>

<xsl:template match="/">
  <xsl:apply-templates select="doc/foo"  />
</xsl:template>

<!--When templates match on foo, apply templates for it's attributes -->
<xsl:template match="foo">
    <xsl:apply-templates select="@*"/>
</xsl:template>

<!--Unique template match for the bar attribute -->
<xsl:template match="@bar[parent::foo and .='1']">
  abc
</xsl:template>

<!--Unique template match for the baz attribute -->
<xsl:template match="@baz[parent::foo and .='2']">
  def
</xsl:template>

</xsl:stylesheet>

答案 2 :(得分:0)

如果您修复了XSLT代码(有一些过滤器问题)并运行它,您应该看到:

  

DEF

为什么呢? <xsl:apply-templates />将匹配满足您匹配条件的第一个模板。如果您有两个模板,则应该使用<xsl:apply-templates> mode属性,或使用<xsl:template> priority属性:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="/doc">
        <xsl:apply-templates select="foo" mode="2" />
    </xsl:template>

    <xsl:template mode="1" match="foo[@bar='1']">
        abc
    </xsl:template>

    <xsl:template mode="2" match="foo[@baz='2']">
        def
    </xsl:template>

</xsl:stylesheet>