Chapter 20. Working with Qualified Names, URIs, and IDs

This chapter describes the functions and constructors that act on namespace-qualified names, Uniform Resource Identifiers (URIs), and IDs. Each of these types has unique properties and complexities that sets it apart from simple strings.

Working with Qualified Names

The type xs:QName is used to represent qualified names in XQuery. An xs:QName value has three parts: a namespace, a local part, and an associated prefix. The namespace and the prefix are optional. If a QName does not have a namespace associated with it, it is considered to be in "no namespace."

A prefix may be used to represent a namespace in a qualified name, for example in an XML document. The prefix is mapped to a namespace using a namespace declaration. The prefix itself has no meaning; it is just a placeholder. Two QNames that have the same local part and namespace are equivalent, regardless of prefix. However, the XQuery processor does keep track of a QName's prefix. This simplifies certain processes like serializing QNames and casting them to strings.

Most query writers who are working with qualified names are working with the names of elements and attributes. (It is also possible for a qualified name to appear as element content or as an attribute value, but this is less common.) You may want to retrieve all or part of a name if, for example, you want to test to see if it is a particular value, or you want to include the name in the query results. You may want to construct a qualified name for a node if you are dynamically creating the name of a node using a computed element constructor. These two use cases are discussed in this section.

Retrieving Node Names

Four functions retrieve node names or parts of node names: node-name, name, local-name, and namespace-uri from element and attribute nodes. They are summarized in Table 20-1.

Table 20-1. Functions that return node names

Function

Return value

node-name

The qualified name of the node as an xs:QName

name

The qualified name of the node as an xs:string that may be prefixed

local-name

The local part of the node name as an xs:string

namespace-uri

The namespace part of a node name (a full namespace name, not a prefix) as an xs:anyURI

Each of these functions takes as an argument a single (optional) node. Table 20-2 shows examples of all four functions. They use the input document names.xml shown in Example 20-1.

Example 20-1. Namespaces in XML (names.xml)

<noNamespace>
  <pre:prefixed xmlns="http://datypic.com/unpre"
           xmlns:pre="http://datypic.com/pre">
    <unprefixed pre:prefAttr="a" noNSAttr="b">123</unprefixed>
  </pre:prefixed>
</noNamespace>

Note that the original prefixes from the input document (or lack thereof) are taken into account when retrieving the names. For example, calling the name function with the unprefixed element results in the unprefixed string unprefixed. This does not mean that the unprefixed element is not in a namespace; it is in the http://datypic.com/unpre namespace. It simply indicates that the unprefixed element was not prefixed in the input document, because its namespace was the default, and therefore had no prefix as part of its QName. Therefore, if you are testing the name or manipulating it in some way, it is best to use node-name rather than name, because node-name provides a result that includes the namespace.

Table 20-2. Examples of the name functions

Node

node-name returns an xs:QName with:

name returns

local-name returns

namespace-uri returns

noNamespace

Namespace: empty

Prefix: empty

Local part:noNamespace

noNamespace

noNamespace

A zero-length string

pre:prefixed

Namespace: http://datypic.com/pre

Prefix: pre

Local part: prefixed

pre:prefixed

prefixed

http://datypic.com/pre

unprefixed

Namespace: http://datypic.com/unpre

Prefix: empty

Local part: unprefixed

unprefixed

unprefixed

http://datypic.com/unpre

@pre:prefAttr

Namespace: http://datypic.com/pre

Prefix: pre

Local part: prefAttr

pre:prefAttr

prefAttr

http://datypic.com/pre

@noNSAttr

Namespace: empty

Prefix: empty

Local part: noNSAttr

noNSAttr

noNSAttr

A zero-length string

Suppose you want to create a report on the product catalog. You want to list all the properties of each product element in an XHTML list. You could accomplish this using the query shown in Example 20-2. It uses the local-name function to return the names like name, colorChoices, and desc, allowing them to appear as part of the report.

Example 20-2. Using names as result data

Query
<html>{
  for $prod in doc("catalog.xml")//product
   return (<p>Product # {string($prod/number)}</p>,
           <ul>{
             for $child in $prod/(* except number)
             return <li>{local-name($child)}: {string($child)}</li>
           }</ul>)
}</html>
Results
<html>
  <p>Product # 557</p>
  <ul>
    <li>name: Fleece Pullover</li>
    <li>colorChoices: navy black</li>
  </ul>
  <p>Product # 563</p>
  <ul>
    <li>name: Floppy Sun Hat</li>
  </ul>
  <p>Product # 443</p>
  <ul>
    <li>name: Deluxe Travel Bag</li>
  </ul>
  <p>Product # 784</p>
  <ul>
    <li>name: Cotton Dress Shirt</li>
    <li>colorChoices: white gray</li>
    <li>desc: Our favorite shirt!</li>
  </ul>
</html>

Constructing Qualified Names

There are several ways to construct qualified names. Qualified names are constructed automatically when using direct element and attribute constructors. They can also be constructed directly from strings in certain expressions such as computed element constructors. In addition, three functions are available to construct QNames: the xs:QName constructor, the QName function, and the resolve-QName function.

The xs:QName type has a constructor just like all other atomic types. The argument may be prefixed (e.g., prod:number) or unprefixed (e.g., number). However, it has a special constraint that it can only accept a literal xs:string value (not an evaluated expression). This limits its usefulness, since names cannot be dynamically generated.

A function called QName can also be used to construct QNames. Unlike the xs:QName constructor, it can be used to generate names dynamically. It accepts a namespace URI and name (optionally prefixed), and returns a QName. For example:

QName("http://datypic.com/p", "pre:child")

returns a QName with the namespace http://datypic.com/p, the local part child, and the prefix pre. As with any function call, the arguments are not required to be literal strings. You could just as easily use an expression such as concat("pre:",$myElName) to express the local part of the name.

A third option is the resolve-QName function, which accepts two arguments: a string and an element. The string represents the name, which may have a prefix. The element is used to determine the appropriate namespace URI for that prefix. Typically, this function is used to resolve a QName appearing in the content of a document against the namespace context of the element where the QName appears. For example, to retrieve all products that carry the attribute xsi:type="prod:ProductType", you can use a path such as:

declare namespace prod = "http://datypic.com/prod";

doc("catalog.xml"//product[resolve-QName(@xsi:type, .) = xs:QName("prod:ProductType")]

This test allows the value of xsi:type in the input document to use any prefix (not just prod) as long as it is bound to the http://datypic.com/prod namespace.

Other Name-Related Functions

Three functions exist to extract parts of an xs:QName:

local-name-from-QName

Returns the local part of the name as a string

prefix-from-QName

Returns the prefix as a string

namespace-uri-from-QName

Returns the namespace URI

The local-name-from-QName and namespace-uri-from-QName functions are similar to the local-name and namespace-uri functions, respectively, except that they take an atomic xs:QName rather than a node as an argument. If you are working with element or attribute names, it is easier to use the functions for retrieving node names, such as local-name and name.

XQuery also has two other prefix-related functions: in-scope-prefixes and namespace-uri-for-prefix. The in-scope-prefixes function returns a list of all the prefixes that are in scope for a given element, as a sequence of strings. The namespace-uri-for-prefix function retrieves the namespace URI associated with a particular prefix, in the scope of a specified element. Because most processing is based on namespaces rather than prefixes (which are technically irrelevant), these functions are not especially useful to the average query writer.

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

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