我想将所有匹配的模板应用于节点,但似乎总是只应用一个模板,具体取决于我的XSLT文件中模板的顺序。这是最小的例子:
<!-- XML Source -->
<a>
<b url="foo">
<text>1</text>
<text>2</text>
</b>
</a>
<!-- XSL transformation -->
<!-- Transform1 -->
<xsl:template match="//*[text]">
<xsl:for-each select="text">
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
<!-- Transform2 -->
<xsl:template match="//*[@url]">
<xsl:value-of select="@url"/>
</xsl:template>
所以我期待的结果是12foo
,但是这样写的它只匹配Transfor1模板,如果我交换顺序,它只匹配Transform2模板。
答案 0 :(得分:3)
处理器首先查看优先级https://www.w3.org/TR/xslt-30/#conflict,如果有多个具有相同优先级,则可以报告错误或选择最后一个错误。
因此,您必须重新设计代码,并使用模式来区分您希望使用的模式中的处理步骤和应用模板,或者在XSLT 2或更高版本中,您可以测试使用<xsl:next-match/>
是否可以帮助您解决这一点。
另一方面,如果您只是编写模板匹配text
而另一个匹配{{},那么您当前的代码会匹配元素,然后处理url
子元素和*/text
属性。 1}}并且@url
或*[text]
匹配的模板执行*[@url]
您可能根本没有这个问题。
如果要在子节点之后输出属性,那么在XSLT 1中,您需要两个<xsl:apply-templates select="@* | node()"/>
:
apply-templates
正如https://xsltfiddle.liberty-development.net/bdxtpB所示,这足以输出元素和属性的值,因为内置模板可以正常工作。
在XSLT 2或3中,您可以将代码缩短为
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="b">
<xsl:apply-templates select="text"/>
<xsl:apply-templates select="@*"/>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/bdxtpB/1
至于在尝试中使用 <xsl:template match="b">
<xsl:apply-templates select="text, @*"/>
</xsl:template>
,它看起来像
next-match