Tuesday, March 4, 2008

Comparing XML attributes with parents attributes

I had a need to test if all/most of the attributes of a child node were equal to its parent and strip out the child node if true.

My XML structure was basically:

<PARAGRAPH style='heading1' emphasis='true' font='arial' number='30' indent=’10’>

<SPECIALTEXT style='heading1' emphasis='true' font='arial' number='31'>

Helloworld

</SPECIALTEXT>

</PARAGRAPH>

Output needed to be:

<PARAGRAPH style='heading1' emphasis='true' font='arial' number='30'>

Helloworld

</PARAGRAPH>

Now this only works on the first level after the PARAGRAPH but that’s all I needed, and it could be changed to do this recursively I guess. Basically I am matching on any paragraph that contains a child element SPECIALTEXT with the same style attribute and calling the template CompareKeyAttributes.
PARAGRAPH has more attributes than SPECIALTEXT in most cases so I compare only the ones that exist in SPECIALTEXT.

CompareKeyAttributes will return a string of all the
attributes that don’t match so then I just check if I care that the attribute
is different and output accordingly.

<xsl:template match="PARAGRAPH[SPECIALTEXT[@Style=./@Style] ] ">

<xsl:copy>

<xsl:apply-templates select="@*"/>

<xsl:for-each select=" child::*">

<xsl:variable name="RESULT">

<xsl:call-template name="CompareKeyAttributes">

<xsl:with-param name="PARA" select=".."/>

<xsl:with-param name="SPEC" select="."/>

</xsl:call-template>

</xsl:variable>

<xsl:choose>

<xsl:whentest="$RESULT='number' ">

<xsl:apply-templates select="child::node()"/>

</xsl:when>

<xsl:otherwise>

<xsl:copy>

<xsl:apply-templates select="@*|node()"/>

</xsl:copy>

</xsl:otherwise>

</xsl:choose>

</xsl:for-each>

</xsl:copy>

</xsl:template>

<xsl:template name="CompareKeyAttributes">

<xsl:param name="PARA"/>

<xsl:param name="SPEC"/>

<xsl:for-each select="$SPEC/@*">

<xsl:variable name="SPEC_ATT" select="name()"/>

<xsl:variable name="PARA_ATT" select="$PARA/@*[name()= $SPEC_ATT]"/>

<xsl:choose>

<xsl:when test="$PARA_ATT != .">

<xsl:value-of select="name()"/>

</xsl:when>

</xsl:choose>

</xsl:for-each>

</xsl:template>

Let me know if you find this useful or have anyway to make it better. Enjoy

No comments: