views:

75

answers:

3
+3  Q: 

XSL and Namespaces

This may be a really simple question, but its one I can't seem to get and am tearing my hair out over. I have the following XML:

<?xml-stylesheet type="text/xsl" href="email.xsl"?>
<Example xmlns="">
  <Name xmlns="urn:rnb.fulfilment.bus.contracts.public.exampleBookName.v1">Mark</Name>
</Example>

And am trying to use the following XSLT:

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
   <xsl:template match="/">
    <html>
      <body>
        <table width="90%" border="0" cellpadding="0" cellspacing="0">
          <tr>
            <td>
              <p>AUTOMATED CONFIRMATION: This confirmation email is unable to take replies. For further assistance please visit our Help pages or Contact us</p>
              <p>Dear <xsl:value-of select="Name"/>,</p>
              <p>Thank you for blah blah... </p>
            </td>
          </tr>
        </table>
        <xsl:apply-templates/>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

I cannot get the Name to appear when I am using the xmlns=urn:rnb.fulfilment.bus.contracts.public.exampleBookName.v1 in the XML feed, when I remove the xmlns, the name displays fine.

Is there some syntax I'm missing? I've tried adding the namespace to the <xsl:stylesheet> element:

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:rpg="urn:rnb.fulfilment.bus.contracts.public.exampleBookName.v1"
>

Then using the prefix I gave to the XSLT in the XPath expression:

<xsl:value-of select="Name"/>

But this doesn't work either. Can anyone help? Thanks in advance.

+4  A: 

You need to use the same namespace in the XSLT so that the XPath expression for Name matches.

<xsl:value-of select="x:Name" xmlns:x="urn:rnb.fulfilment.bus.contracts.public.exampleBookName.v1"/>
Lucero
It's unfortunate that so few of the XSL tutorial examples include namespaces, this is a common confusion. If there's a namespace associated with an element, as far as XSL is concerned its name is a qualified name (http://en.wikipedia.org/wiki/QName), not the simple name.
Jeffrey Harris
This is not the best method to do it, because declaring namespaces at the `xsl:value-of` bloats the XSL code unnecessarily. Declaring them at the document level is the way to go.
Tomalak
@Tomalak, it depends in which scope the namespace is used. If it is used only on this element, using it like this makes it clear what namespace the prefix represents. Of course, if the namespace was to be used in several places, I'd also move it to the document.
Lucero
+5  A: 

Your approach with declaring the namespace at <xsl:stylesheet> was the right direction already. Now all you got to do is use the prefix also:

<xsl:value-of select="Example/rpg:Name" />

I further recommend a tiny change to your template to better reflect your input:

<xsl:template match="Example">
  <!-- ... -->
  <xsl:value-of select="rpg:Name" />
</xsl:template>
Tomalak
A: 

Alternatively use a predicate and local-name(). E.g.:

<xsl:value-of select="*[local-name() = 'Name']"/>
That's a bad idea, because it is not only inefficient (slow because of string compare) but also doesn't take into account namespaces, which it really should do.
Lucero
... If namespaces are relevant (if different behaviour is desired for different namespaces). If the XSL is just formatting contents of raw XML you are interested in then the namespace is not so relevant, and can be ignored. In the OP example, the namespace is *not* intended to be preserved in output XML only the text content of the element is.I am not sure on the performance concern. Remember that as per the XPath function definitions "*[name() = name]" is equivalent to "name"; and anyway a compiler is free to `rewrite' XPath expressions to equivalent ones for the purpose of optimizing.
+1 This is not a bad or wrong answer that deserves a negative score. It has some implications, but they were named. The performance argument strongly depends on how many children the current node has and how well the XSLT processor optimizes. The namespace argument strongly depends on whether you care or not. ;)
Tomalak
Thanks everyone for all of your help. I was just being dumb and didn't use the alias.Thanks again!
iali