How is "at" used in XQuery to find the position of a node?

976 Views Asked by At

Where and how is $p defined or created from? Why is it the index or position of the node at all?


Input from w3schools, the bookstore example.

output:

<book category="children">
  <title lang="en">Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
  <price>29.99</price>
</book>

query:

xquery version "3.1";

let $doc := db:open("bookstore")
let $books := $doc/bookstore/book

for $book at $p in $books 
where $p eq 2

return $book

It's the "at" which assigns an index to $p? yet, my understanding is that xpath is declarative and not iterative. Yet, this at least resembles iteration. The "at" is not iteration, perhaps, but just the position of that node within that document?

see also:

C# What query language to specify in rule to pull out the two book nodes

for a related question.

3

There are 3 best solutions below

0
On

See the W3.org XQuery 3.1 ref section 3.12.2 For Clause

In an explicit iteration using the for ··· in construct:

for $v [at $p] in e1
return e2

on positional variables:

Definition: A positional variable is a variable that is preceded by the keyword at.] A positional variable may be associated with a variable that is bound in a for clause. In this case, as the main variable iterates over the items in its binding sequence, the positional variable iterates over the integers that represent the ordinal numbers of these items in the binding sequence, starting with one. Each tuple in the output tuple stream contains bindings for both the main variable and the positional variable. If the binding sequence is empty and allowing empty is specified, the positional variable in the output tuple is bound to the integer zero. Positional variables always have the implied type xs:integer. The expanded QName of a positional variable must be distinct from the expanded QName of the main variable with which it is associated [err:XQST0089].

The following examples illustrate how a positional variable would have affected the results of the previous examples that generated tuples:

Initial clause:

for $x at $i in (100, 200, 300)

Output tuple stream:

($x = 100, $i = 1)
($x = 200, $i = 2)
($x = 300, $i = 3)

So, yes, at $p in an explicit iteration creates the variable and it can be $i or whatever too. (An the index is 1 based as usual in XPath).

0
On

It might resemble iteration, but it's purely functional. It's a mapping operation in which (conceptually) a function is called to process each item in the input sequence; the function is called with two parameters, $x being the item that's being processed and $p being its position in the sequence. The order of processing isn't defined - the items might all be processed in parallel, or in reverse order, for all you know.

0
On

XQuery (and XPATH 2.0+, and XSLT 2.0+) data model is based on ORDERED sequences.

The $p is a position of $x in a sequence

Check it out below to see and feel it.

<root>
{
  for $x at $p in (10 to 20)
  where $x mod 2
  return <r pos='{$p}' value='{$x}' />
}
</root>

Output

<root>
  <r pos="2" value="11"/>
  <r pos="4" value="13"/>
  <r pos="6" value="15"/>
  <r pos="8" value="17"/>
  <r pos="10" value="19"/>
</root>