[XSLT 2.0] Inheriting Namespace Nodes

The following comment was initially raised at:

http://lists.w3.org/Archives/Member/w3c-xsl-wg/2003Oct/0122.html
(member-only URL)

(I think this comment slipped off the radar because we were too busy
getting the Last Call draft published at the time. I have updated the
note slightly to address the relationship of serialization and
validation).

We have changed the rules for namespace fixup so that when an element C
is
attached as a child of parent element P, it no longer automatically
inherits
the namespace nodes of P.

We defined it this way for xsl:copy, and it works reasonably well in
that
case. The idea is that if you put your XML payload in a SOAP envelope
and
then extract it again, it hasn't been polluted with SOAP namespaces.
This
leads occasionally to a superfluous xmlns="" undeclaration, but that's
liveable-with.

More problematic is the situation with xsl:element. In a formal sense
the
rules here are exactly the same: we create a new element, in this case
with
no namespace nodes of its own unless we use xsl:namespace to create
them. It
then gets fixed up, which gives it namespace nodes for the element and
attribute names, and then it gets attached to a new parent, at which
point
it acquires no additional namespace nodes.

The effect of this is that if you are writing a stylesheet, and do:

<xsl:template match="/">
  <xsl:element name="xsl:stylesheet" 
               namespace="http://www.w3.org/1999/XSL/Transform">
     <xsl:namespace
name="xs">http://www.w3.org/2001/XMLSchema</xsl:namespace>
     <xsl:element name="xsl:template">
       <xsl:attribute name="match">attribute(*,xs:date)</xsl:attribute>
     </xsl:element>
  </xsl:element>
</xsl:template>

Then the "xs" namespace is in scope for the generated xsl:stylesheet
element, but not for the generated xsl:template element, which means
that
the reference to xs:date is an error. At any rate, it will be an error
if
you serialize with undeclare-namespaces="yes"; but possibly also if you
try
to use the result tree as a stylesheet without serializing it, since the
parser will look for an in-scope namespace node to resolve "xs:date" and
won't find one. 

In a slightly modified example, one could show that QName-valued
attributes
would not pass validation. But this actually shows up a gap in our
specs: we define validation formally in terms of a process of
serializing the tree, then parsing to create an Infoset, and then
validating the Infoset. But we don't say what options are chosen to do
the validation. Currently XML Schema is only defined in terms of XML
1.0, so this would suggest serializing as XML 1.0, which has the
fortuitous effect of propagating the namespace scope; but this doesn't
seem a long-term solution.

The problem is particularly acute for xsl:element because it doesn't
inherit
namespace nodes from its parents in the stylesheet either.

The most obvious noticeable effect is a proliferation of xmlns=""
undeclarations. If the parent element has a namespace node that binds
the
default prefix to some namespace, and if the child element has no
namespace
node for the default prefix, then the serializer is required to output
xmlns="". In 1.0 you only get these if the child element actually uses
the
default namespace in its element name. We could say that this comes
within
the scope of undeclare-namespaces, but that's tricky, because the
serializer
can't easily tell whether the absence of a namespace node for the
default
namespace is significant or not.

Technically there's probably no backwards incompatibility because XSLT
1.0
defined no way of accessing a result tree without serializing it, and
serializing would always cause any namespace nodes (other than the
default
namespace perhaps) to be inherited by child elements because XML 1.0
didn't
allow any other option. But I don't feel entirely comfortable about it.

My first thought was to have different rules for xsl:copy-of and
xsl:element
but that doesn't work. The semantics describing how nodes are
constructed
are now completely separated from the semantics of how they are attached
to
a parent element, so the latter process can't depend on what instruction
was
used to create the element. 

One could potentially make it a property of the instruction that creates
the
parent element, so one could have an attribute
propagate-namespaces="yes|no"
on xsl:element, LREs, and xsl:copy. But I don't like that much - 99% of
users would have no idea what it meant. 

The underlying problem seems to be that namespace undeclaration in XML
1.1
is a very positive signal that you don't want the namespace propagated.
Because we use namespace nodes rather than declarations and
undeclarations,
we are relying on a negative signal: if you don't explicitly ask for the
namespace at every level, you don't get it. It's hard to see how to
change
this without changing the model for namespace nodes, which is something
I
don't want to touch with a bargepole.

So I think we have to make a binary choice: should namespace nodes
automatically propagate from parents to children, or not? I'm a bit
inclined
at the moment to think that the low-risk approach is to propagate them,
i.e.
to revert to the previous specification. This would leave us without any
way
of forcing a namespace undeclaration to be output.

Michael Kay

Received on Friday, 6 February 2004 05:17:55 UTC