Search code examples
xmlxsltxslt-1.0xslt-2.0

XSLT mapping for selective xml attribute


I have an usecase where I need to modify only one of the attributes in the XML file and need to retain the other segments as it is. Below my sample XML and the XSLT built, I am actually trying to change the "customerDetails" as "userDetails" using XSLT but I am in the need to explicitly mention all other XML attributes in the XSLT.

Is there a way to optimize this like just write logic only customerDetails to userDetails in XSLT by not touching the other attributes?

Sample XML


    <?xml version="1.0" encoding="UTF-8"?>
    <RespData>
        <customerName>XXXX</customerName>
        <customerDetails>
            <customerId>123</customerId>
            <customerAddress>YYYY</customerAddress>
        </customerDetails>
    </RespData>

Sample XSLT


    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:template match="/">
            <RespData>
                <customerName>
                    <xsl:value-of select="/RespData/customerName" />
                </customerName>
                <xsl:for-each select="/RespData/customerDetails">
                    <userDetails>
                        <customerId>
                            <xsl:value-of select="customerId" />
                        </customerId>
                        <customerAddress>
                            <xsl:value-of select="customerAddress" />
                        </customerAddress>
                    </userDetails>
                </xsl:for-each>
            </RespData>
        </xsl:template>
    </xsl:stylesheet>


Solution

  • You don't have any attributes at all, just child elements; as for the right approach, start with the identity transformation which you can declare in XSLT 3 using a top-level <xsl:mode on-no-match="shallow-copy"/> or spell it out in XSLT 1/2 with

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

    then add templates for each micro change you need e.g.

    <xsl:template match="customerDetails">
      <userDetails>
        <xsl:apply-templates/>
      </userDetails>
    </xsl:template>