Reputation: 23
I would like to change namespace in XML file with XSLT based only on namespace-uri without knowing what prefix this namespace has defined. Is it possible?
I get some solution but they work only with small files when I know the input and can setup xsl file kinda manualy.
What I would like to achieve:
INPUT XML:
<?xml version="1.0" encoding="UTF-8"?>
<re:rootElement xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:re="http://something.com/root"
xmlns:ns1="http://something.com/some/schema"
xmlns:cs2="http://something.com/another/schema"
xmlns:ns3="http://something.com/different/schema"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<xsd:import namespace="http://something.com/another/schema" schemaLocation="/schema/location"/>
(multiple nodes below)
XSLT that takes 2 parameters:
<xsl:param name="old_namespace" select="'http://something.com/another/schema'"/>
<xsl:param name="new_namespace" select="'http://something.com/another/schemaNEW'"/>
And output as xml:
<re:rootElement xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:re="http://something.com/root"
xmlns:ns1="http://something.com/some/schema"
xmlns:cs2="http://something.com/another/schemaNEW"
xmlns:ns3="http://something.com/different/schema"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<xsd:import namespace="http://something.com/another/schemaNEW" schemaLocation="/schema/location"/>
(multiple nodes below)
Upvotes: 0
Views: 626
Reputation: 163615
It's not difficult to change the namespace URI used in namespace nodes and in the names of elements and attributes. In a schema-aware stylesheet, it's also possible (but perhaps harder) to change the namespace URI used in values of type QName. It's rather harder, I suspect, to change namespace URIs that appear:
directly in attributes such as xsi:schemaLocation or xs:import (unless you enumerate such attributes)
in the names of NOTATIONs
in content with a micro-syntax, e.g. consider
<xsl:if test="namespace-uri() = 'http://old-namespace.com/'>
If it's just namespaces used in element and attributes that you're after, then you can use
<xsl:template match="*[namespace-uri()=$old-namespace]">
<xsl:element name="{name()}" namespace="{$new-namespace}">
<xsl:apply-templates select="@*, node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="@*[namespace-uri()='$old-namespace']">
<xsl:attribute name="{name()}" namespace="{$new-namespace}" select="."/>
</xsl:template>
along with the identity template (or in 3.0, <xsl:mode on-no-match="shallow-copy"/>
) to make sure that other elements and attributes are copied unchanged.
(This is XSLT 2.0 but could easily be rewritten in 1.0).
Upvotes: 1