tags:

views:

71

answers:

2

Hi all:

I have the following in my XSL which adds a xmlns to my XML.

<xsl:template match="root">
    <xsl:element name="root" namespace="myXslLoc">
        <xsl:attribute name="Name">Default</xsl:attribute>
        <xsl:apply-templates/>
    </xsl:element>
<xsl:template>

The above does add a xmlns attribute to the root element (the top level element). However it also added a xmlns to the subsequent element. This is how it turned out:

<root Name="Default" xmlns="myXslLoc">
    <steps xmlns="">  <-- where did this attribute come from?
    .
    .
    .
    </steps>
</root>

I have no ideas where that xmlns in the steps element come from. I have no code that specifies the adding of the xmlns to the steps element. Below is a snipet of my xsd:

<xs:complexType name="root">
    <xs:sequence>
        <xs:element name="steps" type="steps" maxOccurs="1" MinOccurs="1"/>
    </xs:sequence>
    <xs:attribute name="Name" type="xs:string" use="required"/>
</xs:complexType>

<xs:complexType name="steps">
    <xs:sequence>
        <xs:element name="step" type="step" maxOccurs="unbounded"/>
    </xs:sequence>
</xs:complexType>

Is there something wrong in my xsl or xsd? I can not seem to figure out where the problem came from.

Thanks.

EDIT: Following Dimitre's transformation code, I have managed to insert the namespace attribute into the root element. However, more instances of namespace attribute appeared further down in the transformed xml document.

The below is what happened:

<root Name="Default" xmlns="myXslLoc">
    <steps>  <-- where did this attribute come from?
        <step name="A">
        .
        </step>
        .
        .
        <!-- the below is the final steps element -->
        <step name="Z" xmlns="">  <-- this xmlns was unexpectedly added.
            <steps xmlns="myXslLoc"> <-- this one as well.
            .
            .
            .
            </steps>
        </step>
        <step Name="Step manually added by identity transformation (addLastNode stuff)">
        .
        .
        .
        </step>
    </steps>
</root>

The xsl looks something like this:

<xsl:template match="root">
    <xsl:element name="root namespace="myXslLoc">
        <xsl:attribute name="Name">Default</xsl:attribute>
        <xsl:apply-templates/>
    </xsl:element>
<xsl:template>

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

<xsl:param name="addMyXslLoc" select="'myXslLoc'"/>

<xsl:template match="/*/steps/step[position()=last()]">
    <xsl:call-template name="identity"/>
    <xsl:copy-of select="$addLastNodes"/>
</xsl:template>

<xsl:param name="addLastNodes">
    <step Name="Total Cost">
        <items>
            <item name="A">
            </item>
            <item name="b">
            </item>
        </items>
    </step>
</xsl:param>

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

I liked how the namespace now appears on the root element (along with the Name attribute). But I now face the problem of unable to get rid of the namespaces which was inserted into the last element of the xml document excluding the one that is added via the transformation.

EDIT: Updated the addLastNodes xsl.

+1  A: 

There is nothing wrong with the XSL template; it's just not doing what you want it to do.

What it is doing is creating an element 'root' in the myXslLoc namespace, and then (in the apply-template step) copying the children of the context node (root, in NoNameSpace), in their (the children's) namespace, which is NoNameSpace; so your result is the parent node {myXslLoc}root node, with children {}steps

If what you want is for the steps elements to also be in the myXslLoc root, you need to explicitly create {myXslLoc}steps nodes using xsl:element; just as you did for the 'root' template.

Vincent Marchetti
+1  A: 

@Vincent-Marchetti has already explained what is causing the problem. Here is a complete solution.

This transformation:

<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="pNamespace" select="'myXslLoc'"/>

  <xsl:param name="addLastNodes">
    <step Name="Total Cost">
        <items>
            <item name="A">
            </item>
            <item name="b">
            </item>
        </items>
    </step>
 </xsl:param>


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

  <xsl:template match="/*/steps/step[position()=last()]">
    <xsl:call-template name="repNamespace"/>
    <xsl:apply-templates select="ext:node-set($addLastNodes)/*"/>
 </xsl:template>

 <xsl:template match="*" name="repNamespace">
  <xsl:element name="{name()}" namespace="{$pNamespace}">
    <xsl:copy-of select="namespace::*"/>
    <xsl:apply-templates select="node()|@*"/>
  </xsl:element>
 </xsl:template>
</xsl:stylesheet>

when applied on this XML document:

<root>
 <steps>
  <step>1</step>
  <step>2</step>
  <step>3</step>
 </steps>
</root>

produces the wanted, correct result:

<root xmlns="myXslLoc">
   <steps>
      <step>1</step>
      <step>2</step>
      <step>3</step>
      <step Name="Total Cost">
         <items>
            <item name="A"/>
            <item name="b"/>
         </items>
      </step>
   </steps>
</root>
Dimitre Novatchev
@Dimitre: your solution did add the namespace to the root element. However it also added the namespaces into one of the steps and step elements within the root element (I believe it is the final step before the customly-inserted step from my previous post). Is there anyway to fix this? (Also, I have added a Name attribute to the root element using <xsl:attribute name="Name">blah</xsl:attribute> in a separate xsl:template). Thanks.
BeraCim
@BeraCim: Yes. This solves exactly the problem you were complaining from: the appearance of `xmlns=""`. Didn't you want exactly this to disappear?. If not, please edit your question and state what is a short instance of the schema -- give the exact XML, and what is the exact output you want from the transformation.
Dimitre Novatchev
@BeraCim: I see that you added an XML document to your answer, but only *partial* xslt code. In particular, I want to see the full content of the `addLastNodes` parameter. It is there, where changes are needed.
Dimitre Novatchev
@Dimitre: added as requested. TIA.
BeraCim
@BeraCim: I have edited my solution accordingly and now it works as per your latest specifications. Please, have a look at it again. :)
Dimitre Novatchev