Raj Sharma
Raj Sharma

Reputation: 195

Replacing xml tag using XSLT

I have an xml file where i need to replace one of the tag without replacing the incoming prefix for the namespace. For example for below XML:

 <f:table xmlns:f="https://www.test.com">
  <f:name>Peter</f:name>
  <f:lname>Jenkins</f:lname>
  <f:height>71</f:height>
</f:table>

I need to replace lname with lastname but still keep the prefix (f in this case) intact. Desired output would be like below. Note the prefix can change so it won't be f always

<f:table xmlns:f="https://www.test.com">
  <f:name>Peter</f:name>
  <f:lastname>Jenkins</f:lastname>
  <f:height>71</f:height>
</f:table>

I have tried with below XSLT and this would replace lname with lastname without the original prefix intact. Please help

<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="table/lname">
        <lastname><xsl:apply-templates select="@*|node()" /></lastname>
    </xsl:template>
</xsl:stylesheet>

Upvotes: 1

Views: 1374

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 116959

The prefix has no significance. The following stylesheet:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns0="https://www.test.com">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="ns0:lname">
    <ns0:lastname>
        <xsl:apply-templates/>
    </ns0:lastname>
</xsl:template>

</xsl:stylesheet>

when applied to your input example, will return:

<?xml version="1.0" encoding="UTF-8"?>
<f:table xmlns:f="https://www.test.com">
  <f:name>Peter</f:name>
  <ns0:lastname xmlns:ns0="https://www.test.com">Jenkins</ns0:lastname>
  <f:height>71</f:height>
</f:table>

which is semantically identical to the output shown in your question.


If for some reason you really need to preserve the original prefix, you could do:

<xsl:template match="ns0:lname">
    <xsl:variable name="uri" select="'https://www.test.com'" />
    <xsl:variable name="prefix" select="name(namespace::*[.=$uri])" />
    <xsl:element name="{$prefix}:lastname" namespace="{$uri}">
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

Upvotes: 2

Related Questions