为什么 <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 测试了它,一切都按预期工作。
如果你的第一个XML,结果是
header matched
这是正确的,因为 <xsl:template match="header">
规则匹配 <header>
根元素。并结束。
如果你的第二个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。第一个的结果保持不变。
我有一组复杂的样式表,用于从各种 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 测试了它,一切都按预期工作。
如果你的第一个XML,结果是
header matched
这是正确的,因为
<xsl:template match="header">
规则匹配<header>
根元素。并结束。如果你的第二个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。第一个的结果保持不变。