Reputation: 5040
I have the following xml structure:
<root>
<a>
<b>
<c>
<c1>123</c1>
<c2>abc</c2>
</c>
<d/>
<e/>
<f/>
</b>
</a>
</root>
How do I remove <b>
but preserve <c>
and its child nodes under a, like
<root>
<a>
<c>
<c1>123</c1>
<c2>abc</c2>
</c>
</a>
</root>
Upvotes: 2
Views: 2292
Reputation: 116982
I think you want to do simply:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="b">
<xsl:apply-templates select="c"/>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1
Reputation: 22617
Use an identity transform with an exception. This extra template
<xsl:template match="a/*[not(self::c)]">
matches an element if it is a child of a
, but not named "c". If this is the case, the element is simply ignored, together with all its content.
EDIT: You have changed the requirement, I have changed the code and output. Now, the b
element is traversed and all child elements of b
are ignored, except for c
.
Stylesheet
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="b">
<xsl:apply-templates select="@*|node()"/>
</xsl:template>
<xsl:template match="b/*[not(self::c)]"/>
</xsl:transform>
XML Input
<root>
<a>
<b>
<c>
<c1>123</c1>
<c2>abc</c2>
</c>
<d/>
<e/>
<f/>
</b>
</a>
</root>
XMl Output
<?xml version="1.0" encoding="UTF-8"?>
<root>
<a>
<c>
<c1>123</c1>
<c2>abc</c2>
</c>
</a>
</root>
Upvotes: 5