Finding node order in XML document in SQL Server

You can emulate the position() function by counting the number of sibling nodes preceding each node:

SELECT
    code = value.value('@code', 'int'),
    parent_code = value.value('../@code', 'int'),
    ord = value.value('for $i in . return count(../*[. << $i]) + 1', 'int')
FROM @Xml.nodes('//value') AS T(value)

Here is the result set:

code   parent_code  ord
----   -----------  ---
1      NULL         1
11     1            1
111    11           1
12     1            2
121    12           1
1211   121          1
1212   121          2

How it works:

  • The for $i in . clause defines a variable named $i that contains the current node (.). This is basically a hack to work around XQuery’s lack of an XSLT-like current() function.
  • The ../* expression selects all siblings (children of the parent) of the current node.
  • The [. << $i] predicate filters the list of siblings to those that precede (<<) the current node ($i).
  • We count() the number of preceding siblings and then add 1 to get the position. That way the first node (which has no preceding siblings) is assigned a position of 1.

Leave a Comment