-1

Let's say I have this HTML

<div class="item-wrapper">
 <div>
  <h6>My Header 1</h6>              
 <div>
 <div>
  <div>
   <label>
    <input type="checkbox" />
    <span class="class1">Text 2</span>       
    <span class="class2"></span>
   </label>
  <div>
 </div>
</div>
<div class="item-wrapper">
 <div>
  <h6>My Header 2</h6>              
 <div>
 <div>
  <div>
   <label>
    <input type="checkbox" />
    <span class="class1">Text 2</span>       
    <span class="class2"></span>
   </label>
  <div>
 </div>
</div>

How do I get to any child to the common parent, i.e. <div class="item-wrapper">? In this case, the attribute is the class. However, the attribute could be anything that can identify the common ancestor.

var xPathToAncestor = "ancestor::div[@class='item-wrapper']";
var ancestor = child.FindElement(By.XPath(xPathToAncestor)

I've tried so many combinations //ancestor::div[@class='item-wrapper'], .//ancestor::div[@class='item-wrapper'], but nothing is working.

Richard77
  • 20,343
  • 46
  • 150
  • 252
  • Which _child_ are you looking at with respect to the ancestor `
    `?
    – undetected Selenium Jan 02 '21 at 08:10
  • 1
    One problem is that you need to be specific as to which two (or more elements) you want to find a common ancestor of. If you choose the INPUT or the SPANs, the common ancestor is the LABEL, and so on. You can't find a "common" ancestor with just one element. – JeffC Jan 02 '21 at 21:43
  • @JeffC, that's a good point. That's why I said "any parent" because I want it to be a placeholder. All I need is a working code so that I can replace the above xpath with to string variables. The above code is just to illustrate what I'm looking for. – Richard77 Jan 02 '21 at 22:25
  • @Richard77 the question content says "How do I get to any child to the common parent, i.e.
    ? " and answers are for that . Update ypur question
    – PDHide Jan 03 '21 at 03:34
  • //span/ancestor::div[@class="item-wrapper"] but also added answer to find a parent , this locator finds div element which is a parent of span tag – PDHide Jan 03 '21 at 03:43
  • 1
    I think there's a lot of confusion with your question. In it you ask, "How do I get **TO** any child to the common parent?" I think you typo'd there and meant to state, "How do I get **FROM** any child to the common parent? Is that correct? If so, would you please update your question? Some more examples might help clarify also. – JeffC Jan 04 '21 at 04:54
  • @Richard77 if this what you wanted to then just use `var xPathToAncestor = "./ancestor::div[@class='item-wrapper']";` see the '.' infront it says the child is the context node . That will fix your issue. I have added that to my answer as well – PDHide Jan 04 '21 at 05:26

3 Answers3

0

you can use

//div[@class='item-wrapper']//span

this find span tags which are a direct and indirect child

To find direct child

//div[@class='item-wrapper']/span

How to use ancestor:

//ancestor::div[@class="item-wrapper"]

This finds an element with tag div and class item-wrapper , and is a parent of any child

//span/ancestor::div[@class="item-wrapper"]

In your case just change

var xPathToAncestor = "./ancestor::div[@class='item-wrapper']";

See the '.' it indicates the child is the context node of xpath

This finds an element with tag div and class item-wrapper , and is a parent element of span tag

//ancestor::div[@class="item-wrapper"]/span

finds span tag that is a direct child of class="item-wrapper" and div tag

//ancestor::div[@class="item-wrapper"]//span

finds span tag that is a direct or non direct child of class="item-wrapper" and div tag

PDHide
  • 18,113
  • 2
  • 31
  • 46
  • @Richard77 did the answer solved your issue ? Adding .//ancestors should solve your problem – PDHide Jan 05 '21 at 02:11
0

To get to any child with respect to the common parent <div class="item-wrapper"> you can use the following based Locator Strategies:

  • Getting <input type="checkbox" /> using xpath:

    //div[@class='item-wrapper']//h6[text()='My Header']//following::label[1]/input[1]
    
  • Getting <span class="class1">Text 1</span> using xpath:

    //div[@class='item-wrapper']//h6[text()='My Header']//following::label[1]//span[@class='class1']
    

Update

As per your question update, to get the common parent <div class="item-wrapper"> you can use the following based Locator Strategies:

  • Using ancestor of xpath and text Text 2:

    //span[text()='Text 2']//ancestor::div[@class='item-wrapper']
    
  • Using ancestor of xpath and class="class1" attribute:

    //span[@class='class1']//ancestor::div[@class='item-wrapper']
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
-1

You could try using CSS selectors instead of XPath.

Using the HTML from your question as an example:

<div class="item-wrapper">
 <div>
  <h6>My Header</h6>              
 <div>
 <div>
  <div>
   <label>
    <input type="checkbox" />
    <span class="class1">Text 1</span>       
    <span class="class2"></span>
   </label>
  <div>
 </div>
</div>

To target class="class1" you would use this:

var classOne = driver.findElement(By.cssSelector(".item-wrapper > div(2) > div > label > '.class1'"));

  1. This locates the item-wrapper class,
  2. then the 2nd div (as the 1st div contains the header),
  3. then the next div
  4. then the label
  5. then whatever has the class class1
  6. Alternatively you could use the span instead of the class name. Which will make it var classOne = driver.findElement(By.cssSelector(".item-wrapper > div(2) > div > label > span(1)));. Because you want the first span rather than the 2nd.

Note that the CSS Selector for class is .. There are different CCS Selectors that you can use.

This answer explains using CSS Selectors too.

JeffC
  • 22,180
  • 5
  • 32
  • 55
nuclearcat
  • 164
  • 9