Recipe 1.3. Working with Sequences
Problem
You want to manipulate collections
of arbitrary nodes and atomic values derived from an XML document or
documents.
Solution
XPath 1.0
There is no notion of sequence in XPath 1.0 and hence these recipes
are largely inapplicable. XPath 1.0 has node sets. There is an
idiomatic way to construct the empty node sets using XSLT 1.0.
(: The empty node set :)
/..
XPath 2.0
(: The empty sequence constructor. :)
( )
(: Sequence consisting of the single atomic item 1. :)
1
(: Use the comma operator to construct a sequence. Here we build a sequence
of all X children of the context, followed by Y children, followed by Z children. :)
X, Y, Z
(: Use the to operator to construct ranges. :)
1 to 10
(: Here we combine comma with several ranges. :)
1 to 10, 100 to 110, 17, 19, 23
(: Variables and functions can be used as well. :)
1 to $x
1 to count(para)
(: Sequences do not nest so the following two sequences are the same. :)
((1,2,3), (4,5, (6,7), 8, 9, 10))
1,2,3,4,5,6,7,8,9,10
(: The to operator cannot create a decreasing sequence directly. :)
10 to 1 (: This sequence is empty! :)
(: You can accomplish the intended effect with the following. :)
for $n in 1 to 10 return 11 - $n
(: Remove duplicates from a sequence. :)
distinct-values($seq)
(: Return the size of a sequence. :)
count($seq)
(: Test if a sequence is empty. :)
empty($seq) (: prefer over count($seq) eq 0 :)
(: Locate the positions of an item in a sequence. Index-of produces a sequence
of integers for every item in the first arg that is eq to the second. :)
index-of($seq, $item)
(: Extract subsequences. :)
(: Up to 3 items from $seq, starting with the second. :)
subsequence($seq, 2, 3)
(: All items from $seq at position 3 to the end of the sequence. :)
subsequence($seq, 3)
(: Insert a sequence, $seq2, before the 3rd item in an input sequence, $seq1. :)
insert-before($seq1, 3, $seq2)
(: Construct a new sequence that contains all the items of $seq except the 3rd. :)
remove($seq1, 3)
(: If you need to remove several elements, you might consider an expression like the following. :)
$seq1[not(position( ) = (1,3,5))]
$seq1[position( ) gt 3 and position( ) lt 7]
Discussion
In XPath 2.0, every data item (value) is a sequence. Thus, the atomic
value 1 is just as much a sequence as the result of the expression (1
to 10). Another way of saying this is that every XPath 2.0 expression
evaluates to a sequence. A sequence can contain from zero or more
values, and these values can be nodes, atomic values, or mixtures of
each. Order is significant when comparing sequences. You refer to the
individual items of a sequence starting at position 1 (not 0, as
someone with a C/Java background might expect).
XPath 1.0 does not have sequences but rather node sets. Node sets are
not as tidy a concept as sequence, but in many cases, the distinction
is irrelevant. For example, any XPath 1.0 expression that use the
functions count( ) and empty( ) should behave the same in 2.0. The
advantage of XPath 2.0 is that a sequence is a first class construct
that can be explicitly constructed and manipulated using a variety of
new XPath 2.0 functions. The recipes in this section introduce many
important sequence idioms, and you will find many others
sprinkled
through
the recipes of this book.
|