Understanding WebElement.findElement() and XPATH

35,685

Solution 1

There are my 2 comments with your sample code

1 - With your posted HTML, the xpath //a/li[2] is not found (we only have 3 elements with //a/li[1])

2 - Assume that we do have right code, you need to understand the differences between single slash and double slash in Xpath

a/b (single slash): select element that has "tag b" and "stands right after" an element that has "a tag" 

E.g.:

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

AND

a//b (double slash): select element that has "tag b" and is n-level-child an element that has "a tag"

E.g.:

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

So, with your code

<a>
<li> parent 1
    <div>
        <span class="child-title child-style">title 1</span>
        <span class="child-date child-style"> date 1</span>
        <span class="child-author">author 1</span>
    </div>
</li>
</a>

If you want to get Date Info, you should use

WebElement parent = driver.findElement(By.xpath("//a/li"));
WebElement date = parent.findElement(By.xpath("div/span[contains(@class, 'child-date')]"));
WebElement date = parent.findElement(By.xpath("//span[contains(@class, 'child-date')]"));

The code

WebElement date = parent.findElement(By.xpath("span[contains(@class, 'child-date')]"));

Will bring out NoSuchElementException because there is no [span] tag right after [li] tag

Hope help

Solution 2

Try something like: Use dot(.) before double slash(//)

It looks for child under the given parent element.

Solution 3

Completely new question ... completely new answer. :(

Try something like:

WebElement parent1 = driver.findElement(By.xpath("//a[1]/li"));   // use a[2] for parent2
WebElement author = parent1.findElement(By.xpath("span[@class='child-author']"));
WebElement date = parent1.findElement(By.xpath("span[contains(@class, 'child-date')]"));
WebElement title = parent1.findElement(By.xpath("span[contains(@class, 'child-title')]"));

Solution 4

Try something like :

//a/li[contains(text(), 'parent 1')]/div

It requests for "the <div> inside a <li> whose text contains 'parent 1' and who is inside a <a>.
It might not work if you have more parents because it works with a contains() (this xpath would also select <li> parent 10 ... </li>). It would be better if "parent x" were an attribute of the <li> instead of its text.

Share:
35,685
derrdji
Author by

derrdji

BY DAY: SDM at Amazon BY NIGHT: Taking care of baby @Deprecated FOR FUN: Battlefield, binge watching shows and movies FOR FUN v2: @See About me.BY NIGHT SOreadytohelp

Updated on July 17, 2022

Comments

  • derrdji
    derrdji almost 2 years

    I want to use the WebElement.findElement() API to locate a node inside the parent node using XPATH //span[@class='child-class']. I thought this would return me the <div> that is inside the parent. However, it is returning me the first one it found in the entire DOM tree. Did I use the wrong XPATH?

    I have also tried using .//span[@class='child-class'] as the XPATH, but that does return anything.

    Thank you.

    UPDATE:

    given the HTML below, I want to define a locator for the child-title <span> and child-date <span> and locate them using WebElement.findElement() API regardless of the parent being "//a/li[1]" or "//a/li[2]"

    <a>
        <li> parent 1
            <div>
                <span class="child-title child-style">title 1</span>
                <span class="child-date child-style"> date 1</span>
                <span class="child-author">author 1</span>
            </div>
        </li>
    </a>
    <a>
        <li> parent 2
            <div>
                <span class="child-title child-style">title 2</span>
                <span class="child-date child-style"> date 2</span>
                <span class="child-author">author 3</span>
            </div>
        </li>
    </a>
    <a>
        <li> parent 3
            <div>
                <span class="child-title child-style">title 3</span>
                <span class="child-date child-style"> date 3</span>
                <span class="child-author">author 3</span>
            </div>
        </li>
    </a>
    

    I have a WebElement parent2 initialized and located using "//a/li[2]",

    WebElement child = parent2.findElement(By.xpath("//span[@class='child-author']")); would give me "author 1"

    WebElement child = parent2.findElement(By.xpath("span[@class='child-author']")); would give me NoSuchElementException

  • derrdji
    derrdji almost 10 years
    I have tried removing the "//" in my XPATH locator, but that did not work.