What Is XPath, Anyway?

XPath is a general-purpose query language for addressing and filtering both the elements and the text of an XML document. As the name suggests, the XPath notation is basically declarative. A valid XPath expression looks like a path to a particular set of nodes or a value excerpted from the source document.

XPath works on top of a tree-based representation of the source document. The path expresses a node pattern using a notation that emphasizes the hierarchical relationship between the nodes. Although semantically speaking the closest similarity is with the SQL query language, from a syntax point of view, XPath expressions look a lot like a file system path composed of folder and file names. For example, consider the following simple XPath expression:

customer/address

This expression states: find all the address nodes that happen to be children of the customer element. But on which nodes is this expression evaluated? An XPath expression is always evaluated in the context of a node. The context node is designated by the application and represents the starting point of the query. Expressing the concept of the context node in terms of file system paths, we could say that the appropriate file system counterpart for the context node is the current directory.

The nodes affected by the expression form the context node-set. The final set of nodes that is actually returned to the application is a subset of the context node-set that includes only those nodes that match the specified criteria.

Context of XPath Queries

The context of an XPath query includes, but is not limited to, a context node and a context node-set. The XPath context also contains position and namespace information, variable bindings, and a standard library of functions. We’ll look at the contents of the XPath context in detail in this section.

In the .NET Framework, the context node is the XmlNode object on which you call either the SelectNodes or the SelectSingleNode method. The context node-set is determined by the so-called axis of the query. The axis is a keyword that specifies the group of nodes that will then be filtered out by the XPath expression.

XPath Axes

Continuing with the file system parallel, the axis is similar to the drive information in a file system path. Like the drive identifier, axis information is not strictly necessary, and a default value can be assumed if the axis is omitted.

If an XPath query has no axis element, the context node-set contains the direct children of the context node. As with drives, when specified, an axis defines the entire set of nodes that the following path will evaluate. Table 6-1 lists the available axes.

Table 6-1. XPath Axes
Axis Description Context Node-Set
self The context node. 7
child Children of the context node. 8, 9
parent Parent of the context node. 5
descendant Nodes in the subtree rooted in the context node. The variant descendant-or-self adds the context node to the set. 8, 9, 10
ancestor Parent of the context node and then parent’s parent, up to the document root. The variant ancestor-or-self adds the context node to the set. 5, 1
Following All the nodes that will be visited after the context node. The XPath specification dictates that the document be visited in depth-first order, going as deep as possible on a path. > 7
following-sibling Following sibling nodes of the context node. 11
Preceding All the nodes already visited according to the standard algorithm. < 7
preceding-sibling Preceding sibling of the context node. 6

The context node-set numbers in Table 6-1 refer to the XML tree in Figure 6-1 and indicate the nodes that would form the corresponding node-set once a given axis is specified. The context node is labeled 7.

Figure 6-1. A sample XML tree in which the node numbers indicate the order in which nodes are visited by the XPath query processor.


The XPath specification requires that the nodes be visited in depth-first order, starting from the root and then proceeding with all the children from left to right until a leaf is found. This order corresponds to the order in which nodes are read from an XML disk file.

Position Information

An XPath context is characterized by a position and a size. The position attribute is a one-based value that indicates the ordinal position of the context node in the context node-set to which it belongs. The size attribute, on the other hand, returns the size of the context node-set—that is, the number of nodes being processed by the expression. The number does not necessarily match the size of the final node-set returned to the caller application.

XPath and Namespaces

The XPath processor uses node information to determine whether a match exists with the current expression. The most important information used by XPath expressions is the node’s name, type, and attributes. XPath fully supports XML namespaces and splits the name of a node into two constituent parts: the namespace URI and the local name. The set of namespaces declared in scope for the context node is used to qualify node names in the expression.

Variable Bindings

An XPath expression can contain variable references that are resolved through a set of in-memory bindings established between variable names and actual values. Each variable holds a value whose type is normally one of the four base types—node-set, string, Boolean, and number. It is still possible, however, for a variable reference to contain a value of some other type.

XPath Functions

Any implementation of the XPath parser must provide a function library that is used to evaluate expressions. Functions in the core library have no namespace information, but extension functions can have a namespace. Extension functions are defined within vendor-specific XPath implementations but can also be provided by specialized and XPath-based programming APIs such as XSLT and XML Pointer Language (XPointer) APIs.

The functions in the XPath core library work on the base XPath types: node-set, Boolean, string, and number. Type conversion is automatically performed whenever possible. The only type conversion not permitted is from any other type to node-sets. Table 6-2 lists just the commonly used functions included in the library.

Table 6-2. Some Members of the XPath Core Library
Function Description
last A node-set function that returns the number of nodes in the current node-set
name A node-set function that returns the fully qualified name of the specified node
text A node-set function that returns the text of the specified node
position A node-set function that returns the index of the context node in the current node-set
boolean A Boolean function that converts a value to a Boolean
contains A string function that indicates whether a string contains the specified substring
substring A string function that returns the specified substring
starts-with A string function that indicates whether the string begins with a given substring
ceiling A number function that rounds a number up to the next integer
floor A number function that rounds a number down to the next integer
round A number function that rounds a number to the nearest integer

You will likely use the node-set functions most often. While being processed, an XPath expression is tokenized into subexpressions, and each subexpression is individually evaluated. The XPath processor is passed the subexpression and the context node-set. It returns a possibly narrowed node-set that will be iteratively used as the input argument for the next subexpression. During this process, the context node, position, and size can vary, whereas variable and function references as well as namespace declarations remain intact.

Location Paths

As mentioned, an XPath expression can return any of the following types: Boolean, string, number, or node-set. In most cases, however, it will return a set of nodes. The most frequently used type of XPath expression is the location path.

A location path looks a lot like a file system path and, like a file system path, can be either absolute or relative to the context node. When absolute, a location path begins with the forward slash (/). The following expression, for example, locates all the <invoice> nodes, irrespective of the node on which the expression is evaluated.

/archive/invoices/invoice

In contrast, this expression attempts to retrieve the nodes at the end of a particular path that starts from the current node:

archive/invoices/invoice

Unabbreviated Syntax for a Location Path

A fully qualified location path consists of three pieces: an optional axis, a node test, and an optional predicate. The axis information defines the initial context node-set for the expression, whereas the node test is a sequence of node names that identifies a path in the node-set. The predicate is a logical expression that defines the criteria to filter the current node-set.

If the location path lacks any of its optional components, it is said to be in abbreviated form. The general, unabbreviated, syntax for a location path expression is shown here:

axis::node-test[predicate]

The syntax dictates that the axis be separated from the rest of the expression by a double colon (::). This special separator once again recalls the parallel between axis information and drive information in a file system. The predicate is enclosed in square brackets. A location path can include multiple predicates that are written one after another like indexes in a multidimensional array.

The node test is a node-based expression that is evaluated for each node in the context node-set. If the expression returns true, the node remains in the node-set; otherwise, it is removed. Typically, the node test takes the form of a path. Read as an expression, it returns true if the specified path exists below the context node and false otherwise. The following code demonstrates a fully qualified XPath location:

descendant::invoice[@year = 2002]

The XPath processor first selects all the descendants of the context node. Next it selects from this set all the <invoice> nodes whose year attribute equals 2002.

Tip

You can use the wildcard character (*) to indicate all the nodes in a given axis. For example, the expression child::* denotes all the children of the current context node. Likewise, descendant-or-self::* means all the descendants and the node itself.


Location Steps

A location path is composed of several child elements called location steps. Each location step is actually a location path and, as such, can be expressed in an abbreviated or fully qualified form, as appropriate. Location steps are separated by forward slashes, as shown in Figure 6-2.

Figure 6-2. A location path consists of one or more location steps, each of which can be expressed in full or abbreviated form.


Consider the following three-step expression:

invoices/descendant::invoice[@year = 2002]/child::country[text() = ’USA’]

The first step selects all the nodes named <invoices> below the context node. This node-set is then passed as the context node-set to the next location step. The second location step is expressed in an unabbreviated form and loops through all the descendants of each previously selected <invoices> node. When processed, each node plays the role of the context node and provides different position information. At the end of the second step, the node-set contains only the <invoice> nodes that have a parent <invoices> and a year attribute set to 2002.

The final step further narrows the node-set by excluding all the nodes that have no <country> child whose text equals USA.

Note

The at sign (@) that you use to indicate a node attribute is actually an abbreviation for another particular axis type: the attribute. The full syntax for the year attribute is attribute::year. The XPath specification recommends a number of abbreviations that are commonly used in coding, including the following shortcuts: Use a period (.) to indicate the context node and two periods (..) to refer to the parent. When no axis is specified, child:: is assumed. Finally, [n] means the nth node in the current context node-set; this array-like notation is equivalent to [position() = n].


Links Between Documents

The XPath query language is used to select a set of nodes in a given XML document. You typically use XPath to search for nodes in an XML DOM implementation of a data source and to filter the nodes to which a given transformation template in an XSL script must be applied.

Recently, another possible use for the XPath syntax has boldly emerged. I’m talking about XPointer, which is designed to become the standard way to link portions of external documents to XML documents.

What Is XPointer?

XPointer is used to locate data within an XML document. When XML documents need to point to external resources, they can declare an entity reference or, more effectively, include the whole resource, using the XML Inclusion (XInclude) syntax. XInclude—a W3C recommendation candidate—links the host document to an external resource, or a portion of it. XPointer defines the syntax you use to specify the addressed portion of the document.

Normally, to indicate a particular position in an XML document, you attach a fragment identifier to the document’s URL. A fragment identifier is marked by a number sign (#) and follows the document’s URL. For example, the URL http://www.w3.org/TR/xptr/#conformance points to the portion of the document labeled with the conformance name.

With XPointer, you can use the XPath syntax to identify with greater flexibility a particular location in the external document.

How XPointer Uses XPath

An XPointer fragment identifier can be the name of a particular portion of the target document, but it could also be a more complex and expressive XPath query. For example, you could link a piece of information using the following syntax:

invoices.xml#xpointer(/descendant::invoice[@id=201])

This expression references the particular descendant node named <invoice> having an id attribute equal to 201.

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

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