I have an XML file which looks like the following:
<a>
......
<b>
<c>
<c1>some text</c1>
</c>
<d>
<d1>some more text</d1>
<d1>even more text</d1>
</d>
<e>
<e1>some more text</e1>
<e1>even more text</e1>
</e>
</b>
</a>
And I want to wrap elements <d> and <e> into a <wrapper> element, so I can have something like the following:
<a>
......
<b>
<c>
<c1>some text</c1>
</c>
<wrapper>
<d>
<d1>some more text</d1>
<d1>even more text</d1>
</d>
<e>
<e1>some more text</e1>
<e1>even more text</e1>
<e2>even more</e2>
</e>
</wrapper>
</b>
......
</a>
One of the problems that I'm facing (apart from the fact that I'm new to XSLT) is that both <d> and <e> are optional.
How can I do this?
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:strip-space elements="*"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="b/*[self::d or self::e][1]">
<wrapper>
<xsl:apply-templates mode="copy" select=
". | following-sibling::*[self::d or self::e]"/>
</wrapper>
</xsl:template>
<xsl:template match="*" mode="copy">
<xsl:copy>
<xsl:apply-templates mode="copy" select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="b/*[self::d or self::e][position()>1]"/>
</xsl:stylesheet>
when applied on the provided XML document:
<a> ......
<b>
<c>
<c1>some text</c1>
</c>
<d>
<d1>some more text</d1>
<d1>even more text</d1>
</d>
<e>
<e1>some more text</e1>
<e1>even more text</e1>
</e>
</b>
</a>
produces the wanted result:
<a> ......
<b>
<c>
<c1>some text</c1>
</c>
<wrapper>
<d>
<d1>some more text</d1>
<d1>even more text</d1>
</d>
<e>
<e1>some more text</e1>
<e1>even more text</e1>
</e>
</wrapper>
</b>
</a>
Note: Overriden identity rule + modes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With