Changing namespaces within an xml file with XSLT
Facts - XSLT
Saturday, 10 July 2010 20:19

The following stylesheet changes namespaces in a source document. A namespace urn:data1 is changed into urn:data2 and urn:bom1 is changed into urn:bom2.

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:bom1="urn:bom1" xmlns:data1="urn:data1" 
  xmlns:bom2="urn:bom2" xmlns:data2="urn:data2">
  <xsl:output method="xml" indent="yes"/>
 
  <xsl:template match="/|comment()|processing-instruction()">
    <xsl:copy>
      <!-- go process children (applies to root node only) -->
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>
 
  <xsl:template match="*[namespace-uri(.)='urn:bom1']">
    <xsl:variable name="tempname">
      <xsl:value-of select="concat('bom2:',local-name())"/>
    </xsl:variable>
    <xsl:element name="{$tempname}">
      <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
  </xsl:template>
 
  <xsl:template match="*[namespace-uri(.)='urn:data1']">
    <xsl:variable name="tempname">
      <xsl:value-of select="concat('data2:',local-name())"/>
    </xsl:variable>
    <xsl:element name="{$tempname}">
      <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
  </xsl:template>
 
  <xsl:template match="@*">
    <xsl:attribute name="{local-name()}">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:template>
 
</xsl:stylesheet>

The stylesheet can tested with the following cygwin command:

xsltproc -output output.xml changeNamespace.xsl test.xml

An example input document:

<?xml version="1.0" encoding="UTF-8" ?>
<bom1:rootelem     
    xmlns:bom1="urn:bom1"
    xmlns:data1="urn:data1"
>
  <data1:child1>
    CHILD1
    <bom1:child2>ABC</bom1:child2>
  </data1:child1>
  <data1:child3>
    CHILD3
    <bom1:child4>PQR</bom1:child4>
  </data1:child3>
</bom1:rootelem>

This document generates the following output:

<?xml version="1.0"?>
<bom2:rootelem xmlns:bom2="urn:bom2">
  <data2:child1 xmlns:data2="urn:data2">
    CHILD1
    <bom2:child2>ABC</bom2:child2>
  </data2:child1>
  <data2:child3 xmlns:data2="urn:data2">
    CHILD3
    <bom2:child4>PQR</bom2:child4>
  </data2:child3>
</bom2:rootelem>