给定路径

时间:2018-03-31 14:16:21

标签: xml xslt

我想将所有匹配的模板应用于节点,但似乎总是只应用一个模板,具体取决于我的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模板。

1 个答案:

答案 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

https://xsltfiddle.liberty-development.net/bdxtpB/2