I. 这个 XSLT 2.0 转换:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<section>
<xsl:for-each-group select="*"
group-adjacent="self::amendment and @chapter =(1,2)">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<newwrapper>
<xsl:sequence select="current-group()"/>
</newwrapper>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</section>
</xsl:template>
</xsl:stylesheet>
应用于提供的 XML 文档时:
<section>
<heading>some heading text</heading>
<amendment chapter="1">
<foo/>
</amendment>
<amendment chapter="2">
<bar/>
</amendment>
<amendment chapter="3">
<baz/>
</amendment>
<heading>some heading text</heading>
<amendment chapter="1">
<baz/>
</amendment>
</section>
产生想要的正确结果:
<section>
<heading>some heading text</heading>
<newwrapper>
<amendment chapter="1">
<foo/>
</amendment>
<amendment chapter="2">
<bar/>
</amendment>
</newwrapper>
<amendment chapter="3">
<baz/>
</amendment>
<heading>some heading text</heading>
<newwrapper>
<amendment chapter="1">
<baz/>
</amendment>
</newwrapper>
</section>
说明:
正确使用xsl:for-each-group
withgroup-adjacent
属性。
二、XSLT 1.0 解决方案:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kFollowing" match="amendment[not(@chapter >2)]" use=
"generate-id(preceding-sibling::*
[not(self::amendment and @chapter <= 2)][1])"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"*[not(self::amendment and @chapter <= 2)
and
following-sibling::*[1][self::amendment and not(@chapter >2)]
]">
<xsl:call-template name="identity"/>
<newwrapper>
<xsl:apply-templates mode="inGroup"
select="key('kFollowing', generate-id())"/>
</newwrapper>
</xsl:template>
<xsl:template match="*" mode="inGroup">
<xsl:call-template name="identity"/>
</xsl:template>
<xsl:template match="amendment[not(@chapter >2)]"/>
</xsl:stylesheet>
当此转换应用于同一个 XML 文档(上图)时,会产生相同的、正确的结果。
说明:
正确使用:
使用和覆盖身份规则。
用于定义属性不大于的一组相邻amendment
元素的键,作为该组的前一个兄弟元素的函数chapter
2
generate-id()