Reputation: 13587
I am new to XSLT and got stuck with this issue.
Input XML
<Root>
<Family>
<Entity>
<SomeElement1/>
<Child1>
<Element1/>
</Child1>
<Child2>
<Element2/>
</Child2>
<Entity>
<SomeElement1/>
<Child1>
<Element111/>
</Child1>
<Child2>
<Element222/>
</Child2>
</Entity>
</Entity>
</Family>
</Root>
Output Xml
<Response>
<EntityRoot>
<SomeElement1/>
</EntityRoot>
<Child1Root>
<Element1>
</Child1Root>
<Child2Root>
<Element2>
</Child2Root>
<MetadataEntityRoot>
<SomeElement1/>
</MetadataEntityRoot>
<Child1Root>
<Element111>
</Child1Root>
<Child2Root>
<Element222>
</Child2Root>
</Response>
I know how to copy everything from the input xml. But not sure how would exclude child elements and then copy them again in a different root element.
<!-- Copy everything -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
Tried this based on the given answer
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Entity">
<EntityRoot>
<xsl:apply-templates select="@* | node()[not(self::Child1 | self::Child2)]" />
</EntityRoot>
<xsl:apply-templates select="Child1 | Child2" />
</xsl:template>
<xsl:template match="Child1">
<Child1Root><xsl:apply-templates select="@*|node()" /></Child1Root>
</xsl:template>
<xsl:template match="Child2">
<Child2Root><xsl:apply-templates select="@*|node()" /></Child2Root>
</xsl:template>
</xsl:stylesheet>
But got the output as:
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<Family>
<EntityRoot>
<SomeElement1/>
</EntityRoot>
<Child1Root>
<Element1/>
</Child1Root>
<Child2Root>
<Element2/>
</Child2Root>
</Family>
</Root>
Upvotes: 0
Views: 672
Reputation: 122364
In addition to the "copy everything" identity template you already have, you just add specific templates that match the elements you want to process differently. To rename Child1
to Child1Root
you can use
<xsl:template match="Child1">
<Child1Root><xsl:apply-templates select="@*|node()" /></Child1Root>
</xsl:template>
and similarly to rename Child2
to Child2Root
and Root
to Response
. For Entity
you can think of the process as creating an EntityRoot
containing (the result of applying templates to) all the child elements except Child1 and Child2, then apply templates to these two afterwards, outside the EntityRoot
element:
<xsl:template match="Entity">
<EntityRoot>
<xsl:apply-templates select="@* | node()[not(self::Child1 | self::Child2)]" />
</EntityRoot>
<xsl:apply-templates select="Child1 | Child2" />
</xsl:template>
To strip out a layer entirely (in this case Family
) but still include its children you can use a template without a copy
:
<xsl:template match="Family">
<xsl:apply-templates />
</xsl:template>
Upvotes: 2