How to write XPATH in nested elements of siblings - xpath

I have such DOM structure:
<td>
<div class="name">Max</div>
</td>
<td>Sales Officer</td>
<td>mail#mail.com</td>
<td class="links">
<a class="edit" href="/edit"><i class="second"></i>Edit Profile</a>
</td>
The main goal is to click on Edit button for particular user. And I have different users (they are in another rows of table).
I need to get xpath which contains the combination of name Max and text Edit Profile.
The main problem for me that both elements are in sibling td tags.
I've never written anything similar before.
//a[text()='Max'] //i[text()='Edit Profile']
What should I add between this to xpathes?

This one should do the trick:
//td[a="Max"]/following-sibling::td/a[.="Edit Profile"]

Related

Find an element by text, get xpath and put in a list as every td is a unique element - selenium webdriver junit

I have a dynamically generated table with thead and tbody. Here is the example:
<tbody id="tableId" class="someclass1">
<tr id="rowId1" class="somesubclass">
<td id="item1" class="othersubclass">
<span class="attr">john Doe</span>
<td id="item2">
<span class="attr">55</span>
<td id="item3">
<span class="attr">5 street</span>
<td id="item2">
<span class="attr">cat</span>
<tr id="rowId2" class="somesubclass2">
<td id="item1" class="othersubclass2">
<span class="attr">joe smith</span>
<td id="item2">
<span class="attr">60</span>
<td id="item3">
<span class="attr">2 street</span>
<td id="item2">
<span class="attr">dog</span>
|joe doe|55|5 street|cat|
|joe foo|60|1 street|dog|
I would like to locate a row by text where the name is joe doe and put it into a list.
Locatior is working with this, but it is not a list.
#FindBy(xpath = "//tbody[contains(#id,'tableId')]/tr[td//text()[contains(.,'joe doe')]]")
private List<WebElement> list;
I got the list, but I cannot iterate over because everything has put into the first position like this:
list first element is: joe doe 55 5 street cat so this is the [0] element
How can I locate this row as a list where every td is a unique element in the list.
(iterate over, converting to string etc. is not a problem, just the locator.)
Thanks!
I don't understand what's for the -1. Anyway, here is the answer for others, hope this helps!
There is a good plugin for google kinda firepath: SelAssist, I use it to test my xpath locators.
The problem was that, td was missing. So the proper locator is
//tbody[contains(#id,'tableId')]/tr[td//text()[contains(.,'joe doe')]]/td
and it gives me list of elements, not only one.
Cheers!

XPath of the edit button is //*[#id="edit_1088"]

My query is I need to click on the first edit link on the table. The table has 7 columns and rows will be incremented dynamically.
HTML Code for first row:
<tr role="row" class="odd">
<td>
<form method="GET" target="_blank" action>...</form>
<td> ALLOCATION CHANGE</td>
<td class="right"></td>
<td> SATTER, KRAIG</td>
<td> CAFEMANAGER1</td>
<td class="sorting_1">03/08/2016 17:00</td>
<td class="edit_icon" id="edit_1088" onclick="on EditClick(1088)">
<span class="view_icon" style="margin-left: 40%;"></span>
</td>
</tr>
Note: the ID of the edit button keep on changing as the row increments.
Mycode in cucumber -ruby -capybara
And /^I click on the Expresso image$/ do
find(:xpath, '//*[#id="l1row"]/span').click
find('tr:odd > td:edit_icon [id="edit_"] match: first').click
sleep 10
end
Error Message: invalid selector: An invalid or illegal selector was specified
Update based on the posted HTML -
Note: Your first <td> isn't closed, I'm assuming thats just an error when you were adding the HTML to the question.
So from the HTML posted you don't actually have an edit link you just have a td you need to click on - the one in the first row with an id beginning with "edit_" so
find('tr:first-child > td[id^="edit_"]').click
The attempt you posted in your question won't work because there is no such CSS selector as odd or edit_icon and find needs valid CSS selectors (or XPath if you specify XPath or set it as your default)
Previous Answer Based on the wording of the question:
If this is a table then you can do what you want with CSS and not worry about XPath.
find('tr:first-child > td:last-child [id^="edit_"]')
will find the element whose id starts with "edit_" in the last td in the first row. If your rows and columns are not actually a table you'll need to provide some example HTML of what you're talking about.

XPath to locate a link within a table

I have a table as follows:
<tr class="ng-scope" ng-repeat="client in clients">
<td class="text-left ng-binding">Apu Nahasapeemapetilon</td>
<td class="text-left ng-binding">AN</td>
<td class="text-left">
<span class="ng-scope" ng-repeat="group in client.SecurityGroups">
<a class="label label-info ng-binding" href="#/SecurityGroup/MemberClients/a1cbf118-2c40-4ae7-a9f8-136bec945849/Assistants"> Assistants </a>
<span class="ng-scope" ng-repeat="group in client.SecurityGroups">
<a class="label label-info ng-binding" href="#/SecurityGroup/MemberClients/e4bd1580-3997-4f3d-a975-189e1fdccb4c/Managers"> Managers </a>
I am trying to locate on a link in the third cell. There can be muliple links in this cell. Ideally I want to identify the row by locating on cells 1 or 2.
So the idea given the table data above is: Find row with client code AN (in cell 2), then find the link 'Assistants' on that row (in cell 3).
I have a similar table on my project and the following XPpath will do what im aiming for on that table:
//tr[.//td='AN'] // a[.='Managers']
but it doesnt seem to work on the table above...
If I do:
//tr[.//td='AN'] // a
It will highlight all the links in the cell (i.e links ending Assistants and Managers), for the row containg 'AN', but I just cant seem to get it to locate on an individual link.
try the following xpath
//tr/td[.='AN']/following-sibling::td[1]//a[contains(#href, 'Assistants')]
the xpath looks for a tr with a child td having a value of 'AN'. Then looks at the first following-sibling td then looks for a descendant a which has an href value that contains 'Assistants'

xpath with multiple contains statements do not function correctly

I have html code as follows below. I am trying to access it with selenium. If I do a
//*[contains(text(),'Add OfficeContract (Portal)')]
it finds several (there is more html that has more occurrences). So I want to find a specific instance but when I try
//*[contains(text(),'Add OfficeContract (Portal)') and contains(text(),'7121995')]
There are no matches found. SImpy doing
//*[contains(text(),'7121995')]
Finds all sorts of stuff (html is full of that string)
HTML CODE
<tr class="pd" valign="top"><br>
<td> </td><br>
<td nowrap="">SQAAUTO</td><br>
<td nowrap="">01/30/2014 9:47:48 AM</td><br>
<td><br>
<b>Add OfficeContract (Portal)</b><br>
<br><br>
Office Id 7121995<br>
<br><br>
Contract ID added: "8976504"<br>
<br><br>
Term Date added: "12/31/9999"<br>
<br><br>
</td><br>
</tr>
I believe the issue here is that the two strings are not found together in the same element (based on your sample).
For the above xpath to return a result you would need an element like this:
<b>Add OfficeContract (Portal) 7121995</b>

How do I find if there's a second element exists with the same name with selenium using XPath?

I already know the Text of an element in the table:
string title1 = Driver.FindElement(
By.XPath(
".//[#id='ctl00_ContentPlaceHolder1_BreakdownGridView_ctl02_TitleLabel']"
)).Text;
How do I verify if there's a second element in the table that has the same text as title1?
Here is my Table structure:
<tr class="alt" style="background-color:White;height:110px;">
<td>
<span id="ctl00_ContentPlaceHolder1_BreakdownGridView_ctl03_WindowStartLabel" tabindex="1">
01/13/2013
</span>
</td>
<td>
<span id="ctl00_ContentPlaceHolder1_BreakdownGridView_ctl03_ShowLabel" tabindex="1">
Lea‌​der of the Pack
</span>
</td>
<td>
<span id="ctl00_ContentPlaceHolder1_BreakdownGridView_ctl03_TitleLabel">
Love at First Bite
</span>
</td>
<td>
<span id="ctl00_ContentPlaceHolder1_BreakdownGridView_ctl03_PremiereLabel">
01/12/2013 22:00
</span>
</td>
...
</tr>
After getting title1 try implement logic something like below to find how many elements are there with the same text
int count=driver.findElements(By.xpath("//table[#id='urTable']//*[text()='"+title1+"']")).size();
Based on the count it is easy to find how many elements are there with same text.
In your table structure, doing an xpath query as below would select all the span tags.
//tr/td/span
Now, xpath can be used to select the span tags with specific text as follows:
//tr/td/span[text() = "Text you're matching against"]
/* in your case*/
//tr/td/span[text() = title1]
This is to get spans consist that text....(partial match)
int count= driver.FindElements(
By.XPath(
".//span[contains(text(),'"+titleOneText+"')]"
)).size();
This is to get spans text is same....(full match)
int count= driver.FindElements(
By.XPath(
".//span[text()='"+titleOneText+"']"
)).size();
Based on your question if same xpath value having 2 elements. Just see the static value of particular element and take as xpath. it will work definitely. for example
save & cancel button having same xpath value
driver.find_element_by_xpath("//*[#id='id_sav']")-save
driver.find_element_by_xpath("//*[#id='id_sav']")-cancel
here we can use static element value
driver.find_element_by_xpath("//a[text()='save']")-save
driver.find_element_by_xpath("//a[text()='cancel']")-cancel

Resources