Reputation: 21
I am new in XSLT, i need to delete few child node on the basis of attribute value and then delete their parent node if there are no child tag present under it.
For example Sample XML input Type 1:
<?xml version="1.0" encoding="UTF-8"?>
<GrandFather>
<Father>
<Father-bro>Bro</Father-bro>
<Father-sis>Sis</Father-sis>
<Child name="real">Real Children</Child>
<Child name="fake">FakeChildren</Child>
</Father>
</GrandFather>
Expected Output:
<?xml version="1.0" encoding="UTF-8"?>
<GrandFather>
<Father>
<Father-bro>Bro</Father-bro>
<Father-sis>Sis</Father-sis>
<Child name="real">Real Children</Child>
</Father>
</GrandFather>
For example Sample XML input Type 2:
<?xml version="1.0" encoding="UTF-8"?>
<GrandFather>
<Father>
<Father-bro>Bro</Father-bro>
<Father-sis>Sis</Father-sis>
<Child name="fake">Real Children</Child>
<Child name="fake">FakeChildren</Child>
</Father>
</GrandFather>
Expected OutPut: Remove Father tag if there is no tag of child of name attribute "fake" and remove grandfather tag if there is no father tag at all(as father tag will get removed from earlier logic)
<?xml version="1.0" encoding="UTF-8"?>
Requirement:
If child tag have "name" attribute value as "fake", then we should remove that particular child tag. All child tag can have name attribute as "fake" or none. After that check:
If there is no child tag under Father tag then remove father tag also or else remove only child tag with name attribute as "fake" and keep the real child along with other tag.
If there is no father tag under grandfather tag then remove grandfather tag.
My Code anaysis: I was able to write xsl which will remove all the child tag containg name attribute as "fake". But when I do same for father or grandfather tag, then it does not consider the removed child xml (output of first xsl:template), rather it check with original xml template.
My XSL(this will remove all the child having attribute name as "fake") for sample input xml type 1, but it will not cover when input type is sample input xml 2
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//Child[@name='fake']"/>
</xsl:stylesheet>
Can anyone help me on this?
Upvotes: 0
Views: 817
Reputation: 116993
I believe you could accomplish it all in a single pass:
XSLT 1.0
<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="/">
<xsl:apply-templates select="GrandFather[Father/Child[not(@name='fake')]]"/>
</xsl:template>
<xsl:template match="GrandFather">
<xsl:copy>
<xsl:apply-templates select="Father[Child[not(@name='fake')]]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Child[@name='fake']"/>
</xsl:stylesheet>
Upvotes: 0