XSLT 模板的歧义说明



运行时,以下输入 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>

请帮助我解释在 xsl:template@match 中向 xpath 添加root有什么区别,使我收到此警告。( Ambiguous rule match for /root[1]/value[1]

您的结果是由于隐式模板优先级。您可以在任何模板上显式指定优先级:

<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>

结果将是(在此处在线查看):

<?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。


请参阅 XSLT 规范的相关部分。警告:那里的默认优先级并不容易阅读。


所有优先事项:

<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

通常,默认优先级旨在指示模板规则中匹配模式的特殊性。匹配模式"值"不如"根/值"具体,后者仅将值元素与根父元素匹配,因此根/值具有更高的默认优先级。

默认优先级 (0.5) 恰好与具有谓词的匹配模式相同(请注意,root/value 也可以写为 value[parent::root]),这导致了模板冲突。

您也容易受到第一个模板模式(例如)与匹配 * 的模板冲突的影响,该模板是标识模板,该模板将与 * 匹配的模板冲突。请注意,当发现此类冲突时,允许 XSLT 处理器失败,而不是尝试根据相应模板的位置进行选择

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

相关内容

  • 没有找到相关文章

最新更新