Altova Mailing List Archives>Archive Index >comp.text.xml Archive Home >Recent entries >Thread Prev - cascading deletion/copy in xsl >Thread Next - Re: cascading deletion/copy in xsl Re: cascading deletion/copy in xslTo: NULL Date: 1/4/2007 4:57:00 PM <tschwartz@r...> wrote in message news:1167950447.064161.294510@1...... >I have an xml document in which elements are hierarchically related to > eachother conceptually. Unfortunately, the hierarchical relationship > is not modelled in the schema (i.e., the elements are "flattened" in > the document". I have a case in which I want to remove a high level > element using xslt and want all the related lower-level elements to be > removed as well. Is there an easy way to do this in a template? > > For example, imagine a relationship of elements describing animals > starting with "animal" at the top of the hierarchy and ending in "pets" > at the bottom: > > animal => class => beastie => breed => pet > > Given the xml below, say I wanted to remove the class named "Aves" and > wanted to cause a cascading removal of all other elements related to > "Aves". Is there a simple way to do this using xsl that helps me avoid > writing specific templates for each child node of "animals"? > > <?xml version="1.0" encoding="utf-8"?> > <animals> > > <classes> > <class name="Mammalia"/> > <class name="Aves"/> > </classes> > > <beasties> > <beast type="cat" class="Mammalia"/> > <beast type="dog" class="Mammalia"/> > <beast type="bird" class="Aves"/> > </beasties> > > <breeds> > <breed name="collie" type="dog"/> > <breed name="beagle" type="dog"/> > <breed name="persian" type="cat"/> > <breed name="siamese" type="cat"/> > <breed name="parakeet" type="bird"/> > <breed name="crow" type="bird"/> > </breeds> > > <pets> > <pet name="rover" breed="collie"/> > <pet name="fluffy" breed="persian"/> > <pet name="tweety" breed="parakeet"/> > </pets> > > </animals> > > The desired xml output would be this: > > <?xml version="1.0" encoding="utf-8"?> > <animals> > > <classes> > <class name="Mammalia"/> > </classes> > > <beasties> > <beast type="cat" class="Mammalia"/> > <beast type="dog" class="Mammalia"/> > </beasties> > > <breeds> > <breed name="collie" type="dog"/> > <breed name="beagle" type="dog"/> > <breed name="persian" type="cat"/> > <breed name="siamese" type="cat"/> > </breeds> > > <pets> > <pet name="rover" breed="collie"/> > <pet name="fluffy" breed="persian"/> > </pets> > > </animals> XSLT 1.0 solution (49 lines): <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:param name="pClassToDel" select="'Aves'"/> <xsl:key name="kBeastByType" match="beast" use="@type"/> <xsl:key name="kBreedByName" match="breed" use="@name"/> <xsl:template match="node()|@*" name="identity"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match="class"> <xsl:if test="not(@name = $pClassToDel)"> <xsl:call-template name="identity"/> </xsl:if> </xsl:template> <xsl:template match="beast"> <xsl:if test="not(@class = $pClassToDel)"> <xsl:call-template name="identity"/> </xsl:if> </xsl:template> <xsl:template match="breed"> <xsl:if test= "not(key('kBeastByType', @type)/@class = $pClassToDel)"> <xsl:call-template name="identity"/> </xsl:if> </xsl:template> <xsl:template match="pet"> <xsl:if test= "not(key('kBeastByType', key('kBreedByName', @breed)/@type )/@class = $pClassToDel)"> <xsl:call-template name="identity"/> </xsl:if> </xsl:template> </xsl:stylesheet> Output: <animals> <classes> <class name="Mammalia" /> </classes> <beasties> <beast type="cat" class="Mammalia" /> <beast type="dog" class="Mammalia" /> </beasties> <breeds> <breed name="collie" type="dog" /> <breed name="beagle" type="dog" /> <breed name="persian" type="cat" /> <breed name="siamese" type="cat" /> </breeds> <pets> <pet name="rover" breed="collie" /> <pet name="fluffy" breed="persian" /> </pets> </animals> XSLT 2.0 solution (40 lines): <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xs" > <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:strip-space elements="*"/> <xsl:param name="pClassToDel" select="'Aves'"/> <xsl:key name="kDeleted" match="beast" use="string(@class = $pClassToDel)"/> <xsl:key name="kDeleted" match="class" use="string(@name = $pClassToDel)"/> <xsl:key name="kDeleted" match="breed" use="string(key('kBeastByType',@type)/@class = $pClassToDel)"/> <xsl:key name="kDeleted" match="pet" use="string(key('kBeastByType', key('kBreedByName',@breed)/@type ) /@class = $pClassToDel)"/> <xsl:key name="kBeastByType" match="beast" use="@type"/> <xsl:key name="kBreedByName" match="breed" use="@name"/> <xsl:template match="node()|@*" name="identity"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match="*[. intersect key('kDeleted', 'true')]"/> </xsl:stylesheet> Output: <animals> <classes> <class name="Mammalia"/> </classes> <beasties> <beast type="cat" class="Mammalia"/> <beast type="dog" class="Mammalia"/> </beasties> <breeds> <breed name="collie" type="dog"/> <breed name="beagle" type="dog"/> <breed name="persian" type="cat"/> <breed name="siamese" type="cat"/> </breeds> <pets> <pet name="rover" breed="collie"/> <pet name="fluffy" breed="persian"/> </pets> </animals> Hope this helped. Cheers, Dimitre Novatchev | ||||||
| Company | Legal | Press | Partners | Careers | Sitemap | Contact Us | Altova Blog | Mobile | Full Site | |||
|
