Re: [xsl] Creating an attribute name of xmlns:xyz

Subject: Re: [xsl] Creating an attribute name of xmlns:xyz
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Tue, 13 Feb 2001 12:49:43 +0000
Hi Gilles,

> I an writing an xsl file which creates another xsl file. It works fine
> except I need teh original xsl file to create the following statement:
>     <stylesheet xmlns="";
> xmlns:xfa=""; version="1.0">
> To do so, the following xsl statements are used:
>   <element name="stylesheet">
>     <attribute name="xmlns"></attribute>
>     <attribute name="xmlns:xfa" 
>                    namespace="";>
>     </attribute>
>     <attribute name="version">1.0</attribute>
>   ...
>   </element>

Namespace declarations (which are what the xmlns:... attributes are)
aren't treated as attributes in XSLT.  The purpose of a namespace
declaration is to associate a particular prefix (e.g. 'xfa') with a
particular namespace URI (e.g. in a particular document.

Within a node tree, there are no namespace declarations. Instead,
every element within the scope of a namespace declaration has a
namespace *node* on it, representing the mapping between the prefix
and the namespace URI.

XSLT works on these namespace nodes - the namespace declarations
themselves don't exist in a node tree. This works on the source XML
(you can't select a namespace declaration with the attribute axis) and
on the result XML (you can't create a namespace declaration as an
attribute, which is what you're attempting to do above).

Instead, namespace declarations are created automatically when a node
tree is serialised into some output. When an element is written, if it
has a namespace node on it but there's not been a namespace
declaration that matches that namespace node, then the serialiser
writes a namespace declaration on that element.

So what you are really trying to do is to create a 'stylesheet'
element in the result tree that has (at least) two namespace nodes on
it: the XSLT namespace and the XFA namespace.  And you'd like the XSLT
namespace to be the default namespace (though logically it doesn't
matter - it's just a case of which prefix is used for it).

Now consider the node tree for the XSLT stylesheet itself. It will
have things like xsl:template element nodes, namespace nodes for the
XSLT namespace and so on. If you declare a namespace at the top of
your stylesheet, then all the elements in the stylesheet node tree
will have namespace nodes for that namespace.

The rules for what namespace nodes are put on an element in the result
tree depend on how you create the element.  If you create the element
with a literal result element, then most namespace nodes that are
present on that literal result element are put in the result tree. If
you use xsl:element, then the only extra namespace node that can be
created is one that you use to identify the namespace of the element

[It's only *most* namespace nodes because some namespace nodes, namely
the XSLT namespace node and any with prefixes given in the
extension-element-prefixes or exclude-result-prefixes attributes,
aren't put in the result tree.  This has implications I'll come on to

So, there are two ways to get the XFA namespace node onto the element
that you're creating.  You can declare it for the stylesheet as a whole:

<xsl:stylesheet version="1.0"
   <stylesheet version="1.0">

or you can declare it specifically for the stylesheet element that
you're creating:

  <stylesheet version="1.0"

Remember that this is *not* the same as creating an attribute on the
'stylesheet' element - the xmlns:xfa attribute is a namespace
declaration, used to create a load of *namespace nodes* on the
'stylesheet' element and all its element descendants in the *stylesheet
tree* (including any XSLT instructions that it holds).  Because the
'stylesheet' element in the stylesheet node tree has this namespace
node, it will be copied with it into the result tree, so the
'stylesheet' element in the result tree (or one of its ancestors) will
have an equivalent namespace declaration on it.

So that's the *easy* one! ;)  Now, when we come to the XSLT namespace
it's a bit more tricky because the XSLT namespace nodes aren't
included within the result tree 'cos most of the time you don't care
about them.  If they *were* included, then most result documents would
have XSLT namespace declarations all over the place - really annoying!

Instead, there's a trick specifically designed to help you create
stylesheets that create stylesheets: xsl:namespace-alias.
xsl:namespace-alias allows you to say that the namespace URI of a
particular namespace in the result tree should be replaced with
another namespace URI.

What you need to do is declare a namespace with a made-up namespace
URI, for example, that you
use as a placeholder for the XSLT namespace URI that you want to use.
Then you can place this made-up namespace on any element in the same
way as indicated above, e.g.:

<xsl:stylesheet version="1.0"
   <stylesheet version="1.0">

Now, the 'stylesheet' literal result element's namespace nodes will
include the alias for the XSLT namespace, as well as the XFA namespace
node.  In fact, because the 'stylesheet' element has no prefix, it
will be placed in the default namespace, specified as

You then use xsl:namespace-alias to tell the XSLT processor that the
namespace URI ""; (the default
namespace) should be mapped to the namespace URI
""; in the final result.  You refer
to each of these namespaces using their prefix, or '#default' if it's
the default namespace:

  <xsl:namespace-alias stylesheet-prefix="#default"
                       result-prefix="xsl" />

The other approach would be to state that the 'stylesheet' element is
in the XSLT namespace by defining it with the xsl:element element:

  <xsl:element name="stylesheet"
     <xsl:attribute name="version">1.0</xsl:attribute>

This is quite a bit longer, especially because it means you have to
define the other attributes using xsl:attribute elements and so on.

I hope that helps,


Jeni Tennison

 XSL-List info and archive:

Current Thread