2010-01-26 42 views
5

我正确地认为apply-templates声明应该匹配全部模板可能会被应用于选择吗?理解`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 

这是正确的?

回答

6

不,你没有得到两路输出,因为只有一个模板将被选中。 如果存在多个可能的模板,请参阅this page以获取冲突解决规则。

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

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

+0

+1,很好的回答 – 2010-01-26 10:56:14

0

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

高清

为什么? <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> 
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> 
+0

谢谢,这就是我想要做的。不幸的是,我不能接受答案,因为它没有涉及到“为什么”。 ;) – 2010-01-26 12:22:39