XSLT模板的模糊性澄清

时间:2014-11-22 15:58:51

标签: xslt xpath xslt-1.0 xslt-2.0

运行以下输入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}})

2 个答案:

答案 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处理器可能会失败,而不是尝试根据相应模板的位置进行选择

如果从其样式表导入身份转换,则会消除不必要的重复并减少冲突,因为导入样式表中的模板优先级低于导入样式表中的模板。