0

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)
6
  • 1. How important is to parametrize the namespaces? Couldn't they be hard-coded in the XSLT stylesheet? -- 2. Does your processor support XSLT 2.0? Commented May 30, 2019 at 19:44
  • 1. It is importat but for now as a quick solution I think I would appreciate hardcoded version in xslt 2. Yes Im using Saxon 9 Commented May 30, 2019 at 19:47
  • Do note that your input is not well-formed XML, because the prefix reis not bound to a namespace. Commented May 30, 2019 at 19:51
  • I did correct that. My bad. Commented May 30, 2019 at 19:54
  • It is easy to match and change nodes in a certain namespace. Doing the same with element or attribute value would require the use of schema-aware XSLT. Or how do you expect the XSLT processor to know that the namespace attribute contains a namespace to change? Do you know the structure of the input XML, the possible attributes to change? Commented May 30, 2019 at 20:05

1 Answer 1

1

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).

Sign up to request clarification or add additional context in comments.

5 Comments

namespace-uri()='$old-namespace' should be namespace-uri()=$old-namespace. And the select="{.}" simply select=".".
Thank you. It looks fine and simple but when running with saxon xsl deletes all tags in output xml document. I use it like this: gist.github.com/Tomasz9248/7e31d5f0c2d800e5dc558797d944f3ae
@Tomasz, you will need to use the identity transformation as a starting point e.g. by declaring <xsl:mode on-no-match="shallow-copy"/> in XSLT 3 or by including the template <xsl:template match="@* | node()"><xsl:copy><xsl:apply-templates select="@* | node()"/></xsl:copy></xsl:template> in XSLT 2 or 1.
I did but still cant change namespace uri in root element.
Then you need to tell us exactly what you are doing and exactly how it is failing. Probably best to start a new question.

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.