Re: [xsl] <xsl:copy> and namespaces

Subject: Re: [xsl] <xsl:copy> and namespaces
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Mon, 15 Apr 2002 15:35:53 +0100
Hi Joeri,

> Can anyone explain the use of namespaces and <xsl:copy>. When my XML
> file has no namespaces defined, the stylesheet works perfect. But
> with the namespaces added ( like in my example ), the copy failes.
> How should i copy when namespaces are involved. So i have a default
> namespace ( urn:my-ns ) and a alias for 'o' ( urn:my-o-ns ). The
> record and all the childeren of record take the default ns. Why is
> this interfering in my copy. I have specified the default namespace
> aswell in my stylesheet.

This isn't actually a problem with xsl:copy, but rather with the way
that XPath uses (or rather doesn't use) the default namespace
declaration.

In XPath expressions, if you don't specify a prefix for an element or
attribute, then the XPath matches elements or attributes with that
name *in no namespace*. So for example, when you do:

>     <xsl:apply-templates select="record"/>

you are telling the XSLT processor to apply templates to the 'record'
element children of the context node that are in no namespace. XPath
processors don't use default namespace declarations to supply
namespaces for element (or attribute) names.

In your source document, your elements are all in the namespace
"urn:my-ns", so searching for a 'record' element in no namespace
doesn't find anything, and the transformation produces nothing as a
result.

What you need to do is, in your stylesheet, declare the urn:my-ns
namespace *with a prefix*:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                xmlns:my="urn:my-ns"
                xmlns:o="urn:my-o-ns">
...
</xsl:stylesheet>

Then, in all the XPath expressions and XSLT patterns where you refer
to elements in that namespace, use that prefix. For example:

<xsl:template match="my:record">
  <xsl:copy>
    <xsl:apply-templates select="my:field"/>
  </xsl:copy>
</xsl:template>

This way, the XSLT processor will look for elements called 'record' or
'field' in the namespace 'urn:my-ns' rather than no namespace.

---

This becomes a little more straight-forward in XSLT 2.0, in which the
attribute default-xpath-namespace can hold the namespace that you want
to be used when an element name in a stylesheet (*not* an attribute
name) doesn't have a prefix. In XSLT 2.0, you could do:

<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                default-xpath-namespace="urn:my-ns"
                xmlns:o="urn:my-o-ns">
...
</xsl:stylesheet>

and leave the paths and patterns as you have them at the moment.

Cheers,

Jeni

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


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread