Namespaces are an important part of XML, and it is essential to understand the concepts behind namespaces in order to query XML documents that use them. This chapter first provides a refresher on namespaces in XML input documents in general. It then covers the use of namespaces in queries: how to declare and refer to them, and how to control their appearance in your results.
Namespaces are used to identify the vocabulary to which XML elements and attributes belong, and to disambiguate names from different vocabularies. For example, both of the XHTML and XSL-FO vocabularies have a table
element, but it has a different structure in each vocabulary. Some XML documents combine elements from multiple vocabularies, and namespaces make it possible to distinguish between them.
Namespaces are defined by a W3C recommendation called Namespaces in XML. Two versions are available: 1.0 and 1.1. XQuery implementations may support either version; you should check with your product’s documentation to determine which version is supported.
A namespace is identified by a URI (Uniform Resource Identifier) reference. A namespace URI is most commonly an HTTP URL, such as http://datypic.com/prod
. It could also be a Uniform Resource Name (URN), which might take the form urn:prod-datypic-com
.
The use of a URI helps to ensure the uniqueness of the name. If a person owns the domain name datypic.com
, she is likely to have some control over that domain and not use duplicate or conflicting namespace URIs within that domain. By contrast, if namespaces could be defined as any string, the likelihood of collisions would be much higher. For this reason, using relative URI references (such as prod
or ../prod
) is discouraged in Namespaces 1.0 and deprecated in Namespaces 1.1.
However, the use of URIs for namespaces has created some confusion. Most people, seeing a namespace http://datypic.com/prod
, assume that they can access that URL in a browser and expect to get something back: a description of the namespace, or perhaps a schema. This is not necessarily the case; there is no requirement for a namespace URI to be dereferencable. No parser, schema validator, or query tool would dereference that URL expecting to retrieve any useful information. Instead, the URI serves simply as a name.
For two namespace URIs to be considered the same, they must have the exact same characters. Although http://datypic.com/prod
and http://datypic.com/prod/
(with a trailing slash) might be considered “equivalent” for some uses, they are considered to be different namespace URIs. Likewise, namespace URIs are case-sensitive, so http://datypic.com/prod
is different from http://datypic.com/proD
.
Namespaces are declared in XML documents by using namespace declarations. A namespace declaration, which looks similar to an attribute, binds a short prefix to a namespace name. That prefix is then used before element and attribute names to indicate that they are in a particular namespace. Example 10-1 shows a document that contains two namespace declarations.
<cat:catalog
xmlns:cat=
"http://datypic.com/cat"
xmlns:prod=
"http://datypic.com/prod"
>
<cat:number>
1446</cat:number>
<prod:product>
<prod:number>
563</prod:number>
<prod:name
prod:language=
"en"
>
Floppy Sun Hat</prod:name>
</prod:product>
</cat:catalog>
The first namespace declaration binds the prefix cat
to the namespace http://datypic.com/cat
, while the second binds the prefix prod
to the namespace http://datypic.com/prod
. The cat
and prod
prefixes precede the names of elements and attributes in the document to indicate their namespace. There are two different number
elements, in different namespaces. The one attribute in the document, language
, is also prefixed, indicating that it is in the http://datypic.com/prod
namespace.
It is important to understand that the prefixes are arbitrary and have no technical significance. Although some XML languages have conventional prefixes, such as xsl
for XSLT, you can actually choose any prefix you want for your XML documents. The document shown in Example 10-2 is considered the equivalent of Example 10-1.
<foo:catalog
xmlns:foo=
"http://datypic.com/cat"
xmlns:bar=
"http://datypic.com/prod"
>
<foo:number>
1446</foo:number>
<bar:product>
<bar:number>
563</bar:number>
<bar:name
bar:language=
"en"
>
Floppy Sun Hat</bar:name>
</bar:product>
</foo:catalog>
Prefixes must follow the same rules as XML names, in that they must start with a letter or underscore, and can only contain certain letters. They also cannot start with the letters xml
in upper- or lowercase. Generally, prefixes are kept short for clarity, usually two to four characters.
You can also designate a particular namespace as the default, meaning that any unprefixed elements are in that namespace. To declare a default namespace, you simply leave the colon and prefix off the xmlns
in the namespace declaration. In this example:
<product xmlns="http://datypic.com/prod"> <number>563</number> <name language="en">Floppy Sun Hat</name> </product>
the product
, number
, and name
elements are in the http://datypic.com/prod
namespace, because they are unprefixed and that is the default namespace. Default namespace declarations and regular namespace declarations can be used together in documents.
However, default namespace declarations do not apply to unprefixed attribute names. Therefore, the language
attribute is not in any namespace, even though you might expect it to be in the default namespace.
An attribute name can also be in a namespace. This is less common than an element in a namespace, because often attributes are considered to be indirectly associated with the namespace of the element they are on, and therefore don’t need to be put in a namespace themselves. For example, general-purpose attributes in the XSLT and XML Schema vocabularies are never prefixed.
However, certain attributes, sometimes referred to informally as global attributes, can appear in many different vocabularies and are therefore in namespaces. Examples include the xml:lang
attribute, which can be used in any XML document to indicate natural language, and the xsi:schemaLocation
attribute, which identifies the location of the schema for a document. It makes sense that these attributes should be in namespaces because they appear on elements that are in different namespaces.
If an attribute name is prefixed, it is associated with the namespace that is bound to that prefix. A significant difference between elements and attributes, however, is that default namespace declarations do not apply to attribute names. Therefore, an unprefixed attribute name is always in no namespace, not the default namespace. It may seem that an attribute should automatically be in the namespace of the element that carries it, but it is considered to be in no namespace for the purposes of querying and even schema validation.
The product
element shown in Example 10-3 has two attributes: app:id
and dept
. The app:id
attribute is, as you would expect, in the http://datypic.com/app
namespace. The dept
attribute, because it is not prefixed, is in no namespace. This is true regardless of the fact that there is a default namespace declaration that applies to the product
element itself.
<product
xmlns=
"http://datypic.com/prod"
xmlns:app=
"http://datypic.com/app"
app:id=
"P123"
dept=
"ACC"
>
...</product>
Namespace declarations are not required to appear in the outermost element of an XML document; they can appear on any element. The scope of a namespace declaration is the element on which it appears and any attributes or descendants of that element. In Example 10-4, there are two namespace declarations: one on catalog
and one on product
. The scope of the second namespace declaration is the prod:product
element itself (including its attributes). The prod
prefix cannot be used outside this scope.
<catalog
xmlns=
"http://datypic.com/cat"
>
<number>
1446</number>
<prod:product
xmlns:prod=
"http://datypic.com/prod"
>
<prod:number>
563</prod:number>
<prod:name
language=
"en"
>
Floppy Sun Hat</prod:name>
</prod:product>
</catalog>
If a namespace declaration appears in the scope of another namespace declaration with the same prefix, it overrides it. This is not recommended for namespace declarations with prefixes because it is confusing. However, it is also possible to override the default namespace, which can be useful when a document consists of several subtrees in different namespaces. Example 10-5 shows an example of this, where the product
element and its descendants are in a separate namespace but do not need to be prefixed.
<catalog
xmlns=
"http://datypic.com/cat"
>
<number>
1446</number>
<product
xmlns=
"http://datypic.com/prod"
>
<number>
563</number>
<name
language=
"en"
>
Floppy Sun Hat</name>
</product>
</catalog>
When using Namespaces 1.1, the namespace specified can be a zero-length string, as in xmlns:prod=""
. This has the effect of undeclaring the namespace bound to prod
; that prefix will no longer be available for use in that scope. Undeclaring prefixes is not permitted in Namespaces 1.0.
As with regular namespace declarations, you can specify a zero-length string as the default namespace, as in xmlns=""
. This undeclares the default namespace.
Now that you have seen how namespaces are used in XML documents, let’s look at how they are used in queries. Namespace-qualified names are used in queries in a number of ways:
The input documents may contain elements and attributes that are in one or more namespaces.
The query may construct new elements and attributes that are in one or more namespaces.
The functions that are declared and/or called in a query have qualified names. This includes user-defined functions and XQuery built-in functions.
The types used in a query have qualified names that are used, for example, in function signatures and in the constructors that create new values of that type.
The variables used in a query have qualified names. Many variables will have no namespace and no prefix, but the names are still considered qualified names.
Other XQuery features such as decimal formats, pragmas, annotations, and options also have qualified names.
When using any of these kinds of names in XQuery, it is necessary to indicate the namespace of the name in question. One way to do this is by using a lexical QName that relies on namespace declarations in the query to determine which namespace the name is in, much like in an XML document. Starting in XQuery 3.0, an alternative is to use a URI-qualified name that includes the entire namespace name (not the prefix), delimited by Q{
and }
, at the beginning of a name. This is explained further at the end of this chapter.
There are three ways that namespaces are bound to prefixes in XQuery queries:
Some namespaces are predeclared; no explicit namespace declaration is necessary to associate a prefix with the namespace.
Namespace declarations can appear in the query prolog.
Namespace declarations can appear in XML constructors.
The examples in this section use the input document cat_ns.xml, shown in Example 10-4.
For convenience, five commonly used namespace declarations are built into the XQuery recommendation. They are listed in Table 10-1. The five prefixes can be used anywhere in a query even if they are not explicitly declared by a namespace declaration. These prefixes are also used throughout this book to represent the appropriate namespaces.
In addition, your XQuery implementation may predeclare other namespaces for use within your queries or allow users to predeclare other namespaces by means of an API. Consult the documentation for your implementation to determine what, if any, other namespaces are predeclared.
Namespaces can be declared in the query prolog. The syntax of a namespace declaration in the query prolog, shown in Figure 10-1, is different from a typical XML namespace declaration. For example:
declare namespace cat = "http://datypic.com/cat";
binds the prefix cat
to the namespace http://datypic.com/cat
.
This binding applies to all names in the entire query, including element names, attribute names, function names, variable names, and type names.
Example 10-6 makes use of two prolog namespace declarations:
The rep
prefix is bound to a namespace that is to be used for a newly constructed element, report
. The report
constructor uses a prefix to indicate that it is that namespace.
The prod
prefix is bound to a namespace used in the input document. This declaration is necessary so that the path expression step prod:product
can associate the name product
with the correct namespace.
Note that the http://datypic.com/cat
namespace does not need to be declared in the query (even though it is used in the input document), because it is not used in any names in the query itself. It does appear in the results, even though it is not associated with any names in the results. This is explained further in “Controlling Namespace Declarations in Your Results”.
Query
declare
namespace
rep
=
"http://datypic.com/report"
;
declare
namespace
prod
=
"http://datypic.com/prod"
;
<rep:report>
{
doc
(
"cat_ns.xml"
)//
prod:product
}
</rep:report>
Results
<rep:report
xmlns:rep=
"http://datypic.com/report"
>
<prod:product
xmlns=
"http://datypic.com/cat"
xmlns:prod=
"http://datypic.com/prod"
>
<prod:number>
563</prod:number>
<prod:name
language=
"en"
>
Floppy Sun Hat</prod:name>
</prod:product>
</rep:report>
The namespace name in a namespace declaration must be a literal value (in quotes), not a variable reference or other evaluated expression. The value should be a syntactically valid, absolute URI.
You can also declare default namespaces in the prolog, using the syntax shown in Figure 10-2. There are two different default namespace declarations, one for elements and types, and the other for functions.
declare default element namespace "http://datypic.com/cat";
would make http://datypic.com/cat
the default namespace for elements and types. This means that anywhere an unprefixed element or type name is used in the query (for example, in element constructors and path expressions), it is assumed to be in that namespace.
This is shown in Example 10-7, which is the same as Example 10-6 except with an added default namespace declaration and a new step catalog
in the path expression. The results are the same as those returned by Example 10-6. In this case, because catalog
is unprefixed, the processor will look for a catalog
element in the default element namespace, http://datypic.com/cat
.
declare
default
element
namespace
"http://datypic.com/cat"
;
declare
namespace
rep
=
"http://datypic.com/report"
;
declare
namespace
prod
=
"http://datypic.com/prod"
;
<rep:report>
{
doc
(
"cat_ns.xml"
)/
catalog
/
prod:product
}
</rep:report>
In Example 10-7, it just so happens that the namespace declarations in the query match the namespace declarations in the input document. The namespace http://datypic.com/prod
is bound to the prod
prefix, and http://datypic.com/cat
is the default, in both places.
However, it is not necessary for the prefixes to match. Example 10-8 shows an equivalent query where a different prefix is used for the namespace http://datypic.com/prod
, and http://datypic.com/cat
now has a prefix associated with it too. Note that the prefixes declared in the query (prod2
and cat
) are used in the path expression, not those from the input document. In fact, it would be an error to use the prod
prefix in this query, because it is not declared in the query itself.
declare
namespace
rep
=
"http://datypic.com/report"
;
declare
namespace
cat
=
"http://datypic.com/cat"
;
declare
namespace
prod2
=
"http://datypic.com/prod"
;
<rep:report>
{
doc
(
"cat_ns.xml"
)/
cat:catalog
/
prod2:product
}
</rep:report>
Example 10-8 yields the same results as Example 10-7. It is worth noting that the prod
prefix (from the input document) is used in the results rather than prod2
(from the query).
As with a regular XML default namespace declaration, a prolog default element namespace declaration does not apply to attribute names, nor does it apply to variable names or function names.
Only one default element namespace declaration may appear in the query prolog. If the string literal is a zero-length string, unprefixed element and type names are considered to be in no namespace.
You can also declare a default namespace for functions, using the same syntax, but with the keyword function
. For example:
declare default function namespace "http://datypic.com/funclib";
This means that all unprefixed functions that are called or declared within that query (including type constructors) are assumed to be in that namespace. If you specify a zero-length string, the default will be “no namespace.” Only one default function namespace declaration may appear in the query prolog.
If no default function namespace is declared, the default is the XPath Functions Namespace,
http://www.w3.org/2005/xpath-functions
. In general, it is best not to override this, because if you do, you are required to prefix calls to built-in functions such as substring
and max
.
For convenience, other prolog declarations can bind namespaces to prefixes, namely schema imports, module declarations, and module imports. For example:
import module namespace strings = "http://datypic.com/strings" at "strings.xqm";
will bind the http://datypic.com/strings
namespace to the strings
prefix. These types of declarations are covered in Chapter 12 and Chapter 14.
Namespaces can also be declared in direct element constructors by using regular XML attributes whose names start with xmlns
. These are known as namespace declaration attributes in XQuery, and are shown in Example 10-9.
Query
<rep:report
xmlns
=
"
http://datypic.com/cat
"
xmlns:prod
=
"
http://datypic.com/prod
"
xmlns:rep
=
"
http://datypic.com/report
"
>
{
doc
(
"cat_ns.xml"
)/
catalog
/
prod:product
}
</rep:report>
Results
<rep:report
xmlns:rep=
"http://datypic.com/report"
xmlns:prod=
"http://datypic.com/prod"
xmlns=
"http://datypic.com/cat"
>
<prod:product>
<prod:number>
563</prod:number>
<prod:name
language=
"en"
>
Floppy Sun Hat</prod:name>
</prod:product>
</rep:report>
The location of the namespace declarations in the results of Example 10-9 are different from those of Example 10-7, although the two results are technically equivalent. This subtle difference is explained in “Controlling Namespace Declarations in Your Results”.
As with prolog namespace declarations, the namespace name used in a namespace declaration attribute must be a literal value, not an enclosed expression, and it should be a syntactically valid, absolute URI. Namespace declaration attributes with prefixes whose values are zero-length strings, such as xmlns:cat=""
, are only allowed if the implementation supports Namespaces 1.1.
Starting in version 3.0, it is also possible to construct namespace declarations in computed constructors, using namespace constructors. These have a similar syntax to computed element and attribute constructors, shown in Figure 10-3.
Unlike namespace declarations in the prolog or on direct element constructors, these computed namespace constructors do not affect XQuery expressions within their scope. Example 10-10 shows an example equivalent to Example 10-9, but with computed constructors. Despite the fact that it uses computed namespace constructors for the rep
, prod
, and cat
namespaces, those namespaces also need to be declared in the prolog so that they can be used in the expressions in the query. The computed namespace constructors only have the effect of adding those three namespace declarations to the rep:report
element in the output. (The report
namespace declaration would have appeared anyway because it is needed to properly put rep:report
in the correct namespace.)
xquery
version
"3.0"
;
declare
namespace
rep
=
"http://datypic.com/report"
;
declare
default
element
namespace
"http://datypic.com/prod"
;
declare
namespace
cat
=
"http://datypic.com/cat"
;
element
rep:report
{
namespace
{
""
}
{
"http://datypic.com/cat"
},
namespace
prod
{
"http://datypic.com/prod"
},
doc
(
"cat_ns.xml"
)/
cat:catalog
/
product
}
Computed namespace constructors are very rarely needed. The only time you need one is when two conditions apply: (a) you don’t know at the time of writing the query what the namespace URI will need to be, and (b) the namespace URI needs to be declared in the output document, but it isn’t actually used on any element or attribute names (if it is used on element or attribute names, the namespace declaration will be added automatically).
This situation can occur, for example, if you need to generate an xsi:type
attribute containing the QName of a type that isn’t known until runtime, perhaps because its name is supplied as a query parameter. It can also happen if you are generating XSD or XSLT files, both of which make heavy use of namespaces in contexts other than element and attribute names.
As in XML documents, namespace declarations in queries have a scope and a set of names to which they are applicable. This section describes the scope and impact of namespace declarations in XQuery, whether they are in the prolog or in direct element constructors.
The scope of a namespace declaration in an element constructor is the constructor itself (including any other attributes, whether they appear before or after the namespace declaration). Much like regular XML documents, namespace declarations in child element constructors can override the namespace declarations of the outer constructors. However, this is not recommended.
The scope of a prolog namespace declaration is the entire query module. However, prolog namespace declarations can also be overridden by namespace declarations in an element constructor. For example, if in Example 10-7 you placed a default namespace declaration in the report
start tag, it would be in scope until the report
end tag (including any attributes of report
), thus overriding the default namespace declaration in the prolog.
Whether namespace declarations appear in the prolog or in a direct element constructor, they have similar rules regarding the names on which they have an effect. Namespace declarations that specify a prefix (i.e., ones that are not default namespace declarations) allow that prefix to be used with any qualified name, namely:
The element and attribute names that are constructed in the query, like rep:report
The element and attribute names from the input document that are used in path expressions, such as cat:catalog
and prod:product
Type names that are used in function signatures and in type-related expressions such as constructors or instance of
expressions
The names of functions, in both function calls and function declarations
The names of variables, both when they are bound and when they are referenced
Default element namespace declarations affect only element and type names. They do not affect attribute, variable, or function names. Attribute and variable names, when they appear unprefixed, are considered to be in no namespace, not the default element namespace. Unprefixed function names are in the default function namespace.
These rules governing the impact of namespace declarations on names are summarized in Table 10-2.
Variety of namespace declaration | Element | Attribute | Type | Function/type constructor | Variable |
---|---|---|---|---|---|
Predeclared namespaces | Y | Y | Y | Y | Y |
Prolog namespace declaration (with prefix) | Y | Y | Y | Y | Y |
Prolog default element namespace | Y | Y | |||
Prolog default function namespace | Y | ||||
Namespace declaration attribute (with prefix) | Y | Y | Y | Y | Y |
Namespace declaration attribute (default) | Y | Y |
It is important to understand that namespace declarations in a query affect only names that are explicitly specified in that query, not those of any child elements that might be included from the input document. Example 10-11 shows a query that copies some elements from an input document into a newly constructed element.
Query
<report
xmlns
=
"
http://datypic.com/report
"
>
<firstChild/>
{
doc
(
"prod_ns.xml"
)/
*
}
</report>
Results
<report
xmlns=
"http://datypic.com/report"
>
<firstChild/>
<prod:product
xmlns:prod=
"http://datypic.com/prod"
>
<prod:number>
563</prod:number>
<prod:name
language=
"en"
>
Floppy Sun Hat</prod:name>
</prod:product>
</report>
It uses the input document prod_ns.xml shown in Example 10-12. The input document elements (names
and name
) are in the http://datypic.com/prod
namespace, while the constructed report
element is in the http://datypic.com/report
namespace.
<prod:product
xmlns:prod=
"http://datypic.com/prod"
>
<prod:number>
563</prod:number>
<prod:name
language=
"en"
>
Floppy Sun Hat</prod:name>
</prod:product>
In the results, report
and firstChild
are in the default namespace specified in the query. However, the product
, number
, and name
elements are still in their original namespace from the input document. They do not become part of the default http://datypic.com/report
namespace. This would be true even if they were in no namespace in the input document. Copying an element never changes its namespace.
If you take the results of your query and serialize them as an XML document, you may be surprised by the way the namespace declarations appear. The number and location of namespace declarations in your results is not always intuitive. However, it can be controlled somewhat by how you declare namespaces in your query and by the use of settings in the prolog.
This section describes how you can control the appearance of namespace declarations in your results. In most cases, these techniques do not affect the real meaning of the results; they are simply cosmetic. They would affect the meaning of the results if namespace prefixes are used on something other than element or attribute names, for example in the values of xsi:type
attributes. If you are unconcerned with the appearance of namespace declarations, you can skip this section.
This chapter describes how you can declare namespaces in the prolog or in direct element constructors. Which one you choose will not affect the actual namespaces of the elements and attributes in the results. However, it can affect the way the results will be serialized, in particular the number and location of the namespace declarations.
The difference has to do with statically known namespaces and in-scope namespaces.
Statically known namespaces are all the namespaces that are known at any given point in a query. This includes the predeclared namespaces, those that were declared in the prolog, and those that were declared using a namespace declaration attribute in an element constructor that is in scope.
In-scope namespaces, on the other hand, are namespaces that are declared on a particular element, or on one of its ancestors. For an element from the input document, the in-scope namespaces are all the namespaces that are declared on that element or on any of its ancestors. Likewise, for an element being constructed in a query, they include the namespaces that are declared using a namespace declaration attribute on that element constructor or one of its ancestors.
For a newly constructed element, the in-scope namespaces are a subset of the statically known namespaces. The in-scope namespaces may include predeclared namespaces, or ones that are declared in the prolog, but only if those namespaces are used in the name of that element, one of its ancestors, or one of its attributes.
Only in-scope namespaces, not all of the statically known namespaces, become part of the results. Therefore, whether you declare a namespace in the prolog or in an element constructor can affect whether (and where) its declaration appears in your results. It can also affect which prefix is used; although the prefix is not technically significant, the XQuery processor will keep track of prefixes used in input documents and queries and use them in the result documents.
Examples 10-13 through 10-15 illustrate this subtle difference. These three examples use the input document shown in Example 10-12.
Example 10-13 shows a query where three different namespace declaration attributes appear in the report
element constructor. Namespaces that are declared in constructors are always part of the in-scope namespaces, so the report
element has three in-scope namespaces. As a result, all three namespace declarations appear in the report
element in the results. The namespace that is bound to the cat
prefix is not used anywhere in the results, but its declaration nevertheless appears because it is one of the in-scope namespaces.
Query
<report
xmlns
=
"
http://datypic.com/report
"
xmlns:cat
=
"
http://datypic.com/cat
"
xmlns:prod
=
"
http://datypic.com/prod
"
>
{
for
$
prod
in
doc
(
"prod_ns.xml"
)/
prod:product
return
<lineItem>
{
$
prod
/
prod:number
}
{
$
prod
/
prod:name
}
</lineItem>
}
</report>
Results
<report
xmlns:prod=
"http://datypic.com/prod"
xmlns:cat=
"http://datypic.com/cat"
xmlns=
"http://datypic.com/report"
>
<lineItem>
<prod:number>
563</prod:number>
<prod:name
language=
"en"
>
Floppy Sun Hat</prod:name>
</lineItem>
</report>
Example 10-14, on the other hand, declares the three namespaces in the prolog. Prolog namespace declarations are not included in the in-scope namespaces unless they are specifically used by the element in question. Therefore, in this case, the report
element has only one in-scope namespace: the one that is used as part of its name, namely the default element namespace http://datypic.com/report
. Consequently, in the results, you only see one namespace declaration on the report
element.
The prod:number
and prod:name
elements are in the prod
namespace, so the prod
declaration is added to the in-scope namespaces of each of these elements. The prod
namespace is declared on both the prod:number
and prod:name
elements, rather than on the report
element, because it is not one of the in-scope namespaces for the report
element.
The prod:number
and prod:name
elements also have the http://datypic.com/report
namespace in scope, since it is used by an ancestor. However, the declaration for http://datypic.com/report
does not need to be repeated on the prod:number
and prod:name
elements because the declaration already appears on the report
element.
Query
declare
default
element
namespace
"http://datypic.com/report"
;
declare
namespace
cat
=
"http://datypic.com/cat"
;
declare
namespace
prod
=
"http://datypic.com/prod"
;
<report>
{
for
$
prod
in
doc
(
"prod_ns.xml"
)/
prod:product
return
<lineItem>
{
$
prod
/
prod:number
}
{
$
prod
/
prod:name
}
</lineItem>
}
</report>
Results
<report
xmlns=
"http://datypic.com/report"
>
<lineItem>
<prod:number
xmlns:prod=
"http://datypic.com/prod"
>
563</prod:number>
<prod:name
xmlns:prod=
"http://datypic.com/prod"
language=
"en"
>
Floppy Sun Hat</prod:name>
</lineItem>
</report>
As you can see, your choice of how to declare the namespaces can affect their location in the result document. Example 10-15 shows a balance between the two approaches. The cat
namespace is declared in the prolog because it is not intended to appear in the results. (Perhaps it does need to be declared—for example, if it is used in a function or variable name.) The prod
namespace declaration is included in the report
constructor so that it only appears once in the results rather than being repeated for each of the prod:number
and prod:name
elements.
Query
declare
namespace
cat
=
"http://datypic.com/cat"
;
<report
xmlns
=
"
http://datypic.com/report
"
xmlns:prod
=
"
http://datypic.com/prod
"
>
{
for
$
prod
in
doc
(
"prod_ns.xml"
)/
prod:product
return
<lineItem>
{
$
prod
/
prod:number
}
{
$
prod
/
prod:name
}
</lineItem>
}
</report>
Results
<report
xmlns:prod=
"http://datypic.com/prod"
xmlns=
"http://datypic.com/report"
>
<lineItem>
<prod:number>
563</prod:number>
<prod:name
language=
"en"
>
Floppy Sun Hat</prod:name>
</lineItem>
</report>
In addition to the considerations discussed in the previous section, there is another way to control the placement of namespace declarations in your results. A word of caution: the facilities described here interact in subtle ways, and not all products implement them correctly.
The copy-namespaces declaration, which appears in the query prolog, controls the appearance of namespace declarations. Specifically, it applies to the case where you construct a new element, and include elements from the input document as children of your new element. It controls whether namespace declarations are inherited from parent constructors, and/or preserved from input documents. Its syntax is shown in Figure 10-4.
It consists of two settings (both required), separated by a comma. For example:
declare copy-namespaces no-preserve, inherit;
If no copy-namespaces declaration is provided, the default values are determined by your implementation. They may have been specified by the user outside the scope of the query or set automatically by the processor.
The first setting, either preserve
or no-preserve
, controls whether unused namespace declarations are included from the input document. Unused here means “not used in the name of the element or its attributes.” Namespace declarations that are being used are always included from the input document, regardless of the setting of preserve
or no-preserve
. Generally, no-preserve
is preferred because there is not much point in copying unused namespace declarations.
One reason to choose preserve
is if your element content (or attribute values) contains namespace-sensitive values, such as qualified names. Namespaces used in content (as opposed to in element/attribute names) are not considered to be “used.” If you choose no-preserve
, and the prefixes in the content are dependent on those non-preserved declarations, an error may be raised when you try to validate or use the output document, because there may be an undeclared prefix.
The second setting, either inherit
or no-inherit
, controls whether the in-scope namespace declarations are copied from an outer constructor in the query to elements that are being copied (usually from the input document). Choosing inherit
usually results in a less cluttered result document. If this value is set to no-inherit
, unused namespaces declared on ancestor elements are explicitly undeclared on the copied element. The main reason for this is to stop namespaces from a content envelope (for example, a SOAP header) from bleeding into the content: if the namespaces are undeclared in the content, the recipient can extract the content without the envelope namespaces having polluted the message body.
Undeclaring prefixes is only allowed in Namespaces 1.1, so no-inherit
is essentially ignored if your implementation does not support Namespaces 1.1.
Note that these settings affect in-scope namespaces only, not statically known namespaces. They apply to both default namespace declarations and those that use prefixes.
Examples 10-17 and 10-18 exhibit the differences in these settings. They use the input document shown in Example 10-16, which has three different namespaces declared.
<cat:catalog
xmlns:cat=
"http://datypic.com/cat"
xmlns:prod=
"http://datypic.com/prod"
xmlns:ord=
"http://datypic.com/ord"
>
<prod:product>
<prod:number>
563</prod:number>
<prod:name
language=
"en"
>
Floppy Sun Hat</prod:name>
</prod:product>
</cat:catalog>
Example 10-17 shows a query that uses the settings no-preserve
and inherit
. This combination of settings usually results in the fewest surprises. The query returns a report
element that contains a product
element copied from the input document. The report
element has three namespace declaration attributes, and therefore has three in-scope namespaces.
no-preserve
, inherit
Query
declare
copy-namespaces
no-preserve
,
inherit
;
<report
xmlns
=
"
http://datypic.com/report
"
xmlns:cat
=
"
http://datypic.com/cat
"
xmlns:prodnew
=
"
http://datypic.com/prod
"
>
{
doc
(
"cat_ns2.xml"
)//
prodnew:product
}
</report>
Results
<report
xmlns=
"http://datypic.com/report"
xmlns:cat=
"http://datypic.com/cat"
xmlns:prodnew=
"http://datypic.com/prod"
>
<prod:product
xmlns:prod=
"http://datypic.com/prod"
>
<prod:number>
563</prod:number>
<prod:name
language=
"en"
>
Floppy Sun Hat</prod:name>
</prod:product>
</report>
In the results, the only namespace declaration preserved from the input document is the one that the product
element is actually using (because it is part of its name). This is because the no-preserve
setting meant that unused namespace declarations were not copied from the input document.
Because inherit
is chosen, the product
element has declarations for the default (report
) and cat
namespaces in scope, even though it doesn’t use them.
Note that even though the http://datypic.com/prod
namespace is declared (with the prefix prodnew
) in the report
start tag, it is redeclared in the product
start tag with a different prefix, and it is the prod
prefix that is used. This is because nodes that are included from the input document will always use the prefixes that come from the input document. No combination of copy-namespaces settings will allow the prodnew
prefix to be used for the product
element instead of the prod
prefix. To change any aspect of the element name, whether prefix, URI, or local name, you need to construct a new element rather than copying the original.
Example 10-18 shows the exact same query but with the opposite settings: preserve
and no-inherit
. In this case, all three namespace declarations from the input document are preserved (prod
, ord
, and cat
), even though the cat
and ord
namespaces are not used. The cat
namespace declaration is not written out in the product
start tag because it has the same prefix and namespace as the one in the report
start tag. The serialization process takes care of eliminating duplicate namespace declarations that are in the same scope.
Because no-inherit
is chosen, the product
element should not inherit the default (report
) and prodnew
namespace declarations from the report
element. Therefore, they are undeclared (assuming your processor supports Namespaces 1.1).
preserve
, no-inherit
Query
declare
copy-namespaces
preserve
,
no-inherit
;
<report
xmlns
=
"
http://datypic.com/report
"
xmlns:cat
=
"
http://datypic.com/cat
"
xmlns:prodnew
=
"
http://datypic.com/prod
"
>
{
doc
(
"cat_ns2.xml"
)//
prodnew:product
}
</report>
Results
<report
xmlns=
"http://datypic.com/report"
xmlns:cat=
"http://datypic.com/cat"
xmlns:prodnew=
"http://datypic.com/prod"
>
<prod:product
xmlns:prod=
"http://datypic.com/prod"
xmlns:ord=
"http://datypic.com/ord"
xmlns=
""
xmlns:prodnew=
""
>
<prod:number>
563</prod:number>
<prod:name
language=
"en"
>
Floppy Sun Hat</prod:name>
</prod:product>
</report>
As an alternative to using namespace declarations, it is possible, starting in XQuery 3.0, to use a URI-qualified name that includes the entire literal namespace name, delimited by Q{
and }
, at the beginning of a name. For example, instead of using the name prod:name
, you could omit the declaration for the prod
prefix and use the following name:
Q{http://datypic.com/prod}product
This syntax can be used almost all places that a literal name is used in a query, for example in a function call, an element or attribute name used in an XPath, or a variable name. One place it cannot be used is in direct constructors, because they use an XML-like syntax, and the URI-qualified name syntax is not allowed in XML documents.
Example 10-19 shows a revised version of Example 10-6 where instead of declaring the prod
prefix in a namespace declaration, the http://datypic.com/prod
namespace name is used in its entirety in the path expression.
xquery
version
"3.0"
;
declare
namespace
rep
=
"http://datypic.com/report"
;
<rep:report>
{
doc
(
"cat_ns.xml"
)//
Q
{
http
://
datypic.com
/
prod
}
product
}
</rep:report>
Because the example uses the http://datypic.com/report
namespace in a direct constructor, it still needs to use a namespace declaration for that namespace, and use the rep
prefix in the constructor. URI-qualified names are more useful in XPath than in XQuery because XPath doesn’t have a prolog where prefixes can be declared, but is carried over to XQuery for compatibility.