bernie2436
bernie2436

Reputation: 23941

get rid of old namespace with xslt

I am am new to xslt. I am trying to convert XML from one schema into another schema. I want to "get rid" of the old namespace after the transform. How can I erase the old schema after the transform if I need it for the transform itself. Essentially, I want http://positionskillmanagementservice.webservices.com to go away and be replaced entirely by http://newschema (after I re-name the nodes). I am able to do most of what I want via Dimitre Novatchev's method from: change the namespace of an element with xslt

This is the XML:

<ns:positionSkillResponse xmlns:ns="http://positionskillmanagementservice.webservices.com">
<ns:return>1</ns:return>
<ns:return>9</ns:return>
</ns:positionSkillResponse>

This is the xslt:

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

  <xsl:output method="xml" />

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

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

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

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

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

I am checking the work with this tool.

Upvotes: 0

Views: 147

Answers (2)

Michael Kay
Michael Kay

Reputation: 163645

Tomalak has shown you a better way to write your transformation, but hasn't really answered your immediate question. When you use literal result elements in your stylesheets, for example <a>...</a>, they are copied to the output together with all the namespaces that are in scope for that element in the stylesheet, with a few exceptions. One of the exceptions is that namespaces are omitted if they are listed in the exclude-result-prefixes element, which is usually placed on the xsl:stylesheet element along with the namespace declaration. So if you weren't refactoring the stylesheet as Tomalak suggests, you could have dropped the namespace by adding exclude-result-prefixes="ns" to the xsl:stylesheet element.

Upvotes: 2

Tomalak
Tomalak

Reputation: 338406

Your attempt is way too specific. Try this more general one:

<xsl:stylesheet 
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ns_old="http://positionskillmanagementservice.webservices.com"
>    
    <xsl:output method="xml" />

    <!-- matches any node not handled elsewhere -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>    

    <!-- matches elements in the old namespace, re-creates them in the new -->
    <xsl:template match="ns_old:*">
        <xsl:element name="ns:{local-name()}" namespace="http://newschema">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>

    <!-- if you don't have namespaced attributes you won't need this template -->
    <xsl:template match="@ns_old:*">
        <xsl:attribute name="ns:{local-name()}" namespace="http://newschema">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

which delivers:

<ns:positionSkillResponse xmlns:ns="http://newschema">
    <ns:return>1</ns:return>
    <ns:return>9</ns:return>
</ns:positionSkillResponse>

Notes

  • You don't need to declare xmlns:ns="http://newschema" in the XSLT because you don't actually have nodes from that namespace in your input document.
  • This also means you could declare the old namespace as xmlns:ns="http://positionskillmanagementservice.webservices.com" and use it like <xsl:template match="ns:*">. It's all the same to the XSL processor, but it's probably less confusing to the human reader if a different prefix like ns_old is used.
  • You can choose your output prefix arbitrarily (<xsl:element name="ns:{local-name()}" ...). This has nothing to do with declared namespaces in the XSLT. Using no prefix at all would result in a document with a default namespace:

    <positionSkillResponse xmlns="http://newschema">
        <return>1</return>
        <return>9</return>
    </positionSkillResponse>
    

Upvotes: 1

Related Questions