Reputation: 267
Could someone break down what this Xquery is doing?
'for $i in . return count(../*[. << $i])'
I can tell it is a for loop, but I am confused by the ../*
and the []
. It is in this SQL code that I'm working on. I am trying to extract column-name nodes from an XML file:
SELECT distinct
Parent.Items.value('for $i in . return count(../*[. << $i])', 'int') as [Index],
Parent.Items.value('local-name(../.)', 'varchar(100)') as 'ParentItem',
Parent.Items.value('local-name(.)', 'varchar(100)') as 'ChildItem'
FROM dbo.MyFormResults
CROSS APPLY xmlformfields.nodes('/form/*') as Parent(Items)
I want this Xquery to iterate through my XML nodes in the order they are in my XML file. It sort of works, but it double counts and I'm not sure why... maybe if i understand this loop better I can fix my problem.
As you can see here Indexes: 15, 16 and 17 are duplicated.
Thanks!
Upvotes: 0
Views: 106
Reputation: 122364
for $i in .
A for $x in y return z
expression assigns the variable $x
to each item in the sequence y
in turn and evaluates the expression z
, returning a sequence which is the concatenation of all the results from the evaluations of z
, e.g. for $i in (1, 2, 3) return (2 * $i)
would generate the sequence (2, 4, 6)
.
In this case the sequence y
is just a single node - it's an idiom to capture the current value of .
in a variable so you can make use of it in deeper predicates, as an alternative to the XSLT current()
function when you're working with XPath 2.0 outside of XSLT.
../*[. << $i]
the <<
operator tests the relative position of nodes, x << y
is true if x
comes before y
in document order.
Therefore for $i in . return count(../*[. << $i])
is simply a long-winded way of writing count(preceding-sibling::*)
- the number of sibling elements of the current node (.
, which is also known as $y
) that come before that node in document order.
Upvotes: 3