为什么XSLT中没有最专业的模板匹配

时间:2016-03-16 15:31:18

标签: xslt xalan

这是我的转变:

<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:message terminate="yes">中的<xsl:template>引起的。为什么?不应该是第二个更专业的<xsl:template>匹配吗?

2 个答案:

答案 0 :(得分:1)

根据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>

答案 1 :(得分:1)

另一个解决方案是简单地让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>

虽然这可能不是很干净,但你应该保持原样并明确地将prio设置为高于.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>