为什么大多数专用模板在 XSLT 中不匹配

Why doesn't most specialized template match in XSLT

这是我的改造:

<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/root">
        <output>
            <xsl:apply-templates select="outer[@type='foo']/inner"/>
        </output>
    </xsl:template>

    <xsl:template match="outer[@type='foo']/inner[@type='bar1' or @type='bar2' or @type='bar3' or @type='bar4']">
        <item>
            <xsl:value-of select="text()"/>
        </item>
    </xsl:template>

    <xsl:template match="outer[@type='foo']/inner">
        <xsl:message terminate="yes">
            <xsl:value-of select="concat('Unexpected type: ', @type)"/>
        </xsl:message>
    </xsl:template>
</xsl:transform>

这是我的输入:

<root>
    <outer type="foo">
        <inner type="bar2">bar2</inner>
    </outer>
</root>

当我对输入执行转换时,Xalan 退出并出现致命错误,这是由第三个 <xsl:template> 中的 <xsl:message terminate="yes"> 引起的。为什么?第二个更专业的 <xsl:template> 不应该匹配吗?

根据 http://lenzconsulting.com/how-xslt-works/#priority

,您的两个匹配表达式的优先级均为 .5

所以你的模板有冲突。如何在 1 个模板中处理所有内容?

<xsl:template match="outer[@type='foo']/inner">
    <xsl:choose>
        <xsl:when test="@type='bar1' or @type='bar2' or @type='bar3' or @type='bar4'">
            <item>
                <xsl:value-of select="text()"/>
            </item>
        </xsl:when>
        <xsl:otherwise>
            <xsl:message terminate="yes">
                <xsl:value-of select="concat('Unexpected type: ', @type)"/>
            </xsl:message>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

另一种解决方案是简单地使用 2 个模板交易头寸:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/root">
        <output>
            <xsl:apply-templates select="outer[@type='foo']/inner"/>
        </output>
    </xsl:template>
    <xsl:template match="outer[@type='foo']/inner">
        <xsl:message terminate="yes">
            <xsl:value-of select="concat('Unexpected type: ', @type)"/>
        </xsl:message>
    </xsl:template>
    <xsl:template match="outer[@type='foo']/inner[@type='bar1' or @type='bar2' or @type='bar3' or @type='bar4']">
        <item>
            <xsl:value-of select="text()"/>
        </item>
    </xsl:template>
</xsl:transform>

尽管这可能不干净,所以您应该保留原来的顺序,并将高于 .5 的优先级显式设置为更专业的模板:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/root">
        <output>
            <xsl:apply-templates select="outer[@type='foo']/inner"/>
        </output>
    </xsl:template>
    <xsl:template match="outer[@type='foo']/inner[@type='bar1' or @type='bar2' or @type='bar3' or @type='bar4']" priority="1">
        <item>
            <xsl:value-of select="text()"/>
        </item>
    </xsl:template>
    <xsl:template match="outer[@type='foo']/inner">
        <xsl:message terminate="yes">
            <xsl:value-of select="concat('Unexpected type: ', @type)"/>
        </xsl:message>
    </xsl:template>
</xsl:transform>