1

For the below HTML code

<table class="table" id="Table1" xpath="1">
   <thead>
      <tr class="table-header">      </tr>
   </thead>
   <tbody>
      <tr class="table-row">
         <span><i data-icon="" class="icon fa fa-pencil fa-1x" id="l2_0-0-Edit_Icon"></i></span>
      </tr>
      <tr class="table-row">
         <span><i data-icon="" class="icon fa fa-pencil fa-1x" id="l2_0-0-Edit_Icon"></i></span>
      </tr>
      <tr class="table-row">
         <span><i data-icon="" class="icon fa fa-pencil fa-1x" id="l2_0-0-Edit_Icon"></i></span>
      </tr>
      <tr class="table-row">
         <span><i data-icon="" class="icon fa fa-pencil fa-1x" id="l2_0-0-Edit_Icon"></i></span>
      </tr>
      <tr class="table-row">
         <span><i data-icon="" class="icon fa fa-pencil fa-1x" id="l2_0-0-Edit_Icon"></i></span>
      </tr>
   </tbody>
</table>
<pre>

Suppose I need to click Edit Button on 4th row .. I can use following code. (This code is working fine)

Driver.FindElement(By.XPath("//table[@id='Table1']//tr[3]//i[contains(@id,'Edit_Icon')]")).Click()

The Problem is Edit Button may not always exist on 1st, 2nd or 3rd row. (Its dynamic based on diff conditions)

<table class="table" id="Table1" xpath="1">
   <thead>
      <tr class="table-header">      </tr>
   </thead>
   <tbody>
      <tr class="table-row">
         <span><i data-icon="" class="icon fa fa-pencil fa-1x" id="l2_0-0-Edit_Icon"></i></span>
      </tr>
      <tr class="table-row">
         
      </tr>
      <tr class="table-row">
         <span><i data-icon="" class="icon fa fa-pencil fa-1x" id="l2_0-0-Edit_Icon"></i></span>
      </tr>
      <tr class="table-row">
         <span><i data-icon="" class="icon fa fa-pencil fa-1x" id="l2_0-0-Edit_Icon"></i></span>
      </tr>
      <tr class="table-row">
         
      </tr>
   </tbody>
</table>

Hence i am trying to follow below code, and then change "3" as per need. (I am trying to do is find the 3row and within that i am trying to find Edit Icon). But its not working.

How i can i write an Xpath that always clicks on the row i wanted, irrespective of other rows has "Edit" button or not?

Driver.FindElement(By.XPath("//table[@id='Table1']")).FindElements(By.XPath("//tr"))[3].FindElement(By.XPath("//i[contains(@id,'Edit_Icon')]")).Click()
Fayas Hussain
  • 69
  • 1
  • 7

2 Answers2

1

Try this:

Driver.FindElement(By.XPath("//table[@id='Table1']")).FindElements(By.XPath(".//tr"))[3].FindElement(By.XPath(".//i[contains(@id,'Edit_Icon')]")).Click();

I can't promise there will be 3 tr elements inside the table.
Also that element may not contain edit icon, as you mentioned, but this will locate the correct element.
If you you wish to check if that element exists before clicking it you can do this:

var list = Driver.FindElement(By.XPath("//table[@id='Table1']")).FindElements(By.XPath(".//tr"))[3].FindElements(By.XPath(".//i[contains(@id,'Edit_Icon')]"));
if(list.Count()>0){
    list[0].Click();
    }
Prophet
  • 32,350
  • 22
  • 54
  • 79
1

First af all you write: "Suppose I need to click Edit Button on 4th row .. I can use following code. (This code is working fine)" And then you use the predicate [3].

This [3] wil select all elements that are in the third position. And that is correct for the third tr in your tbody.

If performance is importend I would use a XPath that is as explicit as possible. So use the tbody in your XPath and try not to use to many //, because that slows down the XPath-engine. See for explanation on the meaning of // this answer

The problem with your example that the tr dont have td/th elements. Since that is not valid html, I assume your span are child-elements of a td-element. If so, this is what you may need:

//table[@id='Table1']/tbody/tr[td/span/i[contains(@id,'Edit_Icon')]][3]/td/span/i[contains(@id,'Edit_Icon')]"))

This XPath first filters tr-elements based on the existence of those i[contains(@id,'Edit_Icon')]] and then use the third position.

Siebe Jongebloed
  • 3,906
  • 2
  • 14
  • 19