我正在尝试匹配在xsl匹配模式中作为bar
元素的后代出现的第一个foo
元素并且正在挣扎。初步尝试:
<xsl:template match="//foo//bar[1]">
...
</xsl:template>
失败,因为有几个匹配的bar
个元素。所以:
<xsl:template match="(//foo//bar)[1]">
...
</xsl:template>
但无法编译。
答案 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>