为什么 <xsl:template match="*"> 无法竞争更具体的模板?

Why is <xsl:template match="*"> out competing more specific templates?

我有一组复杂的样式表,用于从各种 XML 文件创建 SQL 插入语句。 XML 文件可以采用多种模式。我有几个模板来处理这些模式,但我可能会收到无法识别的 XML。对于这种情况,我有一个仅匹配“*”的默认模板。我发现此默认模板 有时 优先于更具体的模板。 此外,当我注释掉默认模板时,更具体的模板匹配成功。强制优先级没有帮助。 我是 运行 Saxon HE 9.6。如果我也使用 9.9,就会发生这种情况。

模板

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">
    
    <xsl:template match="/">
        <xsl:apply-templates/>
    </xsl:template>
    
    <xsl:template match="article/front"> <!-- loses to default -->
        <xsl:text>article/front matched</xsl:text>
        
    </xsl:template>
    
    <xsl:template match="header"> <!-- wins against default -->
        <xsl:text>header matched</xsl:text>
       
    </xsl:template>
    
    <xsl:template match="*">
        <xsl:text>DEFAULT MATCH</xsl:text>
    </xsl:template>
    
</xsl:stylesheet>

我无法提供完整的 XML,但这里有一些模型:

<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<!DOCTYPE header SYSTEM "http://ej.slop.org/dtd/header.dtd">
<header>
  <notification type="new" timestamp="2020-02-27 00:59:35"/>
</header>
<article xml:lang="en" article-type="research-article" dtd-version="1.0" xmlns:xlink="http://www.w3.org/1999/xlink">
    <front>
        <journal-meta>
            <journal-id journal-id-type="publisher-id">CLM</journal-id>
        </journal-meta>
    </front>
</article>

好吧,我用 Saxon-HE 9.9.1.4J 测试了它,一切都按预期工作。

  1. 如果你的第一个XML,结果是

    header matched

    这是正确的,因为 <xsl:template match="header"> 规则匹配 <header> 根元素。并结束。

  2. 如果你的第二个XML,结果是

    DEFAULT MATCH

    这也是正确的,因为它将根元素 <article><xsl:template match="*"> 规则相匹配。并结束。规则 <xsl:template match="article/front"> 不适用,因为它只会应用于具有 <article> 父元素的 <front> 元素。并且模板链中没有<front>个元素,因为*规则没有调用xsl:apply-templates.

所以一切正常。

如果您注释掉 <xsl:template match="*"> 规则,built-in-template-rules 将适用。这里相关的是

<xsl:template match="*|/">
  <xsl:apply-templates/>
</xsl:template>

此规则会下降到树中,直到另一个规则匹配为止。这是 <xsl:template match="article/front"> 会给你结果

article/front matched

与你的第二个 XML。第一个的结果保持不变。