1

I have an xml document where some of the elements have a namespace and others do not. All of them need namespaces, some the same some different. The elements have properties which I want to keep.

The xml:

<foo xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gco="http://www.isotc211.org/2005/gco" xsi:schemaLocation="http://www.isotc211.org/2005/gmd http://schemas.opengis.net/iso/19139/20060504/gmd/gmd.xsd" xmlns="http://www.isotc211.org/2005/gmd">
<bar y="2">
<baz z="3"/></bar>
<a-special-element n="8"/>
<another-special-element k="8"/>
</foo>

And the xslt:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:template match="*">
    <xsl:element name="{local-name()}" namespace="A" >
        <xsl:copy-of select="attribute::*"/>
        <xsl:apply-templates />
    </xsl:element>
</xsl:template>

<xsl:template match="foo">
    <xx:foo xmlns:xx="xx">
        <xsl:apply-templates/>
    </xx:foo>
</xsl:template>

<xsl:template match="a-special-element">
    <B:a-special-element xmlns:B="B">
        <xsl:apply-templates/>
    </B:a-special-element>
</xsl:template>

<xsl:template match="another-special-element">
    <C:a-special-element xmlns:C="C">
        <xsl:apply-templates/>
    </C:another-special-element>
</xsl:template>

</xsl:stylesheet>

Here is the output i would like to have:

<xx:foo xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gco="http://www.isotc211.org/2005/gco" xsi:schemaLocation="http://www.isotc211.org/2005/gmd http://schemas.opengis.net/iso/19139/20060504/gmd/gmd.xsd" xmlns="http://www.isotc211.org/2005/gmd">    <bar y="2">
    <baz z="3"/>
</bar>
<B:a-special-element n="8"/>
<C:another-special-element k="4"/>

</xx:foo>

I checked out this thread but there the property of the "a-special-element" has been magically removed. Add a namespace to elements

Also I have multiple xmlns:??? in the foo that I want to keep.

Community
  • 1
  • 1
Wilbert
  • 13
  • 3
  • There is no namespace "A" declaration. If you declare to not exclude any prefixes (), then even unused ones should be output. – wst Dec 10 '12 at 18:30

1 Answers1

0

First of all: namespaces are a fundamental concept in XML. If you are not familiar with namespaces, please take time to learn and understand them.

I have an xml document where some of the elements have a namespace and others do not.

Actually in your code sample all the elements belong to a namespace.

Code xmlns="http://www.isotc211.org/2005/gmd" in your root element defines a default namespace with URI "http://www.isotc211.org/2005/gmd". Thus this element and its descendants belong to this default namespace if the element name doesn't have a namespace prefix. It's easy to forget that an element is in some namespace, if it uses the default namespace, because there is no namespace prefix. Note that default namespace doesn't apply to attributes, only elements.

Your expected result document is not clear. It should also have namespace definitions for the namespace prefixes xx, B and C. I also assumed that your namespace A is the same as the default namespace used your expected result document.

Anyway, given this input:

<foo xmlns:gml="http://www.opengis.net/gml"
     xmlns:xlink="http://www.w3.org/1999/xlink"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:gco="http://www.isotc211.org/2005/gco"
     xmlns="http://www.isotc211.org/2005/gmd"
     xsi:schemaLocation="http://www.isotc211.org/2005/gmd http://schemas.opengis.net/iso/19139/20060504/gmd/gmd.xsd"
     >
    <bar y="2">
        <baz z="3"/>
    </bar>
    <a-special-element n="8"/>
    <another-special-element k="8"/>
</foo>

This XSLT code:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:gml="http://www.opengis.net/gml"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns:gco="http://www.isotc211.org/2005/gco"
    xmlns:gmd="http://www.isotc211.org/2005/gmd"
    xmlns="http://www.isotc211.org/2005/gmd"
    xmlns:B="B"
    xmlns:C="C"
    xmlns:xx="xx"
    >

<xsl:template match="node() | @*" name="identity">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="*">
    <xsl:element name="{local-name()}">
        <xsl:apply-templates select="node() | @*"/>
    </xsl:element>
</xsl:template>

<xsl:template match="gmd:foo">
    <xx:foo>
        <xsl:apply-templates select="node() | @*"/>
    </xx:foo>
</xsl:template>

<xsl:template match="gmd:a-special-element">
    <B:a-special-element>
        <xsl:apply-templates select="node() | @*"/>
    </B:a-special-element>
</xsl:template>

<xsl:template match="gmd:another-special-element">
    <C:another-special-element>
        <xsl:apply-templates select="node() | @*"/>
    </C:another-special-element>
</xsl:template>

</xsl:stylesheet>

Will produce this output:

<xx:foo xmlns:xx="xx" 
        xmlns:gml="http://www.opengis.net/gml" 
        xmlns:xlink="http://www.w3.org/1999/xlink" 
        xmlns:gco="http://www.isotc211.org/2005/gco" 
        xmlns:gmd="http://www.isotc211.org/2005/gmd" 
        xmlns="http://www.isotc211.org/2005/gmd" 
        xmlns:B="B" 
        xmlns:C="C" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemaLocation="http://www.isotc211.org/2005/gmd http://schemas.opengis.net/iso/19139/20060504/gmd/gmd.xsd"
        >
    <bar y="2">
        <baz z="3"/>
    </bar>
    <B:a-special-element n="8"/>
    <C:another-special-element k="8"/>
</xx:foo>

Notice how an identity template is used to recursively copy the contents of the input document which is a common and useful technique.

Note that the default namespace of the XSLT document doesn't apply to element names used in <xsl:template match="ELEMENT-NAME">. Therefore you need to define a namespace prefix for the default namespace of the input document and use that prefix when you refer to those elements, for example in the match and select attributes. Also note that because of this, the namespace URI http://www.isotc211.org/2005/gmd is defined twice in the result document - with the prefix gmd and as a default namespace. If this bothers you, you can add exclude-result-prefixes="gmd" attribute to the <xsl:stylesheet> element. As a side effect, this could cause your default namespace definition appear later in the document and not in the root element but that is just a visual difference, the underlying functionality stays the same.

jasso
  • 13,736
  • 2
  • 36
  • 50
  • Thanks for your response! I have been called away for a few days however and wont be able to try it right now. I will however keep you posted. – Wilbert Dec 12 '12 at 09:29
  • So now that I am back I had the time to review your answer. I have read the information W3C has on their website regarding Namspaces, it really helped so thanks for pointing that out. I now know the diffirence between default namespaces and "set" namspaces. I think I have been searching for a solution to my problem in the wrong place. – Wilbert Dec 17 '12 at 13:15
  • The problem is that the data get's shown in html on a website. Html created with input from the xml with default namespaces differs from that created with xml with "set" namspaces. Since w3c doesnt say there is a real difference between them I think It's not the namespaces I should be worried about at all. It's the xslt – Wilbert Dec 17 '12 at 13:21