XSLT: How to change an attribute value during <xsl:copy>?

tomato picture tomato · Mar 5, 2009 · Viewed 92.1k times · Source

I have an XML document, and I want to change the values for one of the attributes.

First I copied everything from input to output using:

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

And now I want to change the value of the attribute "type" in any element named "property".

Answer

Dimitre Novatchev picture Dimitre Novatchev · Mar 6, 2009

This problem has a classical solution: Using and overriding the identity template is one of the most fundamental and powerful XSLT design patterns:

<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:param name="pNewType" select="'myNewType'"/>

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

    <xsl:template match="property/@type">
        <xsl:attribute name="type">
            <xsl:value-of select="$pNewType"/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

When applied on this XML document:

<t>
  <property>value1</property>
  <property type="old">value2</property>
</t>

the wanted result is produced:

<t>
  <property>value1</property>
  <property type="myNewType">value2</property>
</t>