我是xsl的新手。我找到了类似的东西,但不能完全调整它以供我使用。
输入:
<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>
使用属性“chapter ='1'或chapter ='2'”包装元素。 输出:
<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>
答案 0 :(得分:1)
<强>予。这个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
与group-adjacent
属性。
<强> II。 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文档(上面)上应用此转换时,会产生相同的,错误的结果。
解释:
正确使用:
利用和覆盖 identity rule 。
Keys 定义一组amendment
元素,chapter
属性不大于2
,作为函数的函数该组的前一个兄弟元素的 generate-id()
。
答案 1 :(得分:0)
Dimitre Novatchev,我将属性修改为字符串,xslt正常工作。感谢。
<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[(@chapter='1' or @chapter='2')]" use="generate-id(preceding-sibling::*[not(self::amendment and (@chapter='1' or @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='1' or @chapter='2')) and following-sibling::*[1][self::amendment and (@chapter='1' or @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[(@chapter='1' or @chapter='2')]"/>
</xsl:stylesheet>