0

I'm trying to retrieve all elements from a html table td, however when I try to find elements by xpath with multiple conditions it fails retrieving 0 elements, there is no problem getting all values with a single condition. So far my issue is probably in the order of the html elements.

This is the search by a single condition using xpath which works fine: "//input[@class='managebtn'][@value='repost']"

This is what I am trying to achieve without desired result:

"//td[contains(text(),'manage')]/div[@class='regular']/form[@class='manage']/input[@class='managebtn'][@value='repost']"

The following html table is the one I am trying to read"

 <tbody aria-live="polite" aria-relevant="all">
  <tr class="posting-row odd ui-state-default" role="row">
     <td class="status expired">
        <small class="gc" style="background:">
        Expired               </small>
     </td>
     <td class="buttons expired"></td>
  </tr>
  <tr class="posting-row even ui-widget-content" role="row">
     <td class="status deleted">
        <small class="gc" style="background:">
        Deleted               </small>
     </td>
     <td class="buttons deleted">
        <div class="regular">
           <form action="https://" method="GET" class="manage display">
              <input type="hidden" name="action" value="display">
              <input type="submit" name="go" value="display" class="managebtn">
           </form>
           <form action="https://" method="GET" class="manage ">
              <input type="hidden" name="action" value="repost">
              <input type="submit" name="go" value="repost" class="managebtn">
           </form>
        </div>
     </td>
   
  </tr>
  <tr class="posting-row odd ui-state-default" role="row">
     <td class="status deleted">
        <small class="gc" style="background:">
        Deleted               </small>
     </td>
     <td class="buttons deleted">
        <div class="regular">
           <form action="https://" method="GET" class="manage display">
              <input type="hidden" name="action" value="display">
              <input type="submit" name="go" value="display" class="managebtn">
           </form>
           <form action="https://" method="GET" class="manage ">
              <input type="hidden" name="action" value="repost">
              <input type="submit" name="go" value="repost" class="managebtn">
           </form>
        </div>
     </td>
  </tr>
  <tr class="posting-row even ui-widget-content" role="row">
     <td class="status deleted">
        <small class="gc" style="background:">
        Deleted               </small>
     </td>
     <td class="buttons deleted">
        <div class="regular">
           <form action="https://" method="GET" class="manage display">
              <input type="hidden" name="action" value="display">
              <input type="submit" name="go" value="display" class="managebtn">
           </form>
           <form action="https://" method="GET" class="manage ">
              <input type="hidden" name="action" value="repost">
              <input type="submit" name="go" value="repost" class="managebtn">
           </form>
        </div>
     </td>
    
  </tr>

I only want to retrieve all values from second column (value='repost')only when the first column has the value Expired.
Looks like since this table has multiple elements inside the columns, maybe there something I am overlooking.

Since the columns have th like this:

      <th data-column="0" class="tablesorter-header tablesorter-headerUnSorted ui-widget-header ui-corner-all ui-state-default" tabindex="0" scope="col" role="columnheader" aria-disabled="false" unselectable="on" style="user-select: none;" aria-sort="none" aria-label="status: No sort applied, activate to apply an ascending sort">
   <div class="tablesorter-wrapper" style="position:relative;height:100%;width:100%">
      <div class="tablesorter-header-inner">
         status <i class="tablesorter-icon ui-icon ui-icon-carat-2-n-s"></i>
      </div>
   </div>
</th>
<th class="sorter-false tablesorter-header tablesorter-headerUnSorted ui-widget-header ui-corner-all ui-state-default" data-column="1" scope="col" role="columnheader" aria-disabled="true" unselectable="on" style="user-select: none;" aria-sort="none" aria-label="manage: No sort applied, sorting is disabled">
   <div class="tablesorter-wrapper" style="position:relative;height:100%;width:100%">
      <div class="tablesorter-header-inner">
         manage  <i class="tablesorter-icon ui-icon"></i>
      </div>
   </div>
</th>

I do't know if it is possible to have a line of code like this one in order to get the values I need:

driver.findElement(By.xpath("//th[@class='sorter-false tablesorter-header tablesorter-headerUnSorted ui-widget-header ui-corner-all ui-state-default' and @text()='manage']"));

This is how the table looks like:

This is how table looks like

DebanjanB
  • 118,661
  • 30
  • 168
  • 217
John
  • 51
  • 1
  • 8
  • You asked about _column (value='repost')only when the first column has the value Expired_ but the HTML you provided was for the elements within **td class="status deleted**. I had to assume a lot while constructing the answer. – DebanjanB Jul 21 '20 at 23:59
  • That's why I said that my xpath and find method may be wrong as there are multiples elements within the first and second column as described in the question (html). Please see my comments below to refer to the error and warning I am getting with you suggested solution. – John Jul 22 '20 at 00:03

1 Answers1

-1

To identify the elements with value attribute as repost within the items with status as Expired you have to induce WebDriverWait for the VisibilityOfAllElementsLocatedBy() and you can use the following based Locator Strategy:

new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.VisibilityOfAllElementsLocatedBy(By.XPath("//tr[contains(@class, 'posting-row')][./td[@class='status expired']]//td[@class='buttons expired']//input[@class='managebtn' and @value='repost']")));

With SeleniumExtras.WaitHelpers you can use:

new WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until(SeleniumExtras.WaitHelpers.ExpectedConditions.VisibilityOfAllElementsLocatedBy(By.XPath("//tr[contains(@class, 'posting-row')][./td[@class='status expired']]//td[@class='buttons expired']//input[@class='managebtn' and @value='repost']")));
DebanjanB
  • 118,661
  • 30
  • 168
  • 217
  • Thank you for you patience DebanjanB, I implemented form and I am getting timeout no matter the time in seconds I specify which means maybe that the xpath could be wrong. Also the ExpectedConditions is Obsolete as per the warning message. I'll show you my implementation on next message. – John Jul 21 '20 at 23:56
  • Warning: Deprecated class OpenQA.Selenium.Support.UI.ExpectedConditions 'ExpectedConditions' is Obsolete. This portion of the code has been migrated to the DotNetSeleniumExtras GitHub (github.com/dotnetseleniumtools/dotnetseleniumextras) Implementation: var wait = new WebDriverWait(webDriver, TimeSpan.FromSeconds(timeoutInSeconds)).Until(ExpectedConditions.VisibilityOfAllElementsLocatedBy(By.XPath("Same one you posted"))); return wait; – John Jul 21 '20 at 23:59
  • @John Checkout the answer update and let me know the status. – DebanjanB Jul 22 '20 at 00:05
  • 1
    Here is the feedback @DebanjanB, I just needed to go to NuGet, download the DotNetSeleniumExtras.WaitHelpers and implemented your solution like: ...SeleniumExtras.WaitHelpers.ExpectedConditions.VisibilityOfAllElementsLocatedBy... and all worked like a charm. Thank you for your time again, I spent several hours on this without any luck and you just saved my night! – John Jul 22 '20 at 00:30
  • @John Glad to be able to help you. [Upvote](https://stackoverflow.com/help/why-vote) the answer if this/any answer is/was helpful to you for the benefit of the future readers. – DebanjanB Jul 22 '20 at 00:36