69

I have an XML document with a default namespace indicated at the root. Something like this:

<MyRoot xmlns="http://www.mysite.com">
   <MyChild1>
       <MyData>1234</MyData> 
   </MyChild1> 
</MyRoot>

The XSLT to parse the XML does not work as expected because of the default namespace, i.e. when I remove the namespace, everything works as expected.

Here is my XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:template match="/" >
  <soap:Envelope xsl:version="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
     <NewRoot xmlns="http://wherever.com">
       <NewChild>
         <ChildID>ABCD</ChildID>
         <ChildData>
            <xsl:value-of select="/MyRoot/MyChild1/MyData"/>
         </ChildData>
       </NewChild>
     </NewRoot>
   </soap:Body>
  </soap:Envelope>
 </xsl:template>
</xsl:stylesheet>

What needs to be done with XSLT document so that translation works properly? What exactly needs to be done in XSLT document?

Larry
  • 989
  • 4
  • 12
  • 25

3 Answers3

77

You need to declare the namespace in your XSLT, and use it in XPath expressions. E.g.:

<xsl:stylesheet ... xmlns:my="http://www.mysite.com">

   <xsl:template match="/my:MyRoot"> ... </xsl:template>

</xsl:stylesheet>

Note that you must provide some prefix if you want to refer to elements from that namespace in XPath. While you can just do xmlns="..." without the prefix, and it will work for literal result elements, it won't work for XPath - in XPath, an unprefixed name is always considered to be in namespace with blank URI, regardless of any xmlns="..." in scope.

Pavel Minaev
  • 99,783
  • 25
  • 219
  • 289
  • Thanks for answer. It is similar to what I have found in internet, but it does not work. My XML output still does not work as expected. If I remove the default namespace from source XML then output XML looks fine. My appl'n that does the XSLT translation is a .NET 2.0 application, if that makes a difference. – Larry Aug 27 '09 at 23:09
  • 1
    Please show your XLST that doesn't work, then. It's hard to say anything more definite without seeing it. What you describe still sounds like you missed the namespace qualifier _somwhere_. For example, keep in mind that you have to repeat it for every XPath step - i.e. `/my:MyRoot/my:foo/my:bar`. – Pavel Minaev Aug 27 '09 at 23:22
  • 1
    Really useful note about needing a prefix. This triggered me to check the specs. It looks like, XPath would respect a default namepace if one were present, but XSLT explicitly excludes the default namespace from being in scope http://www.w3.org/TR/xslt#section-Expressions – Dominic Cronin Sep 01 '14 at 15:23
  • @PavelMinaev: I used `/my:MyRoot` in my xPath so my template match looks like this: `` - so what is the *MyRoot* - is that a reserved name in XSLT? – Our Man in Bananas Sep 02 '14 at 14:27
  • No, it's just an element name. You should use whatever is the name of the outermost element for your XML there. – Pavel Minaev Sep 04 '14 at 17:09
38

If you use XSLT 2.0, specify xpath-default-namespace="http://www.example.com" in the stylesheet section.

Daniel Haley
  • 51,389
  • 6
  • 69
  • 95
vinh
  • 381
  • 3
  • 2
4

If this was kind of name space problem, there is room to try to modify two things in the xslt file:

  • add "my" name space definition in xsl:stylesheet tag
  • use "my:" prefix when call elements in traversing the xml file.

result

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:my="http://www.w3.org/2001/XMLSchema">
    <xsl:template match="/" >
        <soap:Envelope xsl:version="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
            <soap:Body>
                <NewRoot xmlns="http://wherever.com">
                    <NewChild>
                        <ChildID>ABCD</ChildID>
                        <ChildData>
                            <xsl:value-of select="/my:MyRoot/my:MyChild1/my:MyData"/>
                        </ChildData>
                    </NewChild>
                </NewRoot>
            </soap:Body>
        </soap:Envelope>
    </xsl:template>
</xsl:stylesheet>
potame
  • 7,597
  • 4
  • 26
  • 33
hama4g
  • 41
  • 1