考虑这个XML:
<a>
<b>something</b>
<b>something</b>
<M>other</M>
<b>something</b>
<b>something</b>
<N>else</N>
<b>something</b>
<b>something</b>
<b>something</b>
</a>
现在我要删除所有&#34; b&#34;在开始或结束时,如果它们位于不同节点之间,我只想输出一个节点。所以这将是理想的输出:
<a>
<M>other</M>
<b>something</b>
<N>else</N>
</a>
我不知道有多少&#34; b&#34;并且我不知道其他节点名称是什么。开始很简单:删除所有&#34; b&#34;当他们关注&#34; b&#34;:
<xsl:template match="b[preceding-sibling::*[1][self::b]]"/>
然后删除第一个&#34; b&#34;:
<xsl:template match="b[position= 1]"/>
最后一个如果只有一个&#34; b&#34;:
<xsl:template match="b[position= last()]"/>
但是我无法获得最后三个中的第一个&#34; b&#34; s。测试应该说:如果只是&#34; b&#34;但是没有其他任何内容可以删除&#34; b&#34;。我发现的一些解决方案使用了分组,但由于节点的顺序很重要,在这里似乎没什么帮助。
答案 0 :(得分:1)
我建议使用xsl:for-each-group
,如下所示:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* , node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="a">
<xsl:copy>
<xsl:for-each-group select="*" group-adjacent="boolean(self::b)">
<xsl:choose>
<xsl:when test="not(current-grouping-key())">
<xsl:apply-templates select="current-group()"/>
</xsl:when>
<xsl:when test="not(position() = (1, last()))">
<xsl:apply-templates select="."/>
</xsl:when>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
改变
<a>
<b>1</b>
<b>2</b>
<M>foo</M>
<b>3</b>
<b>4</b>
<N>bar</N>
<b>5</b>
<b>6</b>
<b>7</b>
</a>
进入
<a>
<M>foo</M>
<b>3</b>
<N>bar</N>
</a>