2014-11-22 97 views
4

當運行下面的輸入XMLXSLT模板模棱兩可的澄清

<root> 
    <value>false</value> 
    <value>true</value> 
</root> 

針對以下XSLT:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="@*|node()"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="value"> 
    <true_value/> 
</xsl:template> 

<xsl:template match="value[. = 'false']"> 
    <false_value/> 
</xsl:template> 

</xsl:stylesheet> 

我得到value元素與 '假' 作爲其內容改爲false_value ..和所有其他value元素都變成了true_value。 輸出:

<?xml version="1.0" encoding="utf-8"?> 
<root> 
    <false_value/> 
    <true_value/> 
</root> 

但只有當我更改模板匹配root/value做我得到模棱兩可的模板警告。

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="@*|node()"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="root/value"> 
    <true_value/> 
</xsl:template> 

<xsl:template match="root/value[. = 'false']"> 
    <false_value/> 
</xsl:template> 

</xsl:stylesheet> 

請通過解釋幫我什麼區別添加rootxsl:template@match,使我得到這樣的警告中的XPath。(Ambiguous rule match for /root[1]/value[1]

回答

10

你的結果是由於隱含的模板優先級。您可以在任何模板明確指定優先級:

<xsl:template match="foo" priority="2"/> 

但在大多數情況下,你沒有明確說明什麼優先級,你想一個模板採用 - 而這也正是該默認優先級一步如果有。在模板之間是衝突的,也就是說,如果輸入節點匹配多個模板,則XSLT將定義一個利用默認優先級的衝突解決過程。

兩個模板,使處理器發出警告:

<xsl:template match="root/value"> 

<xsl:template match="root/value[. = 'false']"> 

具有相同的默認優先級(0.5)。你會認爲匹配模式match="root/value[. = 'false']"match="root/value"更具體,但就規範而言,它不是 - 它們具有完全相同的優先級。

這就是報告模糊規則匹配的原因。不明確的規則匹配是無法用明確或隱含的優先級解決衝突的情況。作爲最後的手段,最後一個模板被選中

要完成這個思想實驗,改變模板以

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="root/value[. = 'false']"> 
    <false_value/> 
</xsl:template> 

<xsl:template match="root/value"> 
    <true_value/> 
</xsl:template> 

</xsl:stylesheet> 

而結果將是(看到它在線here):

<?xml version="1.0" encoding="utf-8"?> 
<root> 
    <true_value/> 
    <true_value/> 
</root> 

正如你所看到的,對於value元素,選擇最後一個模板。

那麼爲什麼在模板匹配結果中添加root/會導致關於模板歧義的警告呢?

所做的具體變化是從

<xsl:template match="value"> 

<xsl:template match="root/value"> 

更改默認的優先級的模板的(如上所述)。 value的默認優先級爲0,root/value的默認優先級爲0.5。只有在第二種情況下才會出現衝突,因爲另一個模板的默認優先級也是0.5。

添加root/到第二模板:

<xsl:template match="root/value[. = 'false']"> 

不會改變任何東西,默認優先級保持0.5。


查看relevant part of the XSLT specification。注意:這裏的默認優先級並不完全容易閱讀。


所有優先級:

<xsl:template match="value">      0 
<xsl:template match="value[. = 'false']">   0.5 
<xsl:template match="root/value">     0.5 
<xsl:template match="root/value[. = 'false']"> 0.5 
+2

@MartinHonnen感謝馬丁,我也試圖解決這個問題 - 讓我知道你是否有其他建議。 – 2014-11-22 16:28:04

+0

總是很高興收到你的來信。感謝這樣的詳細解釋。 – 2014-11-22 16:51:41

1

一般默認的優先級是爲了表明在模板規則匹配模式的特殊性。匹配模式「值」不如「root/value」特定,它只與具有根父級的值元素相匹配,因此root /值具有較高的默認優先級。

默認優先級(0.5)恰好與以謂詞爲特徵的匹配模式相同(注意根/值也可以寫爲值[parent :: root])並且導致模板衝突。

您的第一個模板模式也是容易受到模板衝突,這是模板(例如)將與匹配*的模板發生衝突的模板模板。請注意,如果發現此類衝突,XSLT處理器可能會失敗,而不是嘗試根據相應模板的位置進行選擇。

如果從其樣式表中導入標識轉換,則不必要的重複操作將被消除,並且衝突因爲導入樣式表中的模板比導入樣式表中的模板具有更低的優先級。