xmlxsltxslt-1.0multipass

Remove namespace from a specific node, use the result for 2nd xslt(version1.0) transformation


I am a newbie on XSLT and I am finding the concept bit difficult to grasp; any book or link suggestion?

I am trying to remove the namespace from customerinfo node and all its child nodes i.e. customerinfo,name and age. After the namespace has been removed i want to use the resulting xml as a input for other xslts?

XML 1:

    <uc:cpy xmlns:uc="http://oldcompany.com">
     <customerinfo xmlns="http://oldcompany.com" xmlns:d="http://test" Cid="1004" fid="aa">
        <name xmlns="http://oldcompany.com">Matt Foreman</name>
        <age xmlns="http://oldcompany.com">26</age>
     </customerinfo>

     <uc:prodcut xmlns="http://oldcompany.com" xmlns:d="http://test" >
        <uc:item>Hammer</uc:item>
        <uc:quantity>1</uc:quantity>
     </uc:prodcut> 
    </uc:cpy>

XML 2: after removing namespace; leaving the attribute value as-is:

    <uc:cpy xmlns:uc="http://oldcompany.com">
     <customerinfo Cid="1004" fid="aa">
        <name>Matt Foreman</name>
        <age>26</age>
     </customerinfo>

     <uc:prodcut xmlns="http://oldcompany.com" xmlns:d="http://test" >
        <uc:item>Hammer</uc:item>
        <uc:quantity>1</uc:quantity>
     </uc:prodcut> 
    </uc:cpy>

Finally, pass the xml 2 as input for other xslt template imports on the document.


Solution

  • I am trying to remove the namespace from customerinfo node and all its child nodes i.e. customerinfo,name and age.

    If you know in advance the names of all child (or descendant) nodes of customerinfo, you can do:

    XSLT 1.0

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:uc="http://oldcompany.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="uc:customerinfo | uc:name | uc:age" >
        <xsl:element name="{local-name()}">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>
    
    </xsl:stylesheet>
    

    Otherwise do something more general like:

    XSLT 1.0

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:uc="http://oldcompany.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="*[ancestor-or-self::uc:customerinfo]" >
        <xsl:element name="{local-name()}">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>
    
    </xsl:stylesheet>
    

    Note that both methods assume that attributes are not in a namespace (i.e. can be just copied).


    Finally, pass the xml 2 as input for other xslt template imports on the document.

    That's a task for your calling application, not something you can do in XSLT itself. I am not sure why you need to do this in two steps to begin with - why not write a single stylesheet that does it all?