user1529282
user1529282

Reputation: 109

XSL Transformation only for certain element based on attributes

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

Answers (2)

hr_117
hr_117

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

Madurika Welivita
Madurika Welivita

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

Related Questions