Search code examples
xsltnamespacesxsi

XSLT missing namespaces in inner tags that have same namespace declaration as the root element


I would like to create xml like this:

<rns:RootElement xmlns:rns="urn:root-element" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:root-element root-element.xsd">
    <rns:DocumentWrapper>
        <ins:InnerDoc xmlns:ins="urn:inner-doc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:inner-doc inner-doc.xsd">
            <ins:Value>Some text</ins:Value>
        </ins:InnerDoc>
    </rns:DocumentWrapper>
</rns:RootElement>

With this template:

<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/">

    <rns:RootElement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                     xmlns:rns="urn:root-element"
                     xsi:schemaLocation="urn:root-element root-element.xsd">
        <rns:DocumentWrapper>
            <ins:InnerDoc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                          xmlns:ins="urn:inner-doc"
                          xsi:schemaLocation="urn:inner-doc inner-doc.xsd">
                <ins:Value><xsl:value-of select="//*[local-name()='SomeNode']"/></ins:Value>
            </ins:InnerDoc>
        </rns:DocumentWrapper>
    </rns:RootElement>

</xsl:template>

But instead of result that i wanted this template gave me a little bit different result:

<rns:RootElement xmlns:rns="urn:root-element" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:root-element root-element.xsd">
    <rns:DocumentWrapper>
        <ins:InnerDoc xmlns:ins="urn:inner-doc" xsi:schemaLocation="urn:inner-doc inner-doc.xsd">
            <ins:Value>Some text</ins:Value>
        </ins:InnerDoc>
    </rns:DocumentWrapper>
</rns:RootElement>

As you can see, in transformation result, InnerDoc element lacks definition of xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" namespace, is there any way to prevent missing of this namespace?


Solution

  • As the namespace declaration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" is present on the root element it is in scope for the child and descendant elements and does not need to be repeated for the ins:InnerDoc element. I don't know of any way to enforce the output of duplicated namespace declarations with XSLT.

    Some other APIs have a way to suppress them, like LINQ to XML with the OmitDuplicateNamespaces on the SaveOptions https://msdn.microsoft.com/en-us/library/system.xml.linq.saveoptions(v=vs.110).aspx, but that option was added rather to suppress duplicate namespace declarations when serializing LINQ to XML trees, not to enforce them.