Calle
Calle

Reputation: 63

Selenium Xpath to find a table cells inside a div tag

I have the following HTML code that I need to check if text exists within a table cell:

<div class="background-ljus" id="AutoText">
  <table class="topAlignedCellContent">
    <tbody>
      <tr>
        <td>X1</td>
      </tr>
      <tr>
        <td>X2</td>
      </tr> 
    </tbody>
  </table>
  <table>
    <tbody>
      <tr>
        <td>Y1</td>
        <td>Y2</td>
      </tr>
    </tbody>
  </table>
  <table>
    <tbody>
      <tr>
        <td>Z1</td>
        <td>Z2</td>
      </tr>
    </tbody>
  </table>
</div>

I have solved it like this:

By locator = getLocator(CommonConst.XPATH, "*//div[@" + type + "='" + anyName + "']");
  fluentWait(locator);

  WebElement div = getDriver().findElement(locator);
  List<WebElement> cells = div.findElements(By.tagName("td"));
  for (WebElement cell : cells) {
    if (cell.getText().contains(cellText)) {
      foundit = true;
    }
  }

But i think its a bit slow because I need to do this several times. I tried to do this with only XPath but had no luck.

"*//div[@id='AutoText']//td[contains[Text(), 'celltext']]"
"*//div[@id='AutoText']//table//tbody//tr[td//Text()[contains[., 'celltext']]"

Anyone have a suggestion about why my XPath isn't working?

Upvotes: 3

Views: 20674

Answers (3)

Tomalak
Tomalak

Reputation: 338406

Wrong:

*//div[@id='AutoText']//td[contains[Text(), 'celltext']]
*//div[@id='AutoText']//table//tbody//tr[td//Text()[contains[., 'celltext']]

Correct (with shorter alternatives):

//div[@id='AutoText']//td[contains(text(), 'celltext')]
//div[@id='AutoText']//td[contains(., 'celltext')]

//div[@id='AutoText']/table/tbody/tr[td//text()[contains(., 'celltext')]
//div[@id='AutoText']/table/tbody/tr[td[contains(., 'celltext')]]
  • contains() is a function
  • text() needs to be lowercase
  • predicates can be nested
  • don't use // when you don't have to

Note

. refers to "this node" and, when given as an argument to a string function such as contains(), is the equivalent of string(.). This, however, is not at all the same as text().

string(.) creates the concatenation of all text nodes inside the current node, no matter how deeply nested. text() is a node test and by default selects only the direct children.

In other words, if the current node was <td>foo <b>bar</b> baz</td>, contains(text(), 'bar') would actually be false. (So would contains(text(), 'baz'), for a different reason.)

contains(., 'bar') on the other hand would return true, so would contains(., 'baz').

Only when the current node contains nothing but a single text node, text() and . are equivalent. Most of the time, you will want to work with . instead of text(). Set up your predicates accordingly.

Upvotes: 8

giri-sh
giri-sh

Reputation: 6962

Your xpath's are wrong. You should be using text() instead of Text(). Also contains() is a function with round braces and not square braces. Try this -

"//div[@id='AutoText']//td[contains(text(), 'celltext')]"
"//div[@id='AutoText']//td[contains(., 'celltext')]"

Or instead if you want all the child elements with the text to be displayed then use . instead of text()

Hope it helps.

Upvotes: 0

Shubham Jain
Shubham Jain

Reputation: 17593

You can do it with dynamic xpath as well

//div[@id='AutoText']/table[1]//tbody/tr[1]/td

Now just replace 1 with i and use for loop to see if the element return any value or not

Upvotes: 0

Related Questions