Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rename an element with xslt

I have this xml:

<pos:getPositionRouter xmlns:pos="positionNS">
   <positionID>
      <code>1</code>
   </positionID>
   <parameter>?</parameter>
</pos:getPositionRouter>

and I want to rename the element pos:getPositionRouter to x:getPosition using xslt:

<x:getPosition xmlns:x="newPositionNS">
   <positionID>
      <code>1</code>
   </positionID>
   <parameter>?</parameter>
</x:getPosition>

This is the sylesheet I came up with:

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

 <xsl:output method="xml" omit-xml-declaration="yes" indent="yes" />

 <xsl:param name="old_namespace" />
 <xsl:param name="old_element_localname" />
 <xsl:param name="new_namespace" />
 <xsl:param name="new_element_localname" />


 <xsl:template match="@*|node()">
  <xsl:choose>
   <xsl:when test="(local-name() = $old_element_localname) and (namespace-uri() = $old_namespace)">
    <xsl:element name="{$new_element_localname}" namespace="{$new_namespace}">
     <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
   </xsl:when>

   <!-- copy the rest as is -->
   <xsl:otherwise>
    <xsl:copy>
     <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
   </xsl:otherwise>
  </xsl:choose>
 </xsl:template>

</xsl:stylesheet> 

I am forced to use xalan as xslt processor, and the output, unfortunately is this:

<getPosition xmlns="newPositionNS">
   <positionID xmlns:pos="positionNS">
      <code>1</code>
   </positionID>
   <parameter xmlns:pos="positionNS">?</parameter>
</getPosition>

The default namespace of the getPosition element becomes the new namespace, but the child elements should remain without namespace (xmlns="").

Can someone understand why?

Thank you!

like image 200
Simon Avatar asked Dec 09 '25 08:12

Simon


1 Answers

This stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="old_namespace" select="'positionNS'"/>
    <xsl:param name="old_element_localname" select="'getPositionRouter'"/>
    <xsl:param name="new_namespace_prefix" select="'x'"/>
    <xsl:param name="new_namespace" select="'newPositionNS'"/>
    <xsl:param name="new_element_localname" select="'getPosition'" />
    <xsl:template match="*">
        <xsl:choose>
            <xsl:when test="local-name()=$old_element_localname and
                            namespace-uri()=$old_namespace">
                <xsl:element
                     name="{substring(concat($new_namespace_prefix,':'),
                                      1 div boolean($new_namespace_prefix))}{
                            $new_element_localname}"
                     namespace="{$new_namespace}">
                    <xsl:apply-templates select="@*|node()"/>
                </xsl:element>
            </xsl:when>
            <xsl:otherwise>
                <xsl:element name="{name()}">
                    <xsl:apply-templates select="@*|node()"/>
                </xsl:element>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    <xsl:template match="@*">
        <xsl:attribute name="{name()}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

Output:

<x:getPosition xmlns:x="newPositionNS">
    <positionID>
        <code>1</code>
    </positionID>
    <parameter>?</parameter>
</x:getPosition>

Note: If you want an specific prefix you should add it to the QName. If you want to remove in-scope namespace you shouldn't use xsl:copy in XSLT 1.0


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!