Basic XPath Theory
Basic XPath Theory
This chapter will provide you with a basic understanding of XPath. Just enough to cover the basic requirements for writing Selenium tests. XPath is the XML Path Language. Since all HTML, once loaded into a browser, becomes well structured and can be viewed as an XML tree, we can use XPath to traverse it. XPath is a full programming language so you can perform calculations (e.g. last()-1), and use boolean operations ( e.g. or, and). NOTE: To help follow this section you might want to visit the web page: http://compendiumdev.co.uk/selenium/basic web page.html With the page loaded, use the Firebug plugin FireFinder to try out the XPath statements listed. Ill include the listing of the XHTML for the basic web page.html here so you can follow along:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <title>Basic Web Page Title</title> </head> <body> <p id="para1" class="main">A paragraph of text</p> <p id="para2" class="sub">Another paragraph of text</p> </body> </html>
15.3 Selections
15.3.1 Start from root
Start selection from the document node with /, this allows you to create absolute path expressions e.g. /html/body/p Matches all the paragraph element nodes.
assertEquals(2,selenium.getXpathCount("/html/body/p"));
relative path expressions. e.g. //p Matches all paragraph element nodes.
assertEquals(2,selenium.getXpathCount("//p"));
15.4 Predicates
Predicates help make selections more specific and are surrounded by square brackets.
//p[@class=main] Matches the p element node where the value of the attribute class is main.
assertEquals("A paragraph of text", selenium.getText("//p[@class=main]"));
15.6.1 node()
node() matches
any type of node (document, element, attribute) e.g //node()[@id=para1] This matches any node with an id of para1.
assertEquals(1,selenium.getXpathCount("//node()[@id=para1]")); //node() matches //body/node() matches
all the nodes (try it, you may not get the results you expect). all the nodes in the body (again, try it to see if you get the value
you expect).
15.6.2 *
Match anything depending on its position with * e.g. @* Matches any attribute. //p[@*=para1] Would match the first paragraph
assertEquals(1,selenium.getXpathCount("//p[@*=para1]")); * can
15.7.1 and
//p[starts-with(@id,para) and contains(.,Another)] Find all paragraphs where the id starts with para and the text contains Another i.e. the second paragraph.
assertEquals("Another paragraph of text", selenium.getText( "//p[starts-with(@id,para) and contains(.,Another)]"));
15.7.2 or
//*[@id=para1 or @id=para2] Find any node where the id is para1 or the id is para2 i.e. our two paragraphs.
assertEquals(2, selenium.getXpathCount("//*[@id=para1 or @id=para2]"));
15.8.1 contains()
contains() allows
you to match the value of attributes and elements based on text anywhere in the comparison item e.g. //p[contains(.,text)] Match any paragraph with text in the main paragraph e.g. Both our paragraphs
assertEquals(2, selenium.getXpathCount("//p[contains(.,text)]")); //p[contains(.,Another)]
Match any paragraph with Another in the paragraph text, in our example this would match the second paragraph.
assertEquals("Another paragraph of text", selenium.getText("//p[contains(.,Another)]"));
//p[contains(@id,1)] This would match any paragraph where the id had 1 in it, in our example this is the first paragraph
assertEquals("A paragraph of text", selenium.getText("//p[contains(@id,1)]"));
15.8.2 starts-with()
starts-with() allows
you to match the value of attributes and elements based on text at the start of the comparison item e.g. //*[starts-with(.,Basic)] Would match any node where the contents of that node start with Basic, in our example this would match the title.
assertEquals("Basic Web Page Title", selenium.getText("//*[starts-with(.,Basic)]")); //*[starts-with(@id,p)]
This would match any node where the id name started with p, in our example this would match the paragraphs.
assertEquals("Basic Web Page Title", selenium.getText("//*[starts-with(.,Basic)]"));
functions.asp
2http://msdn.microsoft.com/en-us/library/ms256115.aspx 3http://www.xmlpitstop.com/ListTutorials/DispContentType/XPath/PageNumber/1.aspx
Because only XPath locators start with // it is possible to write XPath locators without adding xpath= on the front. e.g.
selenium.isElementPresent("//p[@id=p1]") The specific XPath command getXpathCount expects
an XPath statement as its argument so you should not use xpath= in front of the XPath locator. Possibly a good reason for not using xpath= in any of your locators, but each of us has personal coding styles so you get to make a choice as to which you prefer. e.g.
selenium.getXpathCount("//p"); //return a count of the p elements
You can combine the XPath statement in the getAttribute statement to get specific attributes from elements e.g.
assertEquals("p2", selenium.getAttribute("xpath=//p[2]@id")); assertEquals("p2",selenium.getAttribute("//p[2]@id"));
The @id (or more specifically @<attribute-name>) means that the statement is not valid XPath but Selenium parses the locator and knows to split off the @id on the end before using it.