Re: [xsl] How to move the namespaces onto the root element when there is a namespace prefix that is bound to different namespaces?

Subject: Re: [xsl] How to move the namespaces onto the root element when there is a namespace prefix that is bound to different namespaces?
From: Michael Kay <mike@xxxxxxxxxxxx>
Date: Sun, 13 Jan 2013 20:03:32 +0000
Well, if you only want to move the first namespace declaration with any given prefix to the root, you could do something like this:

<xsl:copy-of select="@*"/>
<xsl:for-each-group select="//namespace::*" group-by="name()">
  <xsl:copy-of select="current-group()[1]"/>
</xsl:for-each-group>
<xsl:copy-of select="child::node()"/>

Michael Kay
Saxonica

(Actually current-group()[1] could be written ".", but I think it's more readable as written).

On 13/01/2013 19:29, Costello, Roger L. wrote:
Hi Folks,

I found this wonderful code [1] from Michael Kay to move the namespace declarations up onto the root element:

   <xsl:template match="/*">
     <xsl:copy>
       <xsl:copy-of select="@*, //namespace::*, child::node()"/>
     </xsl:copy>
   </xsl:template>

That works great, provided the XML document doesn't have the same namespace prefix bound to different namespaces. For example, it fails on this XML document:

<Test xmlns="A">
     <ns1:element xmlns:ns1="B">Hello</ns1:element>
     <ns1:element xmlns:ns1="C">C</ns1:element>
</Test>

Notice that the namespace prefix, ns1, is bound to two different namespaces.

Applying the XSLT program to the XML document results in this error:

     Cannot create two namespace nodes with the same
     prefix mapped to different URIs (prefix=ns1, URI=C,
     URI=B)

How do I move the namespace declarations up onto the root element, while taking in account that the XML document may contain a namespace prefix that is bound to different namespaces?

/Roger

[1] http://www.mhonarc.org/archive/html/xsl-list/2009-10/msg00153.html

Current Thread