How to apply filter with XPath on WebElement object

Hi all,

I’m trying to get all rows of a table (@id = A68) and to apply a filter to only keep rows visible (visibility: inherit).

My objective is to store all rows into a list if there are rows visible. If all rows are hidden, the list must be empty.

WebDriver driver = DriverFactory.getWebDriver()
WebDriverWait wait = new WebDriverWait(driver, 10)
WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath('//*[@id="A68"]//tr')))
WebElement table = driver.findElement(By.id('A68'))List<WebElement> listElements = table.findElements(By.xpath('.//tr[contains(@style,"visibility: inherit")]'))println listElements.size()

I use ‘presenceOfElementLocated’ to get all rows.
If it is possible to use ‘element’ and apply the xpath filter on it, I will be happy.

However, size list is 0. I don’t understand why because table has rows visible on the HTML DOM.

Can you help me?

Regards,

How about this?

List<WebElement> listElements = table.findElements(    By.xpath('.//tr[not(contains(@style,"hidden"))]'))println listElements.size()

I suppose that your

nodes do not have string ‘visibility: inherit’ explicitly coded in HTML. Browser assumes ‘visibility: inherit’ as the default value. You can not get access to the Browser’s default interpretation through XPath. I suppose that you HTML would have explicit code of style=“visibility: hidden”. So the above code would work.

Thanks for your answser.

My new code is :

WebDriver driver = DriverFactory.getWebDriver()
WebElement table = driver.findElement(By.id('A68'))
List<WebElement> listElements = table.findElements(By.xpath('.//tr[not(contains(@style,"hidden"))]'))
println listElements.size()

But size is still 0 while in the browser this xpath expression works :

//*[@id='A68']//tr[not(contains(@style,"hidden"))]

How about this ?

WebDriver driver = DriverFactory.getWebDriver()
List<WebElement> listElements = driver.findElements(By.xpath(                      '//*[@id='A68']//tr[not(contains(@style,"hidden"))]'))
println listElements.size()
By.xpath('.//tr[not(contains(@style,"hidden"))]')

The leading dot (.) character here looks odd to me.

If you require the “table” variable, then try this:

WebDriver driver = DriverFactory.getWebDriver()
WebElement table = driver.findElement(By.id('A68'))
List<WebElement> listElements = table.findElements(By.xpath(                   'descendant::tr[not(contains(@style,"hidden"))]'))
println listElements.size()

descendant:: is an instance of XPath Axes. see

https://www.w3schools.com/xml/xpath_axes.asp

With this solution, I apply the filter on all descendants.
However, I want to apply only on the ‘first level of child’.

Below, an extract of HTML code (don’t ask me why there is table in table I don’t have any idea ahah).

<table id='A68'>
  <tbody>
     <tr id='A68_0' style='visibility: inherit'>
       <td>
          <table>
             <tr>
                <td>                   <table>                      <tr>                         <td>...</td>                      </tr>                   </table>                </td>
              </tr>
           </table>
        </td>
      <tr>
      ...
   </tbody>
</table>

The size list in this case is 3.

The final objective is to get all row object but apply the filter only on the first

level.

Straight forward solution:

'//table[@id='A68']/tbody/tr[not(contains(@style,"hidden"))]'))

This code seems to work!

List<WebElement> listElements = driver.findElements(By.xpath('//*[@id="A68_TB"]/tbody/tr[not(contains(@style,"hidden"))]'))
println listElements.size()

Thank’s a lot! I will back if I have any troubles in the future.