Thursday, June 10, 2010

Remove duplicate nodes from XML using XSLT

HI All!

Its been a long time since my last post. I finally got something which I feel need to be posted else I will have a hard

time finding it later.

Ok, one of my recent quests was how to remove duplicate nodes from an xml like below


<?xml version="1.0" encoding="utf-16"?>
<country>
<state>
<count>19</count>
<city>
<street name="id" value="1" />
<street name="name" value="MGROAD" />
</city>
<city>

<street name="id" value="2" />
<street name="name" value="SAVOY" />

</city>
<city>

<street name="id" value="3" />
<street name="name" value="MTBATTENROAD" />

</city>
</state>
</country>


Now if we want to transform this XML into another XML without the repeating
<street id="1" name="MGROAD" /> tag then the xsl to be used is thus :


<xsl:stylesheet version="1.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 ="count">
</xsl:template>

<xsl:template match="city">

<xsl:copy>
<xsl:apply-templates select="@*"/>
<street>
<xsl:attribute name ="id">
<xsl:value-of select ="current()/self::node()/street[@name='id']/@value"/>
</xsl:attribute>
<xsl:attribute name ="name">
<xsl:value-of select ="current()/self::node()/attribute[@name='name']/@value"/>
</xsl:attribute>
</attribute>
</xsl:copy>


</xsl:template>

</xsl:stylesheet>



Transform this using XSLT

XmlDocument stripper = new XmlDocument();
stripper.Load(Server.MapPath("~/App_Data/transform.xsl")); //Compile here
StringWriter output = new StringWriter();
XslCompiledTransform emptyNodeRemover = new XslCompiledTransform();
emptyNodeRemover.Load(stripper); //Port output to string
output = new StringWriter();
XmlDocument source = new XmlDocument();

source.Load(Server.MapPath("~/App_Data/response.xml"));

emptyNodeRemover.Transform(new XmlNodeReader(source), null, output);
output.Flush(); //Reload source with emptied nodes
source.LoadXml(output.ToString());


The above xsl also specifies to restructure the xml file into


<?xml version="1.0" encoding="utf-16"?>
<country>
<state>
<count>19</count>
<city>
<street id="1" name="MGROAD" />
</city>
<city>
<street id="2" name="SAVOY" />
</city>
<city>
<street id="3" name="MTBATTENROAD" />
</city>
</state>
</country>


Now this transformed XML can be fed into a telerik RadGrid successfully as it is the format it accepts.

Cheers!

No comments: