XSLT 样式 - 模式匹配多个模板

XSLT style - pattern matching multiple templates

这是一个关于 xslt 1.0 的问题(但我已经包括了通用的 xslt 标签,因为它可能应用得更广泛)。

假设我们想接受这个xml

<root>
  <vegetable>
    <carrot colour="orange"/>      
    <leek colour="green"/>
  </vegetable>  
</root>

如果是根茎类蔬菜,将其转化为烹饪蔬菜,所以这..

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:output method="xml" indent="yes"/>

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

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

  <xsl:template match="leek">    
  </xsl:template>
</xsl:stylesheet>

所以 xslt 递归地处理数据,当它找到多个匹配的模板时,例如韭菜和胡萝卜,就拿最后一个,有效的压倒。

有时本站接受的答案是这种风格, 例如XSLT copy-of but change values

关于多个匹配模板的其他答案 例如 XSLT Multiple templates with same match

状态

根据 XSLT 规范,具有相同优先级的两个模板匹配相同的节点是错误的

It is an error if [the algorithm in section 5.5] leaves more than one matching template rule. An XSLT processor may signal the error; if it does not signal the error, it must recover by choosing, from amongst the matching template rules that are left, the one that occurs last in the stylesheet.

所以....我们可以通过使用优先级或通过匹配明确排除重叠来避免这种情况,就像这样。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="@* | node()[not(self::carrot) or not(self::leek)]">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

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

  <xsl:template match="leek">    
  </xsl:template>
</xsl:stylesheet>

我感觉很多开发者实际上只是使用默认的回退行为,让处理器使用最后一个匹配,这在风格上类似于大多数使用第一个匹配的函数式语言中的模式匹配。

我个人也不喜欢优先级,感觉有点像魔术数字,我必须扫描并记住模式匹配的优先级才能弄清楚发生了什么。

显式排除重叠的方法似乎很明智,但在实践中需要复杂的逻辑并在模板之间创建耦合,如果我 extend/add 一个新的匹配,我可能不得不修改约束另一个。

以上总结正确吗? 是否有公认的样式(即使它与规范相矛盾)?

我认为您可能忽略了给定示例中没有错误的事实,因此不会调用应用样式表中最后出现的模板的规则。您可以通过切换模板的顺序并观察结果保持不变来验证这一点。

没有错误,因为恒等变换的优先级为 -0.5,而特定模板的优先级为 0。

阅读整个规范以解决冲突:
https://www.w3.org/TR/1999/REC-xslt-19991116/#conflict