1

I am having kind of more trouble with this than I should and have not been able to find a solution that seems to be right:

I want to simply change the namespace of an XML document using xslt 1.0 - used withing a java application, using javax.xml.transform.

This is my xml document:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root xmlns="http://namespace1.org" type="Document" version="V2_2">
    <Content>
        <Text>asdf</Text>
    </Content>
</Root>

This is how it should look after transformation:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Root xmlns="http://namespace2.org" type="Document" version="V2_2">
    <Content>
        <Text>asdf</Text>
    </Content>
</Root>

This is my xslt code:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns="http://namespace2.org">

  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>

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

</xsl:stylesheet>

And this is the actual output I get after the transformation:

<?xml version="1.0" encoding="UTF-8"?>
<ns0:Root xmlns:ns0="http://namespace2.org">2012-11-02T15:39:46.05+01:00DocumentV2_2<ns1:Content xmlns:ns1="http://namespace2.org">
  <ns2:Text xmlns:ns2="http://namespace2.org">asdf</ns2:Text>
 </ns1:Content>
</ns0:Root>

There are way to many prefixes added, which I do not want.

I have been able to get rid of the ns+increment prefix by using the following xlst:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns="http://namespace2.org"
 xmlns:cmp="http://namespace2.org"
 exclude-result-prefixes="cmp">

  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="*">
     <xsl:element name="cmp:{name()}" namespace="http://namespace2.org">
       <xsl:copy-of select="@*"/>
       <xsl:apply-templates/>
     </xsl:element>
 </xsl:template>

</xsl:stylesheet>

which produces the following output:

<?xml version="1.0" encoding="UTF-8"?>
<cmp:Root xmlns:cmp="http://namespace2.org" type="Document" version="V2_2">
 <cmp:Content>
  <cmp:Text>asdf</cmp:Text>
 </cmp:Content>
</cmp:Root>

But I have not been able to get rid of the 'cmp' prefix.

Any ideas how I could achieve the desired output?

1
  • 1
    I'm curious - if you're using Java, then why on earth are you still using XSLT 1.0? Commented Dec 20, 2012 at 22:54

1 Answer 1

2

This generic transformation (applicable on any XML document, and the new namespace is passed as global/external parameter):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pNewNS" select="'http://namespace2.org'"/>

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

 <xsl:template match="*">
  <xsl:element name="{name()}" namespace="{$pNewNS}">
   <xsl:copy-of select="namespace::*[not(name() = '')]"/>
   <xsl:apply-templates select="@*|node()"/>
  </xsl:element>
 </xsl:template>

 <xsl:template match="@*">
  <xsl:attribute name="{name()}">
   <xsl:value-of select="."/>
  </xsl:attribute>
 </xsl:template>

 <xsl:template match="@*[namespace-uri()=namespace-uri(/*)]">
  <xsl:attribute name="{name()}" namespace="{$pNewNS}">
   <xsl:value-of select="."/>
  </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document:

<Root xmlns="http://namespace1.org" type="Document" version="V2_2">
    <Content>
        <Text>asdf</Text>
    </Content>
</Root>

produces the wanted, correct result:

<Root xmlns="http://namespace2.org" type="Document" version="V2_2">
   <Content>
      <Text>asdf</Text>
   </Content>
</Root>
Sign up to request clarification or add additional context in comments.

3 Comments

Unfortunately I could not verify this. This is my ouput with your xslt: <?xml version="1.0" encoding="UTF-8"?> <ns0:Root xmlns:ns0="namespace2.org"; ns0:type="Document" ns0:version="V2_2"> <ns1:Content xmlns:ns1="namespace2.org">; <ns2:Text xmlns:ns2="namespace2.org">asdf</ns2:Text>; </ns1:Content> </ns0:Root> Probably this is an issue with the java implementation of the xslt transformer?
@codeySmurf, The W3C XSLT 1.0 specification doesn't prevent the XSLT processor from adding a generated namespace prefix to the element name. And some XSLT processors, like the one you are using add a prefix to the element names and don't generate a default namespace. The document you get as result and the document I get are exactly the same documents -- they only have differences in their lexical representation. I used Saxon 6.5.4 and got the result that I copied and pasted in my answer. I get exactly the same result with all 12 XSLT processors I have installed on my computer.
@codeySmurf I get exactly the same result with all 12 XSLT processors I have installed on my computer MSXML 3/4/6, .Net XslCompiledTransform and XslTransform, Saxon 6.5.4, 9.1.07, 9.4.06, .NET, Altova (XML-SPY XSLT 1.0 and XSLT 2.0), XQSharp.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.