XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition (613 page)

BOOK: XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition
9.34Mb size Format: txt, pdf, ePub

If the lexical QName does have a prefix, then the system looks for a namespace node of the given element whose name matches this prefix. If it finds one, then the namespace URI component of the result is taken from the string value of this namespace node. If there is no matching namespace node, then the function reports an error.

Examples

Consider the source document:


   title

   

    one:value

    value

  


And suppose that the following variables are bound:

              xmlns:top=“ http://mhk.me.uk/default.uri”/>




Expression
Result (in Clark notation)
resolve-QName($doc/*[1], $doc)
{http://mhk.me.uk/default.uri}title
resolve-QName($chap/@att-one, $chap)
{}text
resolve-QName(string($data1), $data1)
{http://mhk.me.uk/one.uri} value
resolve-QName(string($data2), $data2)
{} value

In these examples I have shown the resulting URI in
Clark notation
, named after James Clark, the lead designer of XSLT 1.0 and XPath 1.0. This notation represents an expanded QName in the form
{namespace-uri}local-name
.

Note that all these examples resolve a lexical QName found in the content of the document against the element node that contains the value. This is the normal and probably the only sensible way to use this function, since the prefix of a QName only has meaning in the context of the element where it is used.

Usage

The purpose of this function, as the examples show, is to resolve QName values found in the content of elements or attributes within a document.

It's never necessary to use this function to resolve QNames used as element and attribute names, because the system does that for you.

It's also unnecessary to use this function if you have a schema-aware processor, and a schema that declares the relevant elements and attributes as having type
xs:QName
. In this case the schema processor will do the work for you, and you can access the expanded QName as the typed value of the element or attribute, using the
data()
function.

The function is needed when you have lexical QNames in the document content and they aren't declared as such in the schema. This can happen for a number of reasons:

  • You are using a processor that isn't schema-aware, or a source document for which no schema has been written.
  • The lexical QName doesn't make up the whole of the element or attribute value, for example, it might be buried inside an XPath expression.
  • The value of the attribute isn't always a QName (an example is the
    default
    attribute of the

    element in XML Schema itself, whose type depends on the type of the element being defined).
  • You don't want to use the rules that XML Schema uses for handling the default namespace (an example is the
    name
    attribute of the

    element in XSLT, where an unprefixed name uses the null namespace rather than the default namespace).

Let's look at this last example more closely. If your source documents are XSLT stylesheets (it is actually quite common to process stylesheets using XSLT), then there are many lexical QNames used within the content of the document (for example, in the
name
attribute of templates, keys, and functions, the
mode
attribute of

, and myriad other places). These aren't declared as
xs:QName
values in the schema for XSLT, however. The reason is subtle: although an XML Schema would do the correct validation if these attributes had type
xs:QName
, it would not do the conversion from the lexical space to the value space correctly. This is because XSLT specifies that when there is no prefix, these names are in the null namespace, regardless of any default namespace declaration, while XML Schema when it processes
xs:QName
values decides that the absence of a prefix implies use of the default namespace (I don't think this rule is in the spec, but it seems to be the way that XML Schema processors are expected to behave).

This means that you can only use this function for names found in XSLT stylesheets if you handle the unprefixed case yourself. Fortunately, this is easy enough:

if (contains(@name, ‘:’))

then resolve-QName(@name, .)

else QName(“”, @name)

Rather surprisingly, it's also possible to come across QNames that aren't declared as such when you run XPath expressions against an XML Schema document. This is because values of any type can appear in places such as the
xs:enumeration
facet of a simple type, or the
default
attribute of an element or attribute declaration. Because these constructs might contain values of any type, their declared type in the schema for schemas is simply
xs:string
. The only way you can work out that one of these strings needs to be treated as a QName is by rather complex analysis of the schema.

See Also

QName()
on page 858

in-scope-prefixes()
on page 808

resolve-uri

The
resolve-uri()
function converts a URI reference into an absolute URI by resolving it against a specified base URI.

Signature

Argument
Type
Meaning
reference
xs:string?
The URI reference to be resolved. If this argument is an empty sequence, an empty sequence is returned.
base-uri
(optional)
xs:string
The base URI against which the relative reference is to be resolved. If this argument is omitted, the base URI from the static context is used. This must be an absolute URI.
Result
xs:string
The resulting absolute URI
.

Effect

It's worth starting by establishing the correct terminology. A
URI Reference
is either a
URI
or a relative reference. A
URI
is an
absolute URI
optionally followed by
#fragment
. An absolute URI starts with a scheme-name and a colon (for example
http:
).

A relative reference is often referred to as a
relative URI
. Technically, this is incorrect: if it's not absolute, then it's not a URI. But it's common usage, and you'll find it elsewhere in this book.

The arguments are defined as
xs:string
rather than
xs:anyURI
because this allows the supplied argument to be either an
xs:string
or an
xs:anyURI
, under the XPath function calling rules.

If the value supplied as
reference
is a URI (as distinct from a relative reference) then no resolution is needed, and the value is returned unchanged. Otherwise, it must be a relative reference, and it will be resolved against the absolute URI supplied in the second argument, or against the base URI from the static context if the second argument is omitted.

The process of URI resolution takes a relative reference such as
details.html
and resolves it against an absolute URI such as
http://example.com/index.html
to produce an absolute URI such as
http://example.com/details.html
. Note that this process is done purely by analyzing the two character strings, it doesn't require any access to the network to find out whether these files actually exist. This means that it is quite legitimate to apply the operation to things like collation URIs that don't necessarily represent real resources on the Web.

Other books

Bearly Breathing by Kim Fox
In the Eye of a Storm by Mary Mageau
Traitor's Masque by Kenley Davidson
Can You See Me? by Nikki Vale
The Hand-Me-Down Family by Winnie Griggs