Reputation: 109
I have a XML file for which transformation rules should be applied for certain elements only based on its attribute value and the rest should be retained as it is.
<bigdata>
<data>
<Object class="QWE" Name="Country-1/State-1/QWE-1">
<p name="Map">20</p>
<p name="Required">0</p>
<p name="Combined">68</p>
<p name="State">0</p>
</Object>
<Object class="RTY" Name="Country-1/State-1/RTY-1">
<p name="Map">20</p>
<p name="Required">0</p>
<p name="Combined">68</p>
<p name="State">0</p>
</Object>
<Object class="UIO" Name="Country-1/State-1/UIO-1">
<p name="Map">20</p>
<p name="Required">0</p>
<p name="Combined">68</p>
<p name="State">0</p>
</Object>
<Object class="PAS" Name="Country-1/State-1/PAS-1">
<p name="Map">20</p>
<p name="Required">0</p>
<p name="Combined">68</p>
<p name="State">0</p>
</Object>
</data>
The above xml should be converted to below xml snippet where only xml element Object for which class equals QWE should be changed to POST. ie only first element in must be changed based on its attribute. Any advices on this would be gratefull
<bigdata>
<data>
<Object class="POST" Name="Country-1/State-1/POST-1">
<p name="Map">20</p>
<p name="Required">0</p>
<p name="Combined">68</p>
<p name="State">0</p>
</Object>
<Object class="RTY" Name="Country-1/State-1/RTY-1">
<p name="Map">20</p>
<p name="Required">0</p>
<p name="Combined">68</p>
<p name="State">0</p>
</Object>
<Object class="UIO" Name="Country-1/State-1/UIO-1">
<p name="Map">20</p>
<p name="Required">0</p>
<p name="Combined">68</p>
<p name="State">0</p>
</Object>
<Object class="PAS" Name="Country-1/State-1/PAS-1">
<p name="Map">20</p>
<p name="Required">0</p>
<p name="Combined">68</p>
<p name="State">0</p>
</Object>
</data>
Upvotes: 0
Views: 162
Reputation: 9627
Try this:
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Object/@class[. = 'QWE' ]">
<xsl:attribute name="class">
<xsl:value-of select="'POST'"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
Which will generate the following output:
<bigdata>
<data>
<Object class="POST" Name="Country-1/State-1/QWE-1">
<p name="Map">20</p>
<p name="Required">0</p>
<p name="Combined">68</p>
<p name="State">0</p>
</Object>
<Object class="RTY" Name="Country-1/State-1/RTY-1">
<p name="Map">20</p>
<p name="Required">0</p>
<p name="Combined">68</p>
<p name="State">0</p>
</Object>
<Object class="UIO" Name="Country-1/State-1/UIO-1">
<p name="Map">20</p>
<p name="Required">0</p>
<p name="Combined">68</p>
<p name="State">0</p>
</Object>
<Object class="PAS" Name="Country-1/State-1/PAS-1">
<p name="Map">20</p>
<p name="Required">0</p>
<p name="Combined">68</p>
<p name="State">0</p>
</Object>
</data>
</bigdata>
Update if the class value should be start with a string (QWE) and only this part should be replaced. Try this:
<xsl:template match="Object/@class[starts-with(., 'QWE') ]">
<xsl:attribute name="class">
<xsl:value-of select="'POST'"/>
<xsl:value-of select="substring-after(.,'QWE')"/>
</xsl:attribute>
</xsl:template>
Upvotes: 1
Reputation: 900
Use following XSLT to transform above xml:
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@class[parent::Object]">
<xsl:choose>
<xsl:when test=".='QWE'">
<xsl:attribute name="class">
<xsl:value-of select="'POST'"/>
</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="class">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
refer this for more info:
XSLT: How to change an attribute value during <xsl:copy>?
Upvotes: 0