Writing XPath for elements which have no ID or Name in Selenium - xpath

I'm trying to automate testing of the code... well, written without testing in mind (no IDs on many elements, and a lot of elements with the same class names). I would appreciate any help (questions are below the code):
<div id="author-taxonomies" class="menu-opened menu-hover-opened-inactive" onmouseover="styleMenuElement(this)" onmouseout="styleMenuElement(this)" onclick="toggleSFGroup(this)">Author</div>
<div id="author-taxonomies-div" class="opened">
<div id="top-level-menu" class="opened">
<div id="top-level-menu-item-1" class="as-master">
<div class="filter-label"> Name</div>
</div>
<div id="top-level-menu-item-1" class="as-slave"
style="top: 525px; left: 34px; z-index: 100; display: none;"> </div>
<div id="top-level-menu-item-2" class="as-master">
<div class="filter-label">Title</div>
</div>
<div id="top-level-menu-item-2" class="as-slave">
<div id="top-level-menu-item-2" class="as-slave-title as-slave-title-subgroup"
>Title</div>
<div id="top-level-menu-item-2" class="as-slave-body"> </div>
<div class="as-slave-buffer"> </div>
</div>
<div id="top-level-menu-item-3" class="as-master">
<div class="filter-label">Location</div>
</div>
<div id="top-level-menu-item-3" class="as-slave"> </div>
</div>
</div>
The question is: how to refer particular labels of this menu and the properties with xPath expressions? For example, if I want to:
verify the "Location" label is there
check if "Title" with class "as-slave" is not visible at the moment

It would be something similar to:
//div[#id="top-level-menu-item-3"]/div[#class="filter-label"]
//div[#id="top-level-menu1"] --- and check in code for display: none ... assuming it is selenium rc you are using
Update: also be sure to install the following firefox addin, it is Really useful when trying different xpath expressions on a site https://addons.mozilla.org/en-US/firefox/addon/1095

As a side note: try to avoid using xpath locators in Selenium, if possible. If you have a long xpath expression, it can be up to 20 times slower for Selenium to find the element compared to identifying it using its unique ID. Of course, sometimes there is no alternative to using xpath. However, when you do use it, keep '//' expressions to minimum - this is a real performance killer.

If you're just starting with Selenium, download the selenium add-on for Firefox. As you click on DOM elements, Selenium shows you the xpath to access it.

I am currently working on an open source library for generating xpath expressions through a fluent .Net API. The idea is to be able to generate xpath based selenium locators without having to know xpath.
Here's an example of how the library can be used in your case:
XPathFinder.Find.Tag("div").With.Attribute("id", "top-level-menu-item-3").And.Child("div").With.Attribute("class", "filter-label").ToXPathExpression();
This will produce the following xpath:
"//div[#id='top-level-menu-item-3']/div[#class='filter-label']"
Check it out at
http://code.google.com/p/xpathitup/

You can use firepath that can be installed over firebug(both firefox plugin). When you get a xpath, dont forget to append // before using it. Either in code or in selenium IDE. You are not appending it thats why its unusable. There are two types of xpath absolute and relative. If you use absolute then it will take care of dynamic ids. But if you use relative it will break with each run.

Related

Need help finding an element in selenium

Can some one help me to locate an element (without using xpath) which is displayed using : <i id="ext-gen759" class="icon-tool"></i> under a <div> tag. The HTML is as follows:
<div id="ext-comp-1089" class=" MiniTbar">
<a href="javascript:void(0);" id="ext-gen760" class=" active">
<i id="ext-gen759" class="icon-tool"></i> -->> need to locate this.
</a>
</div>
I don't want to use:
By.Id --> id is dynamic
By.XPath --> not stable
I have tried the following without getting a result:
By.className("icon-tool") -- > not working
By.partialLinkText("icon-tool") --> not working
Any solution?
You can rely on the part of the id using, for example, starts-with():
//div[starts-with(#id, "ext-comp-")]/a[starts-with(#id, "ext-gen")]/i[#class="icon-tool"]
Or a CSS selector:
div[id^=ext-comp-] a.active[id^=ext-gen] i.icon-tool[id^=ext-gen]
using xpath should do this. You may need to make sure that's the only element i with same criteria on the page
//i[contains(#id,'ext-gen')]
Give a chance to the find element by css selector ?
driver.find_element_by_css_selector('i.icon-tool')
The python documentation is here http://selenium-python.readthedocs.org/en/latest/locating-elements.html
You can find it using css selector:
driver.findElement(By.cssSelector("i[class='icon-tool']"));

Finding an element by XPath in Selenium

I am trying to use Selenium to navigate a webpage. There is a button I am trying to get to via its xpath. For other buttons on the site, it works fine. But for this particular one, I keep getting the error that the element can't be located. Firebug is just giving me the xpath in this format: //*[#id="continueButton"].
I notice that the button has wrappers around it. They are structured like
<div class = "cButtonWrapper">
<div class = "cButtonHolder">
<input type="image" id="continueButton" name="Continue" alt="Continue" src="/store/images/btn_continue.gif" value="Continue">
</div>
</div>
Could the wrappers around the button have anything to do with not being able to locate it?
Maybe the <input> element cannot be properly located by XPath because you are using invalid HTML. Try using <input id="continueButton"/> or <input id="continueButton"></input> in your page source.

Google Spreadsheet importxml timestamp

I been trying for over 2 hours to import timestamp from zap2it.com link to my google spreasheet.
Here is link I am trying to importxml from.
http://affiliate.zap2it.com/tvlistings/ZCGrid.do?zipcode=78238&lineupId=DISH641:-
Here is what I am tryign to import
Here is what I tried so far
=importxml("http://affiliate.zap2it.com/tvlistings/ZCGrid.do?aid=dish&pkg=8388608&fromProvider=true&zipcode=78238&x=52&y=18"&B1,"//body//div[3]/div/div/div[3]/div/div")
EDIT
I was able to improve and get better results
//body//div[3]/div/div/div[1]//*
but it shows timestamp from all over the page. not exactly what I need.
[The first complication is that the data stream returned from dereferencing that URI is not actually XML; it has several thousand well-formedness errors (unescaped ampersands in URIs, unescaped ampersands and less-than signs in scripts, some embedded HTML, some miscellaneous errors). Since you're not reporting problems from that, however, I'll assume that somewhere between the server and your XPath expression someone is doing some tidying.]
I think you'll get better results if you use the id and class attributes that are extensively used in the document. The material you want looks like this in the source (you can use any browser-based debugging tool to find it; I used the 'Web Inspector' in Safari); I have indented to make the structure more visible, and fixed some well-formedness errors in one of the a elements (missing whitespace between attribute-value pairs).
<div class="zc-tn" id="zc-tn-top">
<div class="zc-tn-i">
<a href="ZCGrid.do?fromTimeInMillis=1355781600000"
class="zc-tn-l"
title="Move the grid three hours earlier"></a>
<div class="zc-tn-c">
<span class="zc-tn-z"
title="Central Standard Time">CST</span>
<div class="zc-tn-t">7:00 PM</div>
<div class="zc-tn-t">7:30 PM</div>
<div class="zc-tn-t">8:00 PM</div>
<div class="zc-tn-t">8:30 PM</div>
<div class="zc-tn-t">9:00 PM</div>
<div class="zc-tn-t">9:30 PM</div>
</div>
<a href="ZCGrid.do?fromTimeInMillis=1355803200000"
class="zc-tn-r"
title="Advance the grid three hours"></a>
</div>
</div>
A simple search verifies that the value zc-tn-top is indeed unique as an ID value in the document. Given that, a simple XPath expression to retrieve all the elements whose display is circled in your image is (assuming xhtml is bound to the XHTML namespace):
//xhtml:div[#id='zc-tn-top']//xhtml:div[#class='zc-tn-t']
It looks from your question as if your XPath evaluator is namespace-challenged or namespace-oblivious, so you may need to write this as
//div[#id='zc-tn-top']//div[#class='zc-tn-t']

discover a certain part of a page with selenium

I have a webpage looks something like this:
<html>
...
<div id="menu">
...
<ul id="listOfItems">
<!--- repeated block start -->
<li id="item" class="itemClass">
...
<span class="spanClass"><span class="title">title</span></span>
...
</li>
<!-- repeated block end-->
<li id="item" class="itemClass">
...
<span class="spanClass"><span class="title">title something</span></span>
...
</li>
<li id="item" class="itemClass">
...
<span class="spanClass"><span class="title">title other thing</span></span>
...
</li>
</ul>
...
</div>
...
</html>
I would like to know what is the xpath of the titles ("title", "title something", "title other thing"). The point is that the order of the <li> elements are not specified. It could be different after every page loading. Is there any method how to discover a certain structure of the page with xpath? I have an notion about how to solve this issue, but before I'm going to write iterations with C# to discover the page I ask you.
Thanks in advance!
First of all, id's should be unique, so your portrayed webpage would not work well when it comes to testing.
I did however test, and got some XPath locators to work for selecting specific titles (although I recommend you fix your webpage instead of actually using this):
//li[#id='item']/span/span
//li[#id='item'][1]/span/span
//li[#id='item'][3]/span/span
If you're after all three titles, you could try Dimitre Novatchev's suggestion:
//span[#class='title']
This should get all titles on the page.
I would like to say one thing however, if you're getting into Selenium, I recommend you download the Selenium IDE extension for Firefox. It's a great tool for beginners. It helps you both to make your Selenium tests by recording your clicks on a website, and it also helps you auto-generate and test your XPath locators and other locators.
And again: I urge you to not make a website with duplicate id elements :-)
Does Selenium support XPath expressions like:
//span[#class='title']
If yes, than use the above XPath expression. It selects every span element in the XML document, whose class attribute has string value of "title".
I recommend to use a tool like the XPath Visualizer to play with different XPath expressions and see the selected nodes highlighted in the source XML document.

Trying to create XPath from this HTML snippet

I have played for a while writing XPath but am unable to come up with exactly what I want.
I'm trying to write XPath for link(click1 and click2 in code snippet below) based on known text(myidentity in code snippet below). Can someone take a look into and suggest possible solution?
HTML code snippet:
<div class="abc">
<a onclick="mycontroller.goto('xx','yy'); return false;" href="#">
<img src="images/controls/inheritance.gif"/>
</a>
myidentity
<span>
<a onclick="mycontroller.goto('xx','yy'); return false;" href="#">click1</a>
<a onclick="mycontroller.goto('xx','yy'); return false;" href="#">click2</a>
</span>
</div>
You don't need to use XPath here, you could use a CSS locator. These are often faster and more compatible across different browsers.
css=div:contains(myidentity) > span a:nth-child(1) //click1
css=div:contains(myidentity) > span a:nth-child(2) //click2
Note that the > is only required to workaround a bug in the CSS locator library used by Selenium.
Hard to say without seeing the rest of the HTML but the following should work:
//div[text()[contains(., "myidentity")]]/span/a
See Macro's answer - this form should be used.
//div[text()[contains(., "myidentity")]]/span/a[2]
The following only works with one section of text in the containing div.
You'll need to select based on the text containing your identity text.
Xpath for click1
//div[contains(text(),"myidentity")]/span/a[1]
Xpath for click2
//div[contains(text(),"myidentity")]/span/a[2]

Resources