Generic way to remove specific inline namespace declarations

Viewed 33

For example, I have XML as following:

<RootNode xmlns:test1="test1Namespace"
           xmlns:test2="childNamespace">
    <test1:SomeElement>
        <OtherElement xmlns="test1Namespace">
            <test2:ChildElement>test</test2:ChildElement> 
        </OtherElement>
    </test1:SomeElement>
</RootNode>

I want to add namespace prefix to all elements that have inline XML namespace definition ( in this case "OtherElement") and remove its inline namespace definition, but leave other possible attributes it might contain.

Other XML nodes should not change. All of this should be done using XSLT 1.0. Result should be as follows:

 <RootNode xmlns:test1="test1Namespace"
               xmlns:test2="childNamespace">
        <test1:SomeElement>
            <test1:OtherElement>
                <test2:ChildElement>test</test2:ChildElement> 
            </test1:OtherElement>
        </test1:SomeElement>
    </RootNode>
1 Answers

Not sure what exactly you mean by a "generic" way. In the given example, you could use:

XSLT 1.0

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

</xsl:stylesheet>

to get the desired result. This is "generic" in the sense that the elements to be renamed do not have to be specified in detail; however, the namespace and its prefix does.


P.S. Note that the result is semantically identical to the input. If your target application uses a conforming XML parser, this exercise accomplishes nothing.

Related