Skip to content. | Skip to navigation

Personal tools

Navigation

You are here: Home / weblog / Default namespaces (again - this time in XSLT and XPath)

Default namespaces (again - this time in XSLT and XPath)

Posted by Dominic Cronin at Sep 07, 2014 02:22 PM |
Filed under: , ,

For a long time, the default XSLT for a Rich Text Format area (RTF) in Tridion began with a fairly standard namespace declaration, like this:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
It's very normal to begin an XSLT this way: the XSLT elements are in the namespace referenced by the "xsl" prefix, and you're free to use the default namespace for output that you want to define. In an RTF XSLT, you'll generally want to be outputting HTML elements without a namespace. (Often these HTML fragments will be embedded in a document that gives them a namespace, but that's another story.) Indeed, the document you are transforming will also be without a namespace. (The native storage of an RTF is in the XHTML namespace, but that's removed before the XSLT is invoked.)
So normally, you can write templates with match rules that simply address an HTML element by name - for example:
<xsl:template match="b">
   <strong>
     <xsl:apply-templates/>
  </strong>
</xsl:template>

I've just checked on my Tridion 2013 system, and the default RTF XSLT is done in this style, but I've seen examples in the field that use a rather different, and perhaps bizarre style to achieve the same thing. (I have a suspicion that there was a version of Tridion that used this style, or maybe it was something to do with an upgrade that converted to it, but I have no direct evidence. Maybe there's another explanation as to why we see this in the field.)

This other style I'm referring to looks quite different. It starts with a namepace declaration like this:

<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0"> 

As you see, the XSLT namespace is used as the default, enabling the template code to be slightly terser. The same template would look like this:

<template match="b">
   <strong xmlns="">
     <xsl:apply-templates/>
  </strong>
</template>

When I first saw this kind of code I was almost pulling my hair out. I actually had to manually execute a test XSLT to prove to myself that it would actually work. And it does.

What was upsetting me? Well was convinced that the match should fail. I mean surely, you'd have to do something like:

<template match="empty:b" xmlns:empty="">
   <strong xmlns="">
     <xsl:apply-templates/>
  </strong>
</template>
See what I mean? That b shouldn't match.... right?
Well anyway - it turns out I was wrong. XSLT has explicit provision for this case. Looking at the recommendation for XSLT, we see this:

the set of namespace declarations are those in scope on the element which has the attribute in which the expression occurs; this includes the implicit declaration of the prefix xml required by the the XML Namespaces Recommendation [XML Names]; the default namespace (as declared by xmlns) is not part of this set

So XSLT doesn't let the XPath see the default namespace, but it wouldn't matter, because XPath would ignore it: From the XPath recommendation:

A QName in the node test is expanded into an expanded-name using the namespace declarations from the expression context. This is the same way expansion is done for element type names in start and end-tags except that the default namespace declared with xmlns is not used: if the QName does not have a prefix, then the namespace URI is null (this is the same way attribute names are expanded).

So in an XSLT, the normal namespace weirdness that we're used to for attributes applies to elements as well.

Well, that explains that then. I think I'll be sticking to the more conventional approach though.

Filed under: , ,