XSLT:匹配第一个后代元素

时间:2014-06-17 17:26:28

标签: xslt xpath

我正在尝试匹配在xsl匹配模式中作为bar元素的后代出现的第一个foo元素并且正在挣扎。初步尝试:

<xsl:template match="//foo//bar[1]">
...
</xsl:template>

失败,因为有几个匹配的bar个元素。所以:

<xsl:template match="(//foo//bar)[1]">
...
</xsl:template>

但无法编译。

3 个答案:

答案 0 :(得分:2)

棘手。我不知道效率或其他方面的效率,但你可以将模式转到头部并将逻辑移动到谓词中( 允许使用除子,属性和{之外的轴) {1}}):

//

<xsl:template match="foo//bar[not(preceding::bar/ancestor::foo)]"> 内的任何bar,前提是它之前没有另一个bar-inside-a-foo。或者,您可以尝试类似于Muenchian分组工作的关键技巧,这可能更有效

foo

答案 1 :(得分:2)

你不能用匹配表达式来做这件事。事实上,可以使用匹配表达式执行此操作,而不是像每个XSLT处理器那样。见评论。

我使用<xsl:if>

<xsl:template match="foo//bar">
  <xsl:if test="generate-id() = generate-id(ancestor::foo[1]//bar)">
    <!-- ... -->
  </xsl:if>
</xsl:template>

这样可以确保只有{em>第一个后代<bar><foo> (!)进一步处理。

注意:当给定节点集时,generate-id()返回集合中第一个节点的ID。

答案 2 :(得分:0)

替代解决方案基于&#34;经验法则&#34;使用高级XPATH&#34;选择&#34;不是当你&#34;匹配&#34;。简单地将XML与模板匹配,就像foo一样,甚至不是// foo。

<?xml version="1.0" encoding="UTF-8"?>
<foo>
<bar>bar1<bar>bar2</bar></bar>
<bar>bar3</bar>
</foo>

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="foo">
<xsl:apply-templates select="descendant::bar[1]"/>
</xsl:template>

<xsl:template match="bar">
<!--only the first bar was selected --><xsl:value-of select="text()"/>
</xsl:template>
</xsl:stylesheet>