Reputation: 63
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
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 functiontext()
needs to be lowercase//
when you don't have toNote
.
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
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
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