Search code examples
xpathselenium-webdriverunique

Using xpath to locate element with an underline in the name


I am trying to click on a webelement that changes ID and xpath dynamically. I dont see any other information that can be used directly to identify the element uniquely everytime the page loads.

Here is the Xpath for the element:

.//*[@id='isc_SB']/table/tbody/tr/td

This will be updated along with ID at every page load.

Here is the HTML code for the same element:

<table width="74px" height="30px" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="OBToolbarTextButtonFocusedOver" valign="center" nowrap="true" align="center" onfocus="isc_OBToolbarActionButton_3.$47()" tabindex="-1">
Pu
<u>b</u>
lish
</td>
</tr>
</tbody>
</table>

I want to click on the button with Text called "publish" with 'u' having an underline

Here is what i have tried to no success:

Attempt 1:

publish = //td[. = 'Pu<u>b</u>lish']

Attempt 2:

publish = //td[contains(text(), 'lish')] 

Attempt 3:

publish = .//*[@id='isc_S7']/table/tbody/tr/td # this is just an example to show id, xpath and everything is dynamic.

Please assist. Thank you.


Solution

  • In XPath the string value of an element node is defined as the concatenation of all its descendant text nodes, so if you have a

    <td>Pu<u>b</u>lish</td>
    

    then you can match it using simply

    //td[. = 'Publish']
    

    If, as in your question, there are newlines either side of the u element then you need to be a bit more creative, e.g.

    //td[normalize-space() = 'Pu b lish']
    

    If you want to cover both cases then

    //td[translate(normalize-space(), ' ', '') = 'Publish']
    

    As an aside, the reason your attempt 2 didn't work is that contains expects both its arguments to be strings, but in your example text() gives you a set of two text nodes ("Pu" and "lish"), and converting a node set to a string means taking the value of just the first node in the set in document order and ignoring the other(s).