Search code examples
xmlxsltxslt-1.0xslt-2.0

XSLT: Copy a node of XML and change namespace


I need copy a node of XML, remove all prefix namespaces and change the namespace, below the an example of the "orignal" XML and the expected outcome.

Original:

<service:Body xmlns:service="xxx.yyy.zzz" xmlns:schema="aaa.bbb.ccc">
  <schema:MAIN>
    <schema:Message>
      <schema:XXXXX0>
        <schema:XXXXX010>XXXXX0</schema:XXXXX010>
        <schema:XXXXX020>I</schema:XXXXX020>
        <schema:XXXXX030>8888</schema:XXXXX030>
        <schema:XXXXX040>08</schema:XXXXX040>
        <schema:XXXXX050>0002</schema:XXXXX050>
        <schema:XXXXX060>01</schema:XXXXX060>
        <schema:XXXXX090>00</schema:XXXXX090>
        <schema:XXXXX100>20190830122000</schema:XXXXX100>
        <schema:XXXXX110>1.0</schema:XXXXX110>
        <schema:XXXXX120>A</schema:XXXXX120>
        <schema:XXXXX130>AAA</schema:XXXXX130>
        <schema:XXXXX140>1</schema:XXXXX140>
        <schema:XXXXX150>PTT</schema:XXXXX150>
      </schema:XXXXX0>
    </schema:Message>
  </schema:MAIN>
</service:Body>

Expected outcome

<ns0:Message xmlns:ns0="hhh.kkk.yyy">
  <XXXXX0>
    <XXXXX010>XXXXX0</XXXXX010>
    <XXXXX020>I</XXXXX020>
    <XXXXX030>8888</XXXXX030>
    <XXXXX040>08</XXXXX040>
    <XXXXX050>0002</XXXXX050>
    <XXXXX060>01</XXXXX060>
    <XXXXX090>00</XXXXX090>
    <XXXXX100>20190830122000</XXXXX100>
    <XXXXX110>1.0</XXXXX110>
    <XXXXX120>A</XXXXX120>
    <XXXXX130>AAA</XXXXX130>
    <XXXXX140>1</XXXXX140>
    <XXXXX150>PTT</XXXXX150>
  </XXXXX0>
</ns0:Message>


Solution

  • You can solve this with XSLT-1.0 only.

    Use the following stylesheet which sets the appropriate namespaces and then removes the surrounding schema:Body and schema:MAIN elements with a template. After that, it also removes the namespace from the schema:Message element and recreates it with the new target namespace hhh.kkk.yyy. Now it's ease to remove to remove the remaining namespaces of the rest of the elements with a modified Identity template. The xsl:strip-space... just gets rid of some unnecessary spaces in the output.

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:service="xxx.yyy.zzz" xmlns:schema="aaa.bbb.ccc" xmlns:ns0="hhh.kkk.yyy">
    <xsl:strip-space elements="schema:MAIN" />
    
      <!-- Modified identity template --> 
      <xsl:template match="*">
          <xsl:element name="{local-name()}">
              <xsl:apply-templates select="node()|@*" />
          </xsl:element>
      </xsl:template>     
    
      <xsl:template match="service:Body | schema:MAIN">
          <xsl:apply-templates select="node()|@*" />
      </xsl:template>
    
      <xsl:template match="schema:Message">
          <xsl:element name="ns0:Message" namespace="hhh.kkk.yyy">
              <xsl:apply-templates select="node()|@*" />
          </xsl:element>
      </xsl:template>
    
    </xsl:stylesheet>
    

    Its output is:

    <ns0:Message xmlns:ns0="hhh.kkk.yyy">
      <XXXXX0>
        <XXXXX010>XXXXX0</XXXXX010>
        <XXXXX020>I</XXXXX020>
        <XXXXX030>8888</XXXXX030>
        <XXXXX040>08</XXXXX040>
        <XXXXX050>0002</XXXXX050>
        <XXXXX060>01</XXXXX060>
        <XXXXX090>00</XXXXX090>
        <XXXXX100>20190830122000</XXXXX100>
        <XXXXX110>1.0</XXXXX110>
        <XXXXX120>A</XXXXX120>
        <XXXXX130>AAA</XXXXX130>
        <XXXXX140>1</XXXXX140>
        <XXXXX150>PTT</XXXXX150>
      </XXXXX0>
    </ns0:Message>