5

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.

0

2 Answers 2

4

@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>
Sign up to request clarification or add additional context in comments.

7 Comments

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: 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.
@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.
@BeraCim: I have edited my solution accordingly and now it works as per your latest specifications. Please, have a look at it again. :)
I dont's see the parameter pNamespace used anywhere in the xslt , how do I add it as xmlns attribute of the root node of the resulting XML ?
|
3

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.