Xpath Tutorial Part 2: A Practical Approach for Selenium Users

Intro

Our introductory article on XPath basics can be found at Part 1. In this sequel article, we will be looking at various techniques to enhance our knowledge of XPath.

Technique #1 (Static Elements)

Scenario: Locating elements in a form such as a user registration or admission form

These are elements that have constant properties such as IDs and/or names. These properties do not change upon page refresh, application deployments, or different browser sessions. They are usually not auto-generated either.

Selenium has a search by id and/or name therefore, do not use XPath such as //input[@id=username] or //input[@name='postalAddress'] for static elements. Searching by ID and name is faster and easier.

To make sure that an element is static you need to refresh the page few times using Ctrl-F5 to make sure the element id or name does not change. If you are landed on the current web page by submitting a form (or using http post) then you need to restart the steps that got you to the page where the target element resides.

Examples:

Go to https://mail.yahoo.com/ and do an inspect element on username field. The id=login-username now refresh and try again. As you can see the id does not change so it could be used to target username field in Selenium. Here is the HTML code behind the username on that page with id highlighted:

< input class="phone-no " type="text" name="username" id="login-username" tabindex="1" value="" autocomplete="username" autocapitalize="none" autocorrect="off" autofocus="true" placeholder="Enter your email">

Browse to https://proof.subject-7.com/zul/samplePage.zul. Inspect the box in front of "Lastname" write down the id and do a refresh and look at the id again. As you can see, the id changes each time and hence you know the element is not static. Here is the HTML code behind lastname on that page:

< input id="kYAPh" style="width:80%;" class="z-textbox" value="" type="text">

Here is the HTML code behind lastname on page refresh. As you can see the id has changed:

< input id="jZBPh" style="width:80%;" class="z-textbox" value="" type="text">

Technique #2 (Menu Links) Scenario: Menus are common structures in web pages. A menu structure usually looks like this: <ul> <li> Link 1 </li> </ul>

To get to the menu link, remember that you are looking for a "Link". An XPath that targets the actual text on the screen will not really work. Here are some examples:

Sample HTML 1: <li class=""> <a href="services.html"> <cufon> <canvas /> <cufontext>Services</cufontext> </cufon> <em> </a> </li>

Target Element: Capture Services menu on the reference site www.subject-7.com.

Sample XPath: //*[contains(text(),'Services')]/ancestor::a The expression works like this:

//* Find all elements
[contains(text(),'Services')] Containing the text "Services" ancestor::a Then find an ancestor that is a link

Note how we start by a broad query and we narrow it down as we go. When you try this with Firepath make sure you get 1 match only. Most times when your XPath query matches more than one element on the page you wind up with weird behavior when running your test.

Sample HTML 2: <li id="gn-iphone"> <a href="/iphone/" onclick="s_objectID="http://www.apple.com/iphone/_1";return this.s_oc?this.s_oc(e):true"> <span>iPhone</span> </a> </li>

Target Element: Capture iPhone menu on the reference site www.apple.com Sample XPath:. //*[contains(text(),'iPhone')]/ancestor::a