XSLT模板的模糊性澄清

Lin*_* CS 6 xslt xpath xslt-2.0 xslt-1.0

运行以下输入XML时

<root>
    <value>false</value>
    <value>true</value>
</root>
Run Code Online (Sandbox Code Playgroud)

针对以下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>
Run Code Online (Sandbox Code Playgroud)

我的value元素带有'false',因为它的内容改为false_value..而且所有其他value元素都变成了true_value.输出:

<?xml version="1.0" encoding="utf-8"?>
<root>
   <false_value/>
   <true_value/>
</root>
Run Code Online (Sandbox Code Playgroud)

但是只有当我更改模板匹配时才会出现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>
Run Code Online (Sandbox Code Playgroud)

请帮助我解释rootxsl:template's 中添加xpath @match使得我得到这个警告的区别.(Ambiguous rule match for /root[1]/value[1])

Mat*_*ler 11

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

<xsl:template match="foo" priority="2"/>
Run Code Online (Sandbox Code Playgroud)

但在大多数情况下,您没有明确说明您希望模板采用哪种优先级 - 这就是默认优先级的步骤.如果模板之间存在冲突,即,如果输入节点与多个模板匹配,则XSLT定义利用默认优先级的冲突解决程序.

导致处理器发出警告的两个模板:

<xsl:template match="root/value">
Run Code Online (Sandbox Code Playgroud)

<xsl:template match="root/value[. = 'false']">
Run Code Online (Sandbox Code Playgroud)

具有相同的默认优先级(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>
Run Code Online (Sandbox Code Playgroud)

结果将是(在线查看):

<?xml version="1.0" encoding="utf-8"?>
<root>
   <true_value/>
   <true_value/>
</root>
Run Code Online (Sandbox Code Playgroud)

如您所见,对于这两个value元素,选择最后一个模板.

那么,为什么root/在模板模糊度警告中添加模板匹配结果呢?

您所做的具体更改来自

<xsl:template match="value">
Run Code Online (Sandbox Code Playgroud)

<xsl:template match="root/value">
Run Code Online (Sandbox Code Playgroud)

这会更改模板的默认优先级(如上所述).默认优先级value为0,默认优先级root/value为0.5.只有在第二种情况下才会出现冲突,因为另一个模板的默认优先级也是0.5.

添加root/到第二个模板:

<xsl:template match="root/value[. = 'false']">
Run Code Online (Sandbox Code Playgroud)

不会更改任何内容,默认优先级保持为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
Run Code Online (Sandbox Code Playgroud)

  • @MartinHonnen感谢Martin,我也试图解决这个问题 - 如果您有任何其他建议,请告诉我. (2认同)