Namespace Nuances

XQuery uses the concept of a namespace, adopted from the XML 1.0 specification. But, due to the complex nature of the XQuery language and it's dual roles as both query and serialization/XML construction language, there are several nuances to the use of namespaces that may not be immediately obvious.

The first issue I will deal with is the concept of a default namespace. In XML 1.0, if you used an xmlns attribute without an associated name, all elements under that scope were considered to be in the namespace referenced by the associated URI. Notice I said all elements - attributes are not affected by default namespaces in XML. This functionality is mirrored in XQuery, either through the use of the declare default element namespace prolog entry, or by directly constructing the xmlns attribute on your constructed XML. Again, in XQuery the default element namespace does not affect non-element data i.e. attributes, function names and variables (all of which may have associated namespace prefixes) must be explicitly namespaced if required (NOTE: SQL Server 2005 XQuery does not currently allow variables to be placed into a namespace, even though this is allowed in the XQuery specification). Function names in XQuery have their own default namespace entry, accessible through the declare default function namespace prolog option.

In XQuery a previously declared namespace prefix can be used to add a namespace to elements, attributes, function calls and variables. Unlike the default options, the same namespace prefix can be used to apply to all 4 different identifier types.

Lastly, when doing XML construction, the order that a namespace is declared in does not affect the scope, since attribute order in XML is considered non normative. Take the following XQuery expression as an example:

 <foo:element foo:index="1" xmlns:foo="https://example.com/foo" />

In this simple case, we have constructed an element in the foo namespace, containing an attribute which is also in the foo namespace. Notice that we were able to use the foo namespace prefix even before it was technically defined (by the xmlns attribute). In this case, the result of the query was pretty obvious. Now, consider the following XQuery:

 declare namespace foo="https://example.com/foo1";
<foo:element xmlns:foo="https://example.com/foo2" />

In this case, we initially declare that the namespace prefix foo points to the URI https://example.com/foo1. But, when we construct the new element, the namespace prefix foo is redefined to point to the URI https://example.com/foo2, which is the URI used for the constructed XML element. Again, these results are pretty obvious, but the trick comes when we combine XML construction with XQuery expressions to generate dynamic content. Consider the following query:

 declare namespace foo="https://example.com/foo1";
<foo:element index="{/foo:index}" xmlns:foo="https://example.com/foo2" />

Initially, the namespace prefix foo is declared to point to the URI https://example.com/foo1. The element constructor in the query contains an attribute constructor for the attribute index which uses an XQuery expression to dynamically calculate the value for this attribute. Inside this dynamic attribute content expression, the namespace foo is referenced. Even though the redefinition of the foo namespace prefix technically occurs after the XQuery expression used to generate the contents of the index attribute, since the scope of the redefinition applies to the entire element constructor, within the dynamic attribute expression, the namespace prefix foo is defined to point to the URI https://example.com/foo2\!

The easiest thing is to avoid such inconsistencies by placing any namespace prefix definitions as the first attributes in an element constructor. Thus, the order of assignment of URI's to namespace prefixes will be more immediately apparent.

-
Disclaimer:
This posting is provided “AS IS” with no waranties, and confers no rights.
Use of included script samples are subject to the terms specified at https://www.microsoft.com/info/cpyright.htm.