Complex location paths

Apart from the selection of children, it has already been shown that parents and further ancestors of the current element can also be selected. But there are many other options available, and each can be thought of as a direction, or an ' axis'. A particular axis is indicated using an 'axis specifier'. One axis specifier has already been seen; the 'child::' axis specifier selects the child axis.

Close family

Parents, children and siblings can be selected using the 'parent::', 'child::', 'preceding-sibling::' and 'following-sibling::' axis specifiers:



The ' parent::' prefix, along with the 'node()' function, is equivalent to '..':

.. /title

parent::node()/child::title

The reason for needing 'node()' here, instead of just '*', is to cater for the parent of the root element, which is not an element, but a node that represents the entire document.

Note that sibling elements are divided into those that appear before the context element, and those that appear after:



The counting order is important. Previous siblings are counted backwards from the context element. In the following example, the paragraph closest to the current paragraph is selected:

preceding-sibling::para[1]



Note

The meaning of the square brackets is explained later.


Following siblings are counted up from the context element. In the following example, the next Para element is selected:

following-sibling::para[1]



Ancestors and descendants

Ancestors and descendants can be searched for matching criteria using the ' ancestor::' and 'descendant::' axis keywords:



Note that descendants include children, not just lower levels in the hierarchy. Elements are also counted in 'breadth' order, meaning that, at each level, all sub-elements of one element are counted before going on to the next sibling of that element:



This can be seen as stepping through the elements in document order, as they would be encountered by a parser.

Ancestors are counted backwards up the hierarchy. Siblings of each ancestor element are ignored:



There is no abbreviated format for descendant and ancestor axis navigation. To select the title of the chapter containing the current element, the following verbose expression is required:

ancestor::chapter/title

Ancestors and descendants including current object

The current context node can be included in ancestor and descendant searching. The search works as described above, except that in both of these cases the context element itself is the first node in each list:



The ancestor-or-self:: axis is the same as the ancestor:: axis, except that the first ancestor is the current object.

The ' descendant-or-self::' axis is used to select all descendant nodes, including the original context node itself. It is therefore equivalent to '//', as the following examples demonstrate:

chapter//para

child::chapter/descendant-or-self::node()/child::para

Note the presence of the 'node()' function in the second step above. It is necessary to specify any constraints on what class of node is acceptable, and here there is no desire to rule out anything. As already stated, the 'node()' function is even less discriminatory than '*', particularly because it includes the document root node (which is not an element node).

Remaining axis specifiers

Finally, there are some axis specifiers that select the current object, its attributes, all preceding and all following objects:



Self axis

The current context node itself can be selected using 'self::'. As the current object may be an element, or the node representing the entire document, the node test should again be 'node()'. This is equivalent to the '.' operator. It can now be seen that the verbose equivalent of the following expression is in fact very verbose:

.//para

self::node()/descendant-or-self::node()/child::para

First, the 'self::node()' step is used to identify the current element (or root node) as the starting point. Second, the 'descendant-or-self::' step is used to indicate that all descendants, and the current node itself, are to be selected (and again, the node() function is used just in case the current node at any point is not an element). Third, the 'child::' step is used to indicate which children of these objects are to be selected:

Attribute axis

The attributes of the context node can be selected using ' attribute::'. This is equivalent to '@'.

Preceding and following axis

The preceding:: axis takes a flattened view of the document, and provides access to all elements that occur, and are completed, before the context element begins (thus eliminating ancestors of the context element):



The following:: axis provides the same service for the remainder of the document, only counting elements that begin after the current element ends, so ignoring all ancestors and descendants of that element:



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

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