How can I, given a w3c DOM (Java's default implementation, specifically) change the namespace of every element/attribute/node in that DOM? Efficiently, preferably.
I don't think there is an efficient solution that is also robust. You can't just rename something on the root element. Consider these documents:
Doc1
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="urn:all" xmlns:f="urn:fleet" xmlns:m="urn:mission">
<f:starfleet>
<m:bold>
<f:ship name="Enterprise" />
</m:bold>
</f:starfleet>
</root>
Doc2
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="urn:all">
<starfleet xmlns="urn:fleet">
<bold xmlns="urn:mission">
<ship xmlns="urn:fleet" name="Enterprise" />
</bold>
</starfleet>
</root>
Doc3
<?xml version="1.0" encoding="UTF-8"?>
<r:root xmlns:r="urn:all">
<r:starfleet xmlns:r="urn:fleet">
<r:bold xmlns:r="urn:mission">
<r:ship xmlns:r="urn:fleet" name="Enterprise" />
</r:bold>
</r:starfleet>
</r:root>
These three documents are equivalent in a namespace-aware DOM. You could run the same namespaced XPath queries against any of them.
Since the DOM allows you to specify exactly how nodes should be namespaced, there is no catch-all, one-step call to change a namespace. You need to walk the DOM, taking into consideration not only prefix and URI values, but their scope at any given time.
This XSLT can be used with a Transformer to change elements namespaced as urn:fleet
to be namespaced as urn:new
:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="urn:fleet" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="f:*">
<xsl:variable name="var.foo" select="local-name()" />
<xsl:element namespace="urn:new" name="{$var.foo}">
<xsl:copy-of select="@*" />
<xsl:apply-templates />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Caveats: further tweaking would be required to handle namespaced attributes; dangling urn:fleet
declarations can be left behind, which is messy, but largely inconsequential; probably other stuff I haven't thought of.