Default namespaces (again - this time in XSLT and XPath)
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">
<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>
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.