I want to create as many <Group>
elements as they are in the Main xml dynamically using XSLT as <Group folder ="Group1">
in the new Xml. Also, the <Data>
element added as the last child should be added only once inside.
Main Xml
<Root>
<ClassA>
<Groups>
<Group1>
<Group2>
<Group3>
............
</Group3>
</Group2>
</Group1>
</Groups>
<Data>
<Name>George</Name>
<Class>A</Class>
</Data>
</ClassA>
</Root>
I need an Xml like this
<Data>
<ClassA>
<Group folder = "Group1">
<Group folder = "Group2">
<Group folder = "Group3">
............
<Data>
<Name>George</Name>
<Class>A</Class>
</Data>
</Group>
</Group>
</Group>
</ClassA>
</Data>
Actually, you need the following templates:
Matching Root
. Generate <Data>
element and inside it
apply templates to the whole own content.
Matching ClassA
. Copy the own element and inside if
apply templates to the content of the child Groups
element.
Matching elements with name containing Group
and then a digit.
Create Group
element with proper folder
attribute.
Apply templates to its content (if any).
If this element does not contain any child element, copy
Data
element from ancestor ClassA
.
The identity template.
So the whole script can look like below:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="Root">
<Data><xsl:apply-templates select="@*|node()"/></Data>
</xsl:template>
<xsl:template match="ClassA">
<xsl:copy><xsl:apply-templates select="Groups/*"/></xsl:copy>
</xsl:template>
<xsl:template match="*[matches(name(), 'Group\d')]">
<xsl:element name='Group'>
<xsl:attribute name="folder" select="name()"/>
<xsl:apply-templates select="@*|node()"/>
<xsl:if test="count(*) = 0">
<xsl:copy-of select="ancestor::ClassA/Data"/>
</xsl:if>
</xsl:element>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
</xsl:template>
</xsl:transform>
For a working example see http://xsltransform.net/nb9MWtw
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Root">
<xsl:element name="Data">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="ClassA">
<xsl:element name="ClassA">
<group floder="{Groups/Group1/name()}">
<group floder="{Groups/Group1/Group2/name()}">
<group floder="{Groups/Group1/Group2/Group3/name()}">
<xsl:value-of select="Groups/Group1/Group2/Group3"/>
<xsl:copy-of select="Data"/>
</group>
</group>
</group>
</xsl:element>
</xsl:template>
Try if is benifial for you.