Reputation: 244
I have a piece of XML that I want to transform with XSLT (using xsltproc--so only XSLT 1.0). The original XML uses some tags as separators like this:
<container>
<element />
<element />
<separator />
<element />
<element />
<element />
<separator />
<element />
</container>
I need to transform this into a format that wraps these elements instead. So I need it to look like this:
<container>
<wrapper>
<element />
<element />
</wrapper>
<wrapper>
<element />
<element />
<element />
</wrapper>
<wrapper>
<element />
</wrapper>
</container>
I just can't seem to design a template that achieves this. Anybody out there have any thoughts?
Upvotes: 6
Views: 174
Reputation: 243479
This transformation:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kFollowing" match="element"
use="generate-id(preceding-sibling::separator[1])"/>
<xsl:template match="/*">
<container>
<xsl:apply-templates select=
"element
[generate-id()
=
generate-id(key('kFollowing',
generate-id(preceding-sibling::separator[1])
)[1]
)
]"/>
</container>
</xsl:template>
<xsl:template match="element">
<wrapper>
<xsl:copy-of select=
"key('kFollowing',
generate-id(preceding-sibling::separator[1])
)"/>
</wrapper>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document:
<container>
<element />
<element />
<separator />
<element />
<element />
<element />
<separator />
<element />
</container>
produces the wanted, correct result:
<container>
<wrapper>
<element/>
<element/>
</wrapper>
<wrapper>
<element/>
<element/>
<element/>
</wrapper>
<wrapper>
<element/>
</wrapper>
</container>
Upvotes: 6