Predicate filters

Location paths often select a number of elements. For example, consider the expression '/book/chapter/para'. When used in a Match pattern, all paragraphs in all chapters match the pattern. When used in a Select expression, all chapter paragraphs are selected. Often, especially in the latter scenario, the actual requirement is to locate a single element, or at least take into consideration factors beyond simple contextual location. A predicate filter can be added to 'filter out' unwanted nodes. Filters are expressions enclosed in square brackets, '[' and ']', which return a boolean value. When the value returned is 'true', the node is accepted; when the value returned is 'false', it is rejected. Only accepted nodes are retained and form the basis of the next step in the expression.

Numeric comparisons

The simplest kind of predicate filter is a numeric value. This value represents a specific sequential location in the list of matching nodes. For example, the expression '//chapter/para' may, in one particular chapter, identify 23 paragraphs. Paragraph '1' will be the first paragraph in the chapter, and paragraph '23' will be the last. By entering a value in the predicate filter, only the paragraph at that position is valid. The others are discarded. The following example therefore selects the fifth paragraph in the third chapter of the book:

/book/chapter[3]/para[5]
					

The expression 'following-sibling::*[2]' likewise selects the element after the element following the current element. However, the direction of the count is important, and not always immediately obvious. When taking a direction outward or backward ('ancestor::', 'ancestor-or-self::', 'preceding::' and 'preceding-sibling::'), the count is in reverse order. For example, 'preceding-sibling::*[1]' selects the element immediately before the current one (not the first element within their shared parent). The easy way to remember this is to appreciate that the value '1' will always be the element nearest to the starting point.

Expressions in filters

Filters can contain any expression. This is an important point because they are used in patterns, which are otherwise constrained to a limited subset of the expression language. Patterns are much more flexible when they include filters.

First, though, it should be understood that the placing of simple numeric values in filters is a shorthand version of the 'position()' function. The examples below are equivalent:

/book/chapter[3]/para[5]
/book/chapter[position() = 3]/para[position() = 5]

In the following example, paragraphs are only selected if they are in chapters that have no titles:

/book/chapter[not(title)]/para


   <book>
     <chapter>
       <para>No title in this chapter.</para>
     </chapter>
     <chapter>
       <title>Chapter With Title</title>
       <para>There is a title in this chapter.</para>
     </chapter>
   </book>

The shorthand version is provided because it is a common requirement to target a specific element by its contextual location (when it has no unique identifier), such as the fourth paragraph of the seventh section of the second chapter of the book:

match="/book/chapter[2]/section[7]/para[4]"

Multiple filters

More than one filter can be added to qualify a step in the expression:

						node[...][...]
					

Normally, this is not an essential feature as multiple expressions can be combined into a single expression using the 'and' operator. However, it is not possible to use numeric values for node positions within a filter that contains other tests. For example, while '[position() = 3 and not(title)]' is legal (the element is the third one, and does not contain a Title element), the shorthand version '[3 and not(title)]' is not allowed. Using separate filters overcomes this limitation:

[3][not(title)]

The order in which multiple filters are presented is very important. The examples below are not the same:

//chapter[3][not(title)]


//chapter[not(title)][3]

The reason why they mean different things is explained by the fact that the first filter is applied to create a subset list of matching nodes, and then the second one is applied to this subset. The first example selects the third chapter, then selects or eliminates this chapter depending on whether or not it contains a title. The second example selects all chapters that do not have a title, then selects the third of these chapters.

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

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