Chapter 10. Namespaces and XQuery

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.

XML Namespaces

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.

Namespace URIs

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.

Declaring Namespaces

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.

Example 10-1. 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.

Example 10-2. Alternate prefixes
<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.

Default Namespace Declarations

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.

Namespaces and Attributes

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.

Example 10-3. Namespaces and attributes
<product xmlns="http://datypic.com/prod"
         xmlns:app="http://datypic.com/app"
         app:id="P123" dept="ACC">
...
</product>

Namespace Declarations and Scope

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.

Example 10-4. Namespace declarations and scope (cat_ns.xml)
<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.

Example 10-5. Overriding the default namespace
<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.

Namespaces and XQuery

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.

    • Built-in types are in the XML Schema Namespace, and are conventionally prefixed with xs.

    • User-defined types are in the target namespace of the schema document in which they are defined.

  • 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.

Namespace Declarations in Queries

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.

Predeclared Namespaces

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.

Table 10-1. Predeclared namespaces
PrefixNamespaceUses
xml http://www.w3.org/XML/1998/namespace XML attributes such as xml:lang and xml:space
xs http://www.w3.org/2001/XMLSchema XML Schema built-in types and their constructors
xsi http://www.w3.org/2001/XMLSchema-instance XML Schema instance attributes such as xsi:type and xsi:nil
fn http://www.w3.org/2005/xpath-functions XPath Functions Namespace: the default namespace of most built-in functions
local http://www.w3.org/2005/xquery-local-functions Functions declared in a main module that are not in a specific namespace

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.

Prolog Namespace Declarations

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.

Figure 10-1. Syntax of a prolog namespace declaration

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”.

Example 10-6. Prolog namespace declarations

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.

Default namespace declarations in the prolog

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.

Figure 10-2. Syntax of a prolog default namespace declaration

For example:

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.

Example 10-7. Prolog default namespace declaration
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.

Example 10-8. Namespace declarations in query different from input document
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.

The default function namespace declaration

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.

Other prolog namespace declarations

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.

Namespace Declarations in Direct Element Constructors

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.

Example 10-9. Using namespace declaration attributes

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.

Namespace Declarations in Computed Constructors

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.

Figure 10-3. Syntax of a namespace constructor

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.)

Example 10-10. Using a namespace constructor
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.

The Impact and Scope of Namespace Declarations

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.

Scope of namespace declarations

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.

Names affected by namespace declarations

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.

Table 10-2. Impact of namespace declarations on names
Variety of namespace declarationElementAttributeTypeFunction/type constructorVariable
Predeclared namespacesYYYYY
Prolog namespace declaration (with prefix)YYYYY
Prolog default element namespaceYY
Prolog default function namespaceY
Namespace declaration attribute (with prefix)YYYYY
Namespace declaration attribute (default)YY

Namespace declarations and input elements

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.

Example 10-11. Namespace declaration impact on input elements

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.

Example 10-12. Simple product example in namespace (prod_ns.xml)
<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.

Controlling Namespace Declarations in Your Results

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.

In-Scope Versus Statically Known Namespaces

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.

Example 10-13. Using XML namespace declarations

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.

Example 10-14. The effect of prolog namespace declarations

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.

Example 10-15. A balanced approach

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>

Controlling the Copying of Namespace Declarations

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.

Figure 10-4. Syntax of a copy-namespaces declaration

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.

Example 10-16. Multinamespace input document (cat_ns2.xml)
<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.

Example 10-17. Query with 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).

Example 10-18. Query with 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>

URI-Qualified Names

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.

Example 10-19. Using a URI-qualified name
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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.69.255