3

I am new to XSLT transformation. I have namepace mapping issue in my output xml.

The input XML is

<m:class xmlns:m="http://www.NotRequirednamespace.com">
         <queryDetails>hello</queryDetails>
</m:class>

My XSLT is look like

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xpath-default-namespace="http://www.neededNamespace.com" xmlns:t="http://www.NotRequirednamespace.com" exclude-result-prefixes="t">

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

    <!-- Stylesheet to remove all namespaces from a document -->
    <!-- NOTE: this will lead to attribute name clash, if an element contains
        two attributes with same local name but different namespace prefix -->
    <!-- Nodes that cannot have a namespace are copied as such -->

<xsl:template match="/">
<school xmlns="http://www.neededNamespace.com">
<xsl:apply-templates/>
</school>
</xsl:template>

    <!-- template to copy elements -->
    <xsl:template match="*">
        <xsl:element name="{local-name()}">
            <xsl:apply-templates select="@* | node()"/>
        </xsl:element>
    </xsl:template>

    <!-- template to copy attributes -->
    <xsl:template match="@*">
        <xsl:attribute name="{local-name()}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>

    <!-- template to copy the rest of the nodes -->
    <xsl:template match="comment() | text() | processing-instruction()">
        <xsl:copy/>
    </xsl:template>

</xsl:stylesheet>

The output XML is

<school xmlns="http://www.neededNamespace.com">
<class xmlns="">
<queryDetails>hello</queryDetails>
</class>
</school>

But I dont want the name default namespace (xmlns="") in the element class. I like to specify the default namespace for the class element as "http://www.neededNamespace.com". So that I need the output xml as follows.

<school xmlns="http://www.neededNamespace.com">
<class>
<queryDetails>hello</queryDetails>
</class>
</school>

I have tried all the options i know. Can you help in this. Thanks in advance.

Simbu
  • 766
  • 1
  • 12
  • 37

2 Answers2

3

Do you really need all that code? Or are you just using this as an incantation, in the hope it will somehow appease the evil spirits? Like what does xpath-default-namespace do in an XSLT 1.0 stylesheet? (Answer: either nothing, or produce a fatal error - depending on how tolerant your processor is).

Now, if your XML example is representative, then all you need to do is:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.neededNamespace.com">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/">
    <school>
        <xsl:apply-templates/>
    </school>
</xsl:template>

<xsl:template match="*">
    <xsl:element name="{local-name()}">
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

What this does is:

  1. Create a new root element named <school>;
  2. Create a new element for each existing element, and name it with the local name of the existing element.

Since the stylesheet contains a declaration of a default namespace, ALL newly created elements (in both #1 and #2 above) will be placed in that namespace.

Since your input does not include any attributes, that should be all the code that's required.

In case you worry they may add some attributes in the future that you wish to pass to the output, just change the second template to:

<xsl:template match="*">
    <xsl:element name="{local-name()}">
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

This assumes the attributes will be in no namespace - and that's a very reasonable assumption. Attributes do not inherit their parent's namespace, and very rarely do you see authors place attributes in namespaces explicitly. Only if you really need to anticipate such possibility do you need additional code to handle the attributes.

michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
1

So you don't want to remove the namespace of the "class" element, you want to change it. Use the "namespace" attribute of the xsl:element node.

Instead of

<xsl:element name="{local-name()}">

you want

<xsl:element name="{local-name()}" namespace="http://www.neededNamespace.com">
bjimba
  • 928
  • 8
  • 13
  • Thanks bjimba for your valuable inputs. After including the namespace value as you have mentioned. I got below sort of outputs which is not expected. ` ` Note I have few more tags and elements between school and class with some other namespace. – Simbu Feb 24 '15 at 22:19
  • I don't know why that would not be expected. They are in the right namespace now. Depending on your XSL processor, it might be more verbose in saying so than you might like. You should pay close attention to Michael's answer here, which goes into much more detail than my quick pointer toward the namespace attribute of the xsl:element. And it really pays to spend the time to understand XML namespaces with a good website (or even a book). – bjimba Feb 26 '15 at 05:08