Home > front end >  Remove Namespace and add new elements while copying XML
Remove Namespace and add new elements while copying XML

Time:04-13

I have a simple xml that looks like

<ns0:AAA xmlns:ns0="http://www.example.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ITSVersion="XML_1.0">
    <ns0:id extension="USER_TYPE"/>
    <ns0:bb>SOME VALUE</ns0:bb>
    <ns0:cc>OTHER VALUE</ns0:cc>
</ns0:AAA>

I am trying to add a "wrapper" element around a top-level element AAA and also remove the name-space prefix ns0 from the above xml. Lastly add new elements after the <ns0:bb>SOME VALUE</ns0:bb>.

I have tried building an xslt for that, but somehow I could not remove the ns0 prefix when copying and the new elements that I have added are added with xmlns="". Not sure what I am doing wrong.

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

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>           
    </xsl:copy>
</xsl:template>
    
<xsl:template match="/*">
    <xsl:if test="urn:id[@extension='USER_TYPE']">
         <xsl:element name="WRAPPER" namespace="{namespace-uri()}">
            <xsl:apply-templates select="@* | node()" />
                
                <xsl:element name="cred">
                    <xsl:attribute name="user">test123</xsl:attribute>
                    <xsl:element name="password">
                            <xsl:attribute name="root">n</xsl:attribute>
                    </xsl:element>
                </xsl:element>
        </xsl:element>
    </xsl:if>
    
    <xsl:if test="urn:Id[@extension='ASSET_TYPE']">
        <xsl:element name="WRAPPER" namespace="{namespace-uri()}">
            <xsl:apply-templates select="@* | node()" />
        </xsl:element>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

The output of the xslt looks like

<WRAPPER xmlns="http://www.example.com" ITSVersion="XML_1.0">
    <ns0:id xmlns:ns0="http://www.example.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" extension="USER_TYPE"/>
    <ns0:bb xmlns:ns0="http://www.example.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">SOME VALUE</ns0:bb>
    <ns0:cc xmlns:ns0="http://www.example.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">OTHER VALUE</ns0:cc>
    <cred xmlns="" user="test123"><password root="n"/></cred>
</WRAPPER>

As you can see the WRAPPER element is added correctly, but all the other elements have the prefix and also the xmlns attributes, I want to remove the prefix ns0 and xmlns attributes from those elements. And the new element that I am adding cred shows up with an empty xmlns.

Any idea what I am doing wrong here?

Thanks in Advance for any help?

CodePudding user response:

What you call "remove namespace" actually requires renaming. That means you cannot use the identity transform template which preserves the processed nodes as is.

Try instead something along the lines of:

XSLT 1.0

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

<xsl:template match="*">
    <xsl:element name="{local-name()}">
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates/>      
    </xsl:element>
</xsl:template>
    
<xsl:template match="/*">
    <WRAPPER>
        <xsl:apply-templates/>
        <cred user="test123">
            <password root="n"/>
        </cred>
    </WRAPPER>
</xsl:template>

</xsl:stylesheet>

Applied to your example input, this will produce:

Result

<?xml version="1.0" encoding="UTF-8"?>
<WRAPPER>
   <id extension="USER_TYPE"/>
   <bb>SOME VALUE</bb>
   <cc>OTHER VALUE</cc>
   <cred user="test123">
      <password root="n"/>
   </cred>
</WRAPPER>

Note the use of literal result elements.

  • Related