92

My sample input XML is:

<root>
 <a>
   <b>item</b>
   <b>item1</b>
   <b>item2</b>
   <b>item3</b>
   <b>item4</b>
 </a>
</root>

I am suppose to select a node b whose position is the value of a variable.

How can I use the value of a variable to test the position of a node?

John Smith
  • 7,243
  • 6
  • 49
  • 61
IordanTanev
  • 6,130
  • 5
  • 40
  • 49

2 Answers2

117

you can use this:

/root/a/b[position()=$variable]

position() is 1 based

http://saxon.sourceforge.net/saxon6.5.3/expressions.html

remi bourgarel
  • 9,231
  • 4
  • 40
  • 73
69

The following should work:

/root/a/b[2]

And if it doesn't, try:

/root/a/b[position()=2]
Ronald Wildenberg
  • 31,634
  • 14
  • 90
  • 133
  • 2
    I came here to find the difference between these two, could you please explain how they are different? – Andre Jan 07 '16 at 11:14
  • 14
    `position()` refers to the position in the dom [2] refers to the second result in the list of results. – Becky Conning Jul 01 '16 at 10:19
  • 2
    @Andre. When used inside a `for-each` loop `select` statement, they are the same. When `position()` is used within the loop itself, it refers to the result set. The `[n]` format only works as a shorthand because it is the only conditional inside the `[ ]` block, otherwise `position()` must be used, as in `//a[(@id="xx") and (position()=3)]`, which is "any fifth link that has an `id` of xx". – Patanjali Jan 14 '19 at 06:46
  • @Patanjali That is confusing - links with the position() of 3 are the 5th links? It seems to me [2] could be used instead of :nth-of-type(2), while [position()=2] would be the equivalent of :nth-child(2) then? I guess we need a couple of examples to clear the fog. – bitoolean Aug 11 '19 at 11:04
  • @Patanjali I think I understood the part about it being a shorthand now that I've tested it and it does only give me the "item1" by running `\\*[2]` and `\\*[position()=2]` against the question's XML. Thank you! – bitoolean Aug 11 '19 at 20:55
  • @bitoolean. Sorry, yes it should be 'third'. `[2]` is the shorthand for `[position()=2]`. Note that `//*[2]` or `//*[position())=2]` is the equivalent of `*:nth-child(2)`, but `//*[name()='a'][2]` is the equivalent of `a:nth-of-type[2]`, the latter saying select the second element of name 'a'. That is, each successive `[]` is executed on the result set from the immediately preceding `[]`. – Patanjali Aug 12 '19 at 14:25
  • 1
    @BeckyConning They are exactly the same thing. See https://www.w3.org/TR/1999/REC-xpath-19991116/#predicates : A PredicateExpr is evaluated by evaluating the Expr and converting the result to a boolean. If the result is a number, the result will be converted to true if the number is equal to the context position and will be converted to false otherwise; if the result is not a number, then the result will be converted as if by a call to the boolean function. Thus a location path para[3] is equivalent to para[position()=3]. – SleepyBag Jun 08 '22 at 14:34