-2

I need to select a row in a table where I have a text, hence I would like to leverage the option of selecting a text and then eventually selecting the parent

Now the page looks like:

<tr class=" tableRow1" id="_pu5ufb" dr="1" _awtisprimaryrow="1">
<td width="1" class="tableBody w-tbl-cell" align="center"><span 
class="selectColumnMarker">

<div class="w-chk-container">
<input bh="CHKINP" hasaction="false" class="w-chk-native" 
id="_m7iynb" value="1" type="checkbox" elementid="_jw4lmb" 
issender="false" awnomitcomponent="true" name="_jw4lmb"><label 
bh="CHK" class="w-chk w-chk-dsize"></label>
</div>
</span>
</td>
<td align="left" class="tableBody w-tbl-cell">
<span>


<table role="presentation" class="mls" cellpadding="0" 
cellspacing="0">
<tbody><tr>
<td class="" id="_tz87e" tabindex="0"><a id="_3iqrbb" href="#" 
bh="HL" _sf="true">Analyst</a>
</td>
</tr>
</tbody></table>


</span>
</td><td class="tableBody w-tbl-cell">



&nbsp;</td>
<td class="tableBody w-tbl-cell">
&nbsp;</td>
</tr>

I need to find the text Analyst and then find the associated <tr> class and select the <tr> class.

Any help would be highly appreciable

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352

4 Answers4

2

I need to find the text Analyst and then find the associated tr class and select the tr class.

XPath 2.01

This XPath,

//tr[td/normalize-space() = "Analyst"]/@class

will select all @class attributes of tr elements containing a td with a space-normalized string value of "Analyst".

Do note, however, that in your sample HTML, such a tr has no @class.

1Thanks for correction, @DebanjanB

kjhughes
  • 106,133
  • 27
  • 181
  • 240
2

First, whenever you have mixed content (text and markup) it is better to compare elements' string value than text nodes because inline markup might be splitting the compared text into different text nodes.

Second, you can use:

//tr[td='Analyst']/@class

Note: node-set comparison is an existencial comparison. It means that you are asking if there is some node (some td element in this case) with string value equal to 'Analyst'.

Of course, in HTML there are elements for which white space is not significant for rendering (it's not preserved) despite its presence in the source document. In that case you can use this simple XPath 1.0 expression:

//tr[td[normalize-space()='Analyst']]/@class

Do note: a node-set has a false boolean value if and only if it's empty; you can "nest" predicates (properly, a predicate can be any XPath expression).

Alejandro
  • 1,882
  • 6
  • 13
  • 1
    //tr[td[normalize-space()='Analyst']]/@class Works thanks – supratim dutta Apr 05 '19 at 18:35
  • A follow up question: Now, If I want to use the concept of parent child relationship If I want to select , the chekbox which actually resides beside the text Analyst , how can I select it I tried doing the following things: //tr[td[normalize-space()='Analyst]].//input , but it does not seem to work – supratim dutta Apr 05 '19 at 23:27
  • @supratimdutta That `input` element resides in another hierarchical level very different to the one with `'Analyst'` string. Without more context than your provided input sample, I could only recomend `//tr[td[normalize-space()='Analyst']]/preceding::input[1]` – Alejandro Apr 06 '19 at 13:58
1

Fix your XML file to

<?xml version="1.0"?>
<!DOCTYPE stylesheet [
<!ENTITY nbsp "&#160;">
]>
<root>
  <tr class=" tableRow1" id="_pu5ufb" dr="1" _awtisprimaryrow="1">
    <td width="1" class="tableBody w-tbl-cell" align="center">
      <span class="selectColumnMarker">
        <div class="w-chk-container">
          <input bh="CHKINP" hasaction="false" class="w-chk-native" id="_m7iynb" value="1" type="checkbox" elementid="_jw4lmb" issender="false" awnomitcomponent="true" name="_jw4lmb"/>
          <label bh="CHK" class="w-chk w-chk-dsize"/>
        </div>
      </span>
    </td>
    <td align="left" class="tableBody w-tbl-cell">
      <span>
        <table role="presentation" class="mls" cellpadding="0" cellspacing="0">
          <tbody>
            <tr>
              <td class="" id="_tz87e" tabindex="0">
                <a id="_3iqrbb" href="#" bh="HL" _sf="true">Analyst</a>
              </td>
            </tr>
          </tbody>
        </table>
      </span>
    </td>
    <td class="tableBody w-tbl-cell">



&nbsp;</td>
    <td class="tableBody w-tbl-cell">
&nbsp;</td>
  </tr>
</root>

Then, the expression you are looking for is

//tr[td/a/text()='Analyst']/@class

But because the tr element does not have a class attribute, the result is empty.

zx485
  • 28,498
  • 28
  • 50
  • 59
1

A bit unclear what exactly you meant by ...find the associated tr class and select the tr class... once you have found ...the text Analyst....

However, as the elements are dynamic element and to locate the element with text as Analyst you can use either of the following Java based Locator Strategies:

  • linkText

    WebElement elem = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfElementLocated(By.linkText("Analyst")));
    
  • cssSelector:

    WebElement elem = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("td.tableBody table.mls a[bh='HL']")))
    
  • xpath:

    WebElement elem = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//td[contains(@class, 'tableBody')]//table[@class='mls']//a[text()='Analyst']")));
    

To extract the class attribute of the <tr> element with respect to the text as Analyst you can use the following Java based solution:

  • xpath:

    String tr_class_attrib = new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//td[contains(@class, 'tableBody')]//table[@class='mls']//a[text()='Analyst']//preceding::tr[1]"))).getAttribute("class");
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352