0

I have the below xml, would like to replace the namespace "http://tester.com" with "http://tester.com/v2", within the input xml. I have referred the solution here by Dimitre, able to come up with one xslt(1.0). It is replacing the namespace for all the elements, however attributes are not. How do i modify this so that the replacement applies even for the attributes as well?

input xml

<a:Root xmlns:a="http://tester.com">
    <a:we>er</a:we>
    <a:ty a:yu="samp">gh</a:ty>
</a:Root>

desired output

<a:Root xmlns:a="http://tester.com/v2">
    <a:we>er</a:we>
    <a:ty a:yu="samp">gh</a:ty>
</a:Root>

xslt tried

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

 <xsl:param name="pTarget" select="'http://tester.com'"/>
 <xsl:param name="pRepl" select="'http://tester.com/v2'"/>

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

 <xsl:template match=
  "*[namespace-uri()='http://tester.com'
   or
     namespace::*[.='http://tester.com']
    ]">

  <xsl:variable name="vNS" select="namespace-uri()"/>

  <xsl:variable name="vNewNS">
    <xsl:choose>
      <xsl:when test="not($vNS=$pTarget)">
        <xsl:value-of select="$vNS"/>
      </xsl:when>
      <xsl:otherwise>

        <xsl:value-of select="$pRepl"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <xsl:element name="{name()}" namespace="{$vNewNS}">
   <xsl:copy-of select=
     "namespace::*
        [not(. = $vNS
            or
             .='http://tester.com'
             )
        ]"/>

   <xsl:for-each select=
     "namespace::*
        [.='http://tester.com'
        ]">
     <xsl:variable name="vNewNSUri" select=
     "$pRepl
     "/>

     <xsl:variable name="vPrefix" select="name()"/>

     <xsl:variable name="vPref">
       <xsl:if test="$vPrefix">
         <xsl:value-of select="concat($vPrefix, ':')"/>
       </xsl:if>
     </xsl:variable>

     <xsl:variable name="vrtfDoc">
      <xsl:element name="{$vPref}dummy"
                   namespace="{$vNewNSUri}"/>
     </xsl:variable>

     <xsl:copy-of select=
     "ext:node-set($vrtfDoc)/*/namespace::*[. = $vNewNSUri]"/>
   </xsl:for-each>

   <xsl:apply-templates select="node()|@*"/>
  </xsl:element>
 </xsl:template>
</xsl:stylesheet>
Community
  • 1
  • 1
Suresh
  • 1,081
  • 4
  • 21
  • 44
  • Please note that the the solution i am looking for is just the replacement of the namespace. The prefix(or no prefix) in the input should be same in the output. – Suresh Oct 24 '13 at 09:40

1 Answers1

0

You want something like this:

<xsl:template match="a:*">
  <xsl:element name="a:{local-name()}" namespace="{$newNamespace}"/>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:element>
</xsl:template>

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

plus an identity template for elements/attributes not in this namespace.

Michael Kay
  • 156,231
  • 11
  • 92
  • 164
  • Thanks Michael. Here always the output will have "a" as prefix. I want that to be unchanged from the input. In my xslt, it replaces the namespace for the elements(even it keeps the namespace prefix, same as input). However it is not happening for attributes – Suresh Oct 24 '13 at 14:14
  • I don't know why it's not working for you. Need to see full input, output, and stylesheet. – Michael Kay Oct 24 '13 at 20:25
  • Micheal. It threw an error for me at template match="a:@*">, javax.xml.transform.TransformerException: A node test that matches either NCName:* or QName was expected. – Suresh Oct 25 '13 at 10:31
  • Sorry about the typo, now fixed. Should be `@a:*` – Michael Kay Oct 25 '13 at 11:48