Location paths

Patterns are a limited form of location path. The general form of a location path has therefore already been described above. The main features of a location path beyond those adopted in patterns are the ability to make steps in directions other than downward into the structure of the document, and the ability to begin the path at the current location:

To support the taking of steps in various directions, a number of additional keywords are needed beyond 'child::'. A further 12 keywords are available, allowing navigation to parents and higher-level ancestors, descendants below the level of children, and material that simply precedes or follows the current element.

The 'parent::' keyword selects the parent of the current node. As this is usually done simply to step back out of the node, as a preliminary step to moving elsewhere in the document, it is commonly used with the node() keyword ('parent::node()') in order successfully to match the parent, whatever node type it is or element name it has. Indeed, this is such a common requirement that there is a shorthand equivalent, '..', which should be familiar to users of some command-line operating systems. The location path '../title' selects a Title element that is a sibling of the current element. This is known as a relative path, as the target node selected by this expression actually depends on the location of the current node.

Note: Those familiar with the use of '..' (and '.', which is described below) from MS-DOS and UNIX operating systems should realize that the analogy with directory paths can be stretched too far. Operating systems always require that sibling directories have unique names, so that a path identifies a single target directory. XML documents have no such restriction, and so a location path will often match many target elements. For example, '//chapter/para', activated in the Book element template, will select every paragraph in every chapter, and '../title' may select more than one title.

The 'self::' keyword, followed by node(), identifies the current node. This can also be useful when specifying relative paths, particularly when the target node is a descendant of the current node but the number of intermediate levels is not known. In this scenario, the '//' instruction is needed; but if this appears at the start of an expression, it indicates a descendant of the root node, not the current node. Therefore, the current node needs to be the first part of the expression, as in 'self::node()//…'. As this is a common requirement, the single character '.' is used as an abbreviation for 'self::node()'. For example, the expression './/title' finds descendant Title elements of the current node. The XSLT function 'current()' can also be used but sometimes differs in meaning from '.' (see XSLT Extensions below).

The 'descendant-or-self::' keyword represents zero or more steps down into the document structure. When used with node(), this represents any number of intermediate objects (including none). If this concept seems familiar, it is because this is the longhand equivalent of '//'. The expression fragment '/descendant-or-self::node()/' means the same thing but is far more verbose. This step only makes sense when it precedes another step that is more specific, such as '//para', as the actual number of steps into the document structure taken varies, depending on how many are needed to reach the element specified in the next part of the path. The 'or-self' part of the name is significant, as it indicates that if the current node matches the following element name, then no actual step needs to be taken.

The 'descendant::' keyword is similar, but does not include the current node as a possible match. If the expression is 'descendant::para', and the current node is a Para element, this node will not be considered a match; it must contain another Para element for this test to succeed.

The 'ancestor::' and 'ancestor-or-self::' keywords work in the same way, but outwards from the current element instead of into its contents. For example, the expression 'ancestor::chapter' selects the chapter containing the current element.

The 'following-sibling::' and 'preceding-sibling::' keywords represent elements that follow or precede the current element within the parent element that they all share. To select the paragraphs that follow the current element, within the same parent, the expression 'following-sibling::para' is used. (Note that a count is maintained of the elements encountered in the direction taken. The significance of this is explained later.) Thus:

The 'preceding::' and 'following::' keywords are extensions of the sibling-specific versions described above. Preceding elements are all elements that have occurred before the current element, and have been closed before the current element has been opened (their end-tags occurring before this element's start-tag). Preceding siblings are included, but ancestors are therefore not included, because they are still open. Following elements are all elements that have not begun at the point of the current element, and so ancestors are again not included, but following siblings are:

The following example demonstrates the kind of path that can be built using these concepts. In this example, all elements that precede the title of each chapter are selected:

//child::chapter/child::title/preceding-sibling::*
   <book>
     <chapter>
       <author>J Smith</author>
       <title>Chapter One Title</title>
       ...
     </chapter>

     <chapter>
       <version>1.3</version>
					<date>12/4/2000</date>
       <title>Chapter Two Title</title>
       ...
     </chapter>
   </book>

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

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