2

I have an XML like this

<root>
<el id="1" value="3"/>
<el id="2" value="3"/>
<el id="3" value="4"/>
<el id="4" value="4"/>
<el id="5" value="4"/>
<el id="6" value="4"/>
</root>

I'd like with one xpath (I'm in a c# context not an xslt template) get the 2 first element with a value of 4 ie

<el id="3" value="4"/>
<el id="4" value="4"/>

with /root/el[position() <= 2 and @value=4] I'd get 0 element because position() is based on the parent node, not the current subset.

I can do this in c# but it seems useless to load 1200 node when I only need 20.

Thanks

smci
  • 32,567
  • 20
  • 113
  • 146
remi bourgarel
  • 9,231
  • 4
  • 40
  • 73

2 Answers2

4

The following works for me in an XSLT script;

  <xsl:template match="/">
    <xsl:apply-templates select="/root/el[@value=4][position()&lt;=2]" />
  </xsl:template>

The result is id's 3 and 4, so the XPATH /root/el[@value=4][position()&lt;=2] should work for you.

rsp
  • 23,135
  • 6
  • 55
  • 69
2

The answer by @rsp is correct, but I'd like to add an explanation. It's not always true that [cond1 and cond2] is equivalent to [cond1][cond2]. You need the second form.

Your expression:

/root/el[position() <= 2 and @value=4]

...selects all el elements that have a value attribute equal to 4 and whose position is less than or equal to 2. There are no such elements in your document.

You want:

/root/el[@value=4][position() <= 2]

...which first selects all el elements that have a value attribute equal to 4 and then filters that list by position, as desired.

Wayne
  • 59,728
  • 15
  • 131
  • 126
  • @remi - Yes, I know. I just wanted to provide an explanation. – Wayne May 05 '11 at 15:27
  • @lwburk: The XPath expression in your answer selects nothing and doesn't select what the OP has specified as wanted. The answer by @rsp is correct. I am downvoting this answer due to it being incorrect. In the future, please try to test your answers before posting them. – Dimitre Novatchev May 06 '11 at 02:08
  • @Dimitre - Except for the encoding of the less-than due to @rsp's answer being in XSLT -- which wasn't asked for -- my answer is exactly the same as @rsp's. The main difference is that @rsp's answer says "works for me" while mine provides an actual explanation. I'll give you the benefit of the doubt, but please try not to be so hasty. You just compared two answers that are exactly the same and called one of them wrong and one right. – Wayne May 06 '11 at 17:46
  • 1
    @Dimitre - Re-reading, I think you're just confused and think that the first expression in my answer is the one I'm endorsing. It's not. I was pointing out that the *second* expression -- the one that's the same as @rsp's -- is correct and the *first* one is not. A lot of people think that conjunction with `and` is equivalent to multiple predicates. I was trying to explain explicitly why this is not the case. I'll take some blame for not writing more clearly -- the writer's creed, after all, is to be understood -- but I think your tone could use some work. – Wayne May 06 '11 at 18:00
  • @lwburk: Sorry, if my tone reflected the frustration that an experienced contributor posted a wrong answer. Please, edit and correct. It is natural to conclude, in the absense of any statement to the contrary, that the first expression is offered as the correct solution and that it is contrasted to the second expression, which is considered wrong. Even if one decides to make no such conclusions, an answer that does not say clearly what is the proposed (correct) solution, is not helpful. When you edit and correct your answer I will be glad to cancel my downvote. – Dimitre Novatchev May 06 '11 at 18:17
  • @Dimitre - My time here is wasted if I'm not clear, so, while repeating that my answer was not in fact wrong, I'm happy to edit to make that apparent. Done. – Wayne May 06 '11 at 18:37
  • @lwburk: Completely agree. The downvote is now reversed. Glad that it was useful. :) – Dimitre Novatchev May 06 '11 at 18:39