为什么大多数专用模板在 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>
这是我的改造:
<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>