You are reading O'Reilly XForms Essentials by Micah Dubinko. (What is this?) - Buy XForms Essentials Online

Location Paths

A key requirement for dissecting nearly any XPath expression is an understanding of Location Paths, which select one or more nodes based on their location or other properties. A Location Path consists of a number of individual Location Steps, each separated by a slash (/). Each individual step builds upon the previous steps to traverse the document, and can be a test against the name of a node, or one of the following special tests:

Another special test is *, which will match any element node (or attribute node within the attribute axis, or namespace node within the namespace axis.) Similarly, another special test prefix:* will match any node identified with the namespace mapped to prefix.

Figure 3.2, “Location paths and steps” illustrates how a path is traversed in steps, from left to right.

<purchaseOrder xmlns="http://po.example.org">
  <items>
    <item/>
    <item/>
    <item/>
  </items>
</purchaseOrder>
<xforms:bind nodeset="po:purchaseOrder/po:items/po:item" xmlns:po="http://po.example.org"/>

Each Location Step includes an axis, which is an instruction on how to navigate the tree structure. Since XPath is a general-purpose language, there are many axes that don't make much sense for XForms, but Table 3.1, “XPath axes ” summarizes all of them for completeness.

Table 3.1. XPath axes

Axis name

Description

child

Contains the children of the context node. (As a consequence, this axis never contains attribute or namespace nodes.)

attribute

Contains the attributes of the context node. (As a consequence, this axis is always empty, unless the context node is an element.)

parent

Contains the parent of the context node. (As a consequence, this axis is always empty when the context node is the root node.)

descendant

Contains the descendants of the context node; a descendant is a child or a child of a child and so on. (As a consequence, this axis never contains attribute or namespace nodes.)

descendant-or-self

Contains the context node and the descendants of the context node. (As a consequence, this axis never contains attribute or namespace nodes.)

ancestor

Contains the ancestors of the context node; the ancestors of the context node consist of the parent of context node and the parent's parent and so on. (As a consequence, this axis always includes the root node, unless the context node itself is the root node.)

ancestor-or-self

Contains the context node and the ancestors of the context node. (As a consequence, this axis always includes the root node.)

following

Contains all nodes in the same document as the context node that are after the context node in document order, excluding any descendants and excluding attribute nodes and namespace nodes.

following-sibling

Contains all the following siblings of the context node. (As a consequence, this axis is always empty when the context node is an attribute node or a namespace node.)

preceding

Contains all nodes in the same document as the context node that are before the context node in document order, excluding any ancestors and excluding attribute nodes and namespace nodes.

preceding-sibling

Contains all the preceding siblings of the context node. (As a consequence, this axis is always empty when the context node is an attribute node or a namespace node.)

namespace

Contains the namespace nodes of the context node. (As a consequence, this axis is always empty unless the context node is an element.)

self

Contains just the context node itself.

A bare Location Path expression selects every node that matches the path it specifies. For example, the expression html/body/p selects every p element that's a direct child of body. Often, it is desirable to filter down the selection even more. In XPath, this is done through a predicate, which appears in square brackets and can apply to any Location Step in a Location Path. To select only the first p from the earlier example, the expression would be /html/body/p[position( )=1], or, even shorter, /html/body/p[1].

The predicate expression evaluates to a true or false result (or a number that is special-cased as a comparison against position( )). The way this works is:

Multiple predicates can be specified on any given step, which will result in multiple layers of filtering on the node-set. If a node-set gets filtered down to nothing, no error results—the expression simply returns an empty node-set. Figure 3.3, “Node-set filtering with predicates” illustrates how filtering works through predicates.