Re: [xsl] creating multiple namespace definitions in top element of output document

Subject: Re: [xsl] creating multiple namespace definitions in top element of output document
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Mon, 5 Apr 2004 14:03:37 +0100
Hi Jozef,

> In the top element of the output document (i.e. the result of the
> stylesheet transformation), I want to have multiple namespace
> declarations, e.g.:
>
> <html xmlns="http://www.w3.org/1999/xhtml";
> xmlns:xforms="http://www.w3.org/2002/xforms";
> xmlns:xsd="http://www.w3.org/2001/XMLSchema";
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>
>
> How do I do that in my stylesheet ?

When you create an element using a literal result element (an element
in a non-XSLT namespace within a template), any namespace nodes on
that element get reproduced on the corresponding element in the
result. The namespace nodes are then used to determine what namespace
declarations the element needs.

So to put the namespace declarations above on the <html> element in
the result, you need to give it the namespace nodes for the XForms,
XSD and XSI namespaces. The simplest way to do that is to declare the
namespaces on the <xsl:stylesheet> element; that way, they are in
scope for the entire stylesheet and all the literal result elements
that you use will have those namespace nodes. Like so:

<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                xmlns="http://www.w3.org/1999/xhtml";
                xmlns:xforms="http://www.w3.org/2002/xforms";
                xmlns:xsd="http://www.w3.org/2001/XMLSchema";
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>

<xsl:template match="/">
  <html>
    ...
  </html>
</xsl:template>
...
</xsl:stylesheet>

If you're generating the <html> element by copying it, however, you
can't use this method. The namespace nodes on an element that's copied
are the same as the namespace nodes on the original element. So if
you're copying the <html> element, and it doesn't have the namespaces
you want, you need to add the extra namespace nodes yourself. In XSLT
1.0, the easiest way to do this is to declare the namespaces on the
<xsl:stylesheet> element and then copy them using xsl:copy-of:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                xmlns:xhtml="http://www.w3.org/1999/xhtml";
                xmlns:xforms="http://www.w3.org/2002/xforms";
                xmlns:xsd="http://www.w3.org/2001/XMLSchema";
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>

<xsl:variable name="stylesheet"
              select="document('')/xsl:stylesheet" />
                
<xsl:template match="xhtml:html">
  <xsl:copy>
    <xsl:copy-of select="$stylesheet/namespace::xforms |
                         $stylesheet/namespace::xsd |
                         $stylesheet/namespace::xsi" />
    ...
  </xsl:copy>
</xsl:template>
...
</xsl:stylesheet>

In XSLT 2.0, you can instead create the namespace nodes with the new
<xsl:namespace> instruction, as follows:

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

<xsl:variable name="stylesheet"
              select="document('')/xsl:stylesheet" />
                
<xsl:template match="xhtml:html">
  <xsl:copy>
    <xsl:namespace name="xforms"
                   select="'http://www.w3.org/2002/xforms'" />
    <xsl:namespace name="xsd"
                   select="'http://www.w3.org/2001/XMLSchema'" />
    <xsl:namespace name="xsi"
                   select="'http://www.w3.org/2001/XMLSchema-instance'" />
    ...
  </xsl:copy>
</xsl:template>
...
</xsl:stylesheet>

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/

Current Thread