运行以下输入XML
时<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',因为其内容已更改为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>
请帮助我解释root
xsl:template
中@match
的{{1}}添加到Ambiguous rule match for /root[1]/value[1]
的{{1}}会产生此警告的区别。({{1}})
答案 0 :(得分:11)
您的结果是由于隐式模板优先级。您可以在任何模板上明确指定优先级:
<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
答案 1 :(得分:1)
通常,默认优先级用于指示模板规则中匹配模式的特殊性。匹配模式&#34;值&#34;没有特定于&#34; root / value&#34;它只匹配具有根父级的值元素,因此root / value具有更高的默认优先级。
默认优先级(0.5)恰好与具有谓词的匹配模式(注意root /值也可以写为值[parent :: root])相同,并且导致模板冲突。
您的第一个模板模式也容易受到模板冲突的影响,模板模式是(例如)与匹配*的模板冲突的身份模板。请注意,当发现此类冲突时,XSLT处理器可能会失败,而不是尝试根据相应模板的位置进行选择
如果从其样式表导入身份转换,则会消除不必要的重复并减少冲突,因为导入样式表中的模板优先级低于导入样式表中的模板。