2010-01-26 38 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