7

I was trying my hands on XPath for python-selenium.

I used this link for trying some XPaths' from tutorials:

So I tried these two variants of XPaths'.

  1. This expression

    //webengagedata//preceding-sibling::*
    

returned 14 results

  1. And this expression

    //webengagedata/preceding-sibling::*
    

returned 9 results

What does the "//" do to match 5 more results?

kjhughes
  • 106,133
  • 27
  • 181
  • 240
Prasanth
  • 81
  • 1
  • 6
  • 2
    This is a great question, except for the off-site link. (Questions should endeavor to present a *[mcve]* that will remain useful even if off-site resources change.) See [**my answer below that**](http://stackoverflow.com/a/43100904/290085) covers the concepts without dependence on any off-site resources. Thanks. – kjhughes Mar 29 '17 at 19:09

4 Answers4

15

/ vs // in general

Both child (/) and descendant-or-self (//) are axes in XPath.

  • / is short for /child::node()/.

    Use / to select a node's immediate children.

  • // is short for /descendant-or-self::node()/.

    Use // to select a node, its children, its grandchildren, and so on recursively.


/ vs // with preceding-sibling::*

Your specific question asks about the difference between //preceding-sibling::* and /preceding-sibling::*.

Since your data is offsite and complex, let's consider instead this present and simpler XML:

<r>
  <a/>
  <b>
    <c/>
    <d/>
  </b>
</r>

For this XML,

  1. /r/preceding-sibling::* selects nothing because r has no preceding siblings.
  2. /r//preceding-sibling::* selects the preceding siblings elements of all of the descendant or self nodes of r. That is, a, b, c and d. (Remember, /r//preceding-sibling::* is short for /descendant-or-self::node()/preceding-sibling::*, not /descendant-or-self::*/preceding-sibling::*) Note that even though b and d are predecessor siblings to no elements, they are predecessor siblings to text nodes because the above XML has whitespace after b and d. If all whitespace were removed, then only a and c would be selected.
  3. /r/descendant::*/preceding-sibling::* selects the preceding sibling elements of all descendant elements of r. That is, a and c. Note that b and d are not selected because they are not preceding sibling elements to any descendant elements of r -- unlike the previous example, text nodes do not qualify.
kjhughes
  • 106,133
  • 27
  • 181
  • 240
  • I am able get an hold of 1 and 2. I am still confused with one small thing about descendants. Isn't descendant::* used to get all the child or sub-child nodes of the context node? If yes, shouldn't /r/descendant::*/preceding-sibling::* return all the child nodes a and b and the sub-child nodes c and d? – Prasanth Mar 30 '17 at 09:56
  • @Prasanth, I have update the question to properly address your very insightful follow-up question, which made me realize a mistake in my explanation. Thank you. – kjhughes Mar 30 '17 at 13:38
  • Oh, this is great. I was in an assumption that the output from `/descendant::*` will give `a` **'b'** `c` `d`, where `b` will not include its childs `c` and `d` as part of the output. But `b` element as a whole will be presented with its child `c` and `d` ` \n and hence the `preceding-element` --> `c`. Thank you so much **for your patience** and making me feel comfortable on answering my noob questions. This is my first question in stackoverflow, now I realize I am late to this beautiful world. Cheers. – Prasanth Mar 30 '17 at 16:29
1

For your example

//webengagedata/preceding-sibling::* ---> returned 9 results

Because there are only 9 tags which are exact sibling of webengagedatatags thats why it is showing 9 records

//webengagedata//preceding-sibling::* ---> returned 14 results

Here it is considering child tags as well as biziclop said x/descendant-or-self::node()/y

NarendraR
  • 7,577
  • 10
  • 44
  • 82
0

The difference is that x//y is shorthand for x/descendant-or-self::node()/y.

That's all.

So while the first query selects all the descendants of <webengagedata> that have another tag after them, the second only selects the preceding siblings of the tag itself.

The rules of abbreviated xpath syntax are explained here.

biziclop
  • 48,926
  • 12
  • 77
  • 104
  • Please tell me if this is right.. //webengage//preceding-sibling::* = //webengage//child::* + //webengage/preceding-sibling::* – Prasanth Mar 29 '17 at 18:15
-1

difference between '/' and '//' in xpath is , '/' using for identify the elements in that region of area , '//' is for entire page after the condition