1

I need (well, really would love...) to add a namespace declaration to the root element of a DOM tree. I repeatedly use that namespace later in the document, and it's not very handy to have the declaration in each node where I use it:

<?xml version="1.0" encoding="UTF-8" standalone="no"?><test>
   <value xmlns:test="urn:mynamespace" test:id="1">42.42</value>
   <value2 xmlns:test="urn:mynamespace" test:id="2">Hello Namespace!</value2>
</test>

What I'd like to get is

<?xml version="1.0" encoding="UTF-8" standalone="no"?><test xmlns:test="urn:mynamespace">
   <value test:id="1">42.42</value>
   <value2 test:id="2">Hello Namespace!</value2>
</test>

which is much more convenient when later editing by hand.

I know it's possible, because this is what I get when I load a document that contains

<test xmlns:test="urn:mynamespace">
</test>

and add the remaining nodes.

So I think the questions boils down to: How do I add xmlns:test="urn:mynamespace" to the root node? When I just try to add the attribute, I get a NAMESPACE_ERR exception (I use namespace-aware factory, etc). because I try to mess with namespaces bypassing the API that I just can't find...

Note: there is no attribute using the namespace in the root element (when I allow that, I can get it to work), but just the namespace declaration.

jasso
  • 13,736
  • 2
  • 36
  • 50

1 Answers1

0

With this XSLT document

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

<xsl:output indent="yes" standalone="no" encoding="UTF-8"/>

<!-- Copies root element and its contents -->
<xsl:template match="/*" priority="2">
    <xsl:element name="{name()}" namespace="{namespace-uri()}">
        <xsl:copy-of select="namespace::*"/>
        <xsl:copy-of select="document('')/*/namespace::*[name()='test']"/>
        <xsl:copy-of select="@*"/>
        <xsl:copy-of select="*"/>
    </xsl:element>
</xsl:template>

<!-- Copies comments, processing instructions etc. outside
     the root element. This is not neccesarily needed. -->
<xsl:template match="/node()">
    <xsl:copy-of select="."/>
</xsl:template>

</xsl:stylesheet>

given this input (your code example)

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<test>
   <value xmlns:test="urn:mynamespace" test:id="1">42.42</value>
   <value2 xmlns:test="urn:mynamespace" test:id="2">Hello Namespace!</value2>
</test>

results in this desired output

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<test xmlns:test="urn:mynamespace">
  <value test:id="1">42.42</value>
  <value2 test:id="2">Hello Namespace!</value2>
</test>

You can perform XSLT transformations in Java with Transformer class.

javax.xml.transform.Source xsltSource = new javax.xml.transform.stream.StreamSource(xsltFile);
Transformer transformer = TransformerFactory.newInstance().newTransformer(xsltSource);

where xsltFile is a File object pointing to that XSLT file.

jasso
  • 13,736
  • 2
  • 36
  • 50