Sunday, May 21, 2017

How to create custom cssSelector Using Different Techniques

 What is CSS selector?

CSS(Cascading Style Sheets) selector is a pattern/locator to identify elements in HTML DOM/web page. The element finding is generally carried out based on different attributes such as name id, name, class and so on. 

CSS selector is used in vast to find web elements in selenium and any java script language based automation.

There are various techniques to create custom CSS selector. I will describe one by one as follows.

1. # cssSelector: This cssSelector refers to id, which will select all element which is having id attribute in the DOM.  

Syntax: 

tagname#id

or

#id

From the below image if we want to find the search box using id selector, we can use 

input#search or # search









2. . cssSelector(dot cssSelector): This cssSelector refers to class, which will select all element which is having class attribute in the DOM.   

Syntax:

tagname.classname

or

.classname

From the below image if we want to find the search box using class selector, we can use 

input.search or .search








3. cssSelector using combination of id and classname: This  cssSelector is build using combination of id and class.

Syntax:

tagname#id.classname

or 

tagname.classname#id

From the below image if we want to find the search box using combination of id and classname selector, we can use

input#search.text or input.text#search 








4. cssSelector using parent and child relationship: This  cssSelector is build using parent and child tags relationship.

Syntax:

parent_tagname>child_tagname

From the below image, we see the parent is div.dd-inner and its corresponding child is ul. So we can establish the relationship between them as  div.dd-inner>ul









5. cssSelector using tagname with single attribute: This cssSelector refers to particular element using the tagname with single attribute value.

Syntax:

tagname[attribute='value']

From the below image if we want to find the search box using tagname and single attribute, we can use

tagname=input, attribute=id and attribute_value=search and combinedly the cssSelector as per syntax  is as follows.

input[id='search']







6. cssSelector using tagname with multiple attribute: This cssSelector refers to particular element using the tagname with multiple attribute value.

Syntax:

tagname[attribute1='value'][attribute2='value']

From the below image if we want to find the search box using tagname and multiple attributes, we can use tagname=input, attribute1=type, attribute1_value=text, attribute2=id, attribute2_value=search and combinedly the cssSelector as per syntax is as follows.

input[type='text'][id='search']


7. cssSelector based on contains text: This cssSelector is used to find element that contains specific text.  It is used *= that means text(regardless of order) contains in element.

Syntax:

tagname[attribute*='abc']

From the below image if we want to select ABOUT US menu, we can use tagname=input and attribute=href with * , attribute_value=aboutus.htm in which contains text outus and combinedly the cssSelector as per syntax is as follows.

input[href*='outus']







8. cssSelector based on starting the textThis cssSelector refers to any attribute, which will select the first portion text of element, it is used ^= that means starts with.

Syntax:

tagname[attribute^='first_text']

From the below image if we want to select ABOUT US menu, we can use tagname=input and attribute=href with ^ , attribute_value=aboutus.htm in which text starts with about and combinedly the cssSelector as per syntax is as follows.

input[href^='about']








9. cssSelector based on ending the textThis cssSelector refers to any attribute, which will select the last portion text of element, it is used $= that means ends with. 

Syntax:

tagname[attribute$='last_text']

From the below image if we want to select ABOUT US menu, we can use tagname=input and attribute=href with $ , attribute_value=aboutus.htm in which text ends with us.htm and combinedly the cssSelector as per syntax is as follows.

input[href$='us.htm']








10. cssSelector  using comma separator: This cssSelector is used combination of more cssSelector using comma separator.

Syntax:

tagname.attribute1.attribute2, tagname.attribute

From the below image if we want to select top header menus, we can use comma separator between two cssSelectors. first tagname=div, attribute=class, attribute_value=menu-icon, second tagname=a, attribute=class, attribute_value=top-heading and combinedly the cssSelector as per syntax is as follows.

div.menu-icon, a.top-heading








11. cssSelector using first-of-type: This cssSelector selects the first element among the number of elements.

Syntax:

tagname#attribute>tagname:first-of-type

From the below image if we want to select the first element ABOUT US among eight headers menu, we can use first-of-type and the cssSelector is as follows.

nav#ddmenu>ul>li:first-of-type











12. cssSelector using last-of-type: This cssSelector selects the last element among the number of elements.

Syntax:

tagname#attribute>tagname:last-of-type

From the below image if we want to select the last element CAREER among eight headers menu, we can use last-of-type and the cssSelector is as follows.

nav#ddmenu>ul>li:last-of-type











13. cssSelector using nth-of-type : This cssSelector selects the element of any position among the number of elements.

If the index of nth-of-type is n, the cssSelector selects all elements.

Syntax:

For the element of any position:

tagname#attribute>tagname:nth-of-type(5)

For all elements:

tagname#attribute>tagname:nth-of-type(n)

From the below image if we want to select the 4th element INDUSTRIES among eight headers menu, we can use nth-of-type and the cssSelector is as follows.

nav#ddmenu>ul>li:nth-of-type(4)











14. cssSelector based on siblings of element: This cssSelector finds the siblings of element. To finds the siblings of an element + operator is used after finding that element.

Syntax:

tagname.attribute+tagname

From the below image if we want to select the siblings of  ABOUT US menu , we can use + operator after selecting ABOUT US menu and the cssSelector is as follows.

nav#ddmenu>ul>li+li











15. cssSelector using not() method: This cssSelector includes not() method. The element which is not required not() method excludes that element. not() method is used after all finding element and : is used before not() method.

Syntax:

tagname.attribute:not(.attribute)

From the below image if we want to exclude top search filed among six text filed elements we need to use :not() method and search filed id is used in :not(#search) method. So the cssSelector is as follows.

input[type='text']:not(#search)














That is the end. I hope this article will help to build custom cssSelector.

Sunday, April 23, 2017

How to create custom xpath Using Different Techniques in Selenium WebDriver

I have discussed about selenium locators in the previous article. Actually xpath is one of the locators. It is very vital to find out different web elements in the web page. Selenium WebDriver supports xpath to locate web elements.  Due to many disadvantages of absolute xpath, most of the cases it is used relative xpath that can be created using different approaches. Here I will discuss about how to create custom/dynamic relative xpath based on various techniques.

1. xpath Using Single Attribute 

Syntax: 

//tagname[@attribute='value']

We can use * instead of tagname as follows.

//*[@attribute='value']

Here, 

// means point to the current node.

tagName means tagName of the particular node, basically HTML/XML tag like <input>, <button>, <image>, <div>, <span>, <table>, <td>, <tr>, <ul>, <li> and so on..

Attribute: one or more attributes may have a particular node. Mostly used some common attributes are id,name, class, href, img, label and so on

@ is used to address any attribute. It is placed prior to the attribute.

Value: value of the attribute.

 * is placed after double slash to match any tag with the expected attribute value or text

Example: 











From the web page as per above image if we want to locate search field using single attribute, the xpath expression is as follows.

//input[@id='search']

* is used instead of tagname.

//*[@id='search'] 

2. xpath Using Multiple Attribute 

Syntax: 

//tagname[@attribute1='attribute1_value'][@attribute2='attribute2_value]

Example:












From the web page as per above image if we want to locate search field using multiple attribute, the xpath expression is as follows.

//input[@id='search'][@name='q']

3. xpath Using and

Syntax: 

//tagname[@attribute1='attribute1_value' and @attribute2='attribute2_value]

Example:












From the web page as per above image if we want to locate search field using and, the xpath expression is as follows.

//input[@type='text' and @id='search']

4. xpath Using or

Syntax: 

//tagname[@attribute1='attribute1_value' or @attribute2='attribute2_value]

Example:














From the web page as per above image if we want to locate search field using or, the xpath expression is as follows.

//input[@id='search' or @name='q']

5. xpath Using Contains() Method

Contains() method is used to find web elements that contain particular attribute or text(full or partial).

Syntax: 

//tagname[contains(@attribute,'attribute_value')]

Example:












From the web page as per above image if we want to locate search field using contains() method, the xpath expression is as follows.

//input[contains(@id,'search')]

6. xpath Using Starts-with() Method

starts-with() method in xpath, identify the element which attribute value starts with given specific character or text. This method is actually used to interact dynamic web elements within the web pages. Suppose an element with attribute value that changes every time during the page loading. These web elements have some common starting characters followed by random dynamic texts. Besides dynamic attribute, starts-with() method can identify static elements as well.

Syntax:

//tag_name[starts-with(@attribute,'starting_with_fixed_part_of_Attribute_value')]

For example, the ID of a particular element changes dynamically such as,

Id="reg_12"

Id="reg_abc"

Id="reg_1ab"

Id="reg_312" and so on.

In this case the first part remains static and second part dynamically changes. We normally use starts-with expression to locate element in this situation. 















From the web page as per above image, there are two web elements(email address and password fields) whose id start with reg_ text that is fixed. To find those elements the xpath expression is as follows.

//input[starts-with(@id,'reg_')]

7. xpath Using ends-with() Method

ends-with() method in xpath, identify the element which attribute value ends with given specific character or text. This method is actually used to interact dynamic web elements within the web pages. Suppose an element with attribute value that changes every time during the page loading. These web elements have random dynamic texts followed by fixed ending characters. Besides dynamic attribute, ends-with() method can identify static elements as well.

Syntax:

//tag_name[ends-with(@attribute,'ending_with_fixed_part_of_Attribute_value')]

For example, the ID of a particular element changes dynamically such as,

Id="12_reg"

Id="abc_reg"

Id="1ab_reg"

Id="312_reg" and so on.

In this case the first part dynamically changes and second part remains static. We normally use ends-with expression to locate element in this situation. 

xpath expression is as follows.

//input[ends-with(@id,'_reg')]

In previous example, we used starts-with approach that is just opposite of ends-with approach. 

8. xpath using Text() Method

text() method is used to find the web element using text or string of the element within the web pages.

Syntax:

//tagname[text()='text or string of the element']

For example, any message, which always contain a static text or string.










From the web page as per above image if we want to locate CONTACT link using text() method, the xpath expression is as follows.

//a[text()='Contact']

9. xpath Using last() Method: 

Find out the last element of mentioned type out of all element present.

Example:























From the web page as per above image, In google sign up form, find out the last text field(last name) we can use following xpath.

(//input[@type='text'])[last()]

or

(//*[@type='text'])[last()]

If we use [last()-1], to find out the last but one element of mentioned type out of all element present.

Example:















From the web page as per above image, in google sign up form, find out the last-1 text field(first name) we can use following xpath.

(//input[@type='text'])[last()-1]

or

(//*[@type='text'])[last()-1]

10. xpath Using position() Method: 

Find out the element based on mentioned position number out of all element present

Example:















From the web page as per above image, in google sign up form, there are 2 input text fields(first name and last name). If we mention the position=2 to find out the desired text field(last name field) in following xpath expression, we can get easily the expected element of 2nd position.

(//input[@type='text'])[position()=2]

11. xpath Using index within Square Bracket:

We can identify the nth element out of all similar type of elements present.

Example:















From the web page as per above image, in google sign up form, there are 2 input text fields(first name and last name). To identify the 1st element(first name field) we have to mention index in square bracket of following  xpath expression.

(//input[@type='text'])[1]

12. xpath axes Methods:

xpath axes methods are used to identify the dynamic elements. There are different types of xpath axes methods such as following, ancestor, ancestor-or-self, child, preceding, following-sibling, preceding-sibling, parent, self, descendant, descendant-or-self and so on.

i) following

following axis finds all nodes present in the DOM after the current node that is the base node. 

Syntax: 

//tagname[attribute='attribute_value']//following::tagname 

//tagname[attribute='attribute_value']//following::attribute

//tagname[attribute='attribute_value']//following::tagname[index]

//tagname[attribute='attribute_value']//following::tagname[@attribute='attribute_value']

When we use following axis in xpath expression, we have to use two colons(::) after following and then the others like attribute or tagname such as input, button, label and so on.

Example:















From the web page as per above image, in google sign up form, to find the input field of type text after the first name field, we have to use the xpath as follows.

//input[@name='firstName']//following::input[@type='text']
















As per above image, there are 6 input fields, to find only the input fields after the first name field, we have to use the xpath as follows.

//input[@name='firstName']//following::input

ii) Preceding:

peceding axis finds all nodes that come before the current node in DOM except ancestors, attribute nodes and namespace nodes.

Syntax:

//tagname[attribute='attribute_value']//preceding::tagname 

//tagname[attribute='attribute_value']//preceding::tagname[index]

//tagname[attribute='attribute_value']//preceding::attribute

When we use preceding axis in xpath expression, we have to use two colons(::) after preceding and then the others like attribute or tagname such as input, button, label and so on.

Example:















From the web page as per above image, in google sign up form, to find the input field of type text before the Show password checkbox, we have to use the xpath as follows.

//input[@type='checkbox']//preceding::input[@type='text']
















As per above web image, there are 6 input fields, to find only the input fields before the Show password checkbox, we have to use the xpath as follows.

//input[@type='checkbox']//preceding::input

iii) ancestor

ancestor axis finds all ancestors(parent, grandparent and so on) of the current node. It may be from parent node up to the root node. 

Syntax:

//tagname[attribute='attribute_value']//ancestor::tagname 

//tagname[attribute='attribute_value']//ancestor::tagname[index]

//tagname[attribute='attribute_value']//ancestor::tagname[@attribute='attribute_value']

When we use ancestor axis in xpath expression, we have to use two colons(::) after ancestor and then the others like attribute or tagname such as input, button, label and so on.

Example:

From the bellow web page, we are looking for ancestors element of the current node.


Here, we are getting 52 "div" nodes matching by using "ancestor" axis. If we want to locate any particular element then we have to use the below xpath using index =1,2,3,... and so on.

//div[@class='innercomencontent']//ancestor::div[index]

iv) ancestor-or-self

ancestor-or-self axis finds the current node and its ancestors(parent, grandparent and so on).

Syntax:

//tagname[attribute='attribute_value']//ancestor-or-self::tagname 

//tagname[attribute='attribute_value']//ancestor-or-self::tagname[index]

//tagname[attribute='attribute_value']//ancestor-or-self::tagname[@attribute='attribute_value']

When we use ancestor-or-self axis in xpath expression, we have to use two colons(::) after ancestor-or-self and then the others like attribute or tagname such as input, button, label and so on.

From the previous example (iii) we see there are 52 "div" nodes matching by using "ancestor" axis. If we use  ancestor-or-self axis instead of  ancestor axis, we can get 53 div nodes including current node as bellow image.











xpath expression:

 //div[@class='innercomencontent']//ancestor-or-self::div

v) child

child axis finds all child elements of the current node.

Syntax:

//tagname[attribute='attribute_value']//child::tagname 

//tagname[attribute='attribute_value']//child::tagname[index]

//tagname[attribute='attribute_value']//child::attribute

When we use child axis in xpath expression, we have to use two colons(::) after child and then the others like attribute or tagname such as input, button, label and so on.

Example:

From the bellow web page, we are looking for child element of the current node("top navigation" div node).


Here, we are getting 6 "li" nodes matching by using "child" axis. If we want to locate CONTACT element then we have to use the below xpath using index=4.

//div[@id='topnav']//ul//child::li[4]

vi) following-sibling

Siblings indicate in xpath expression the same level of a particular node. following-sibling axis finds all siblings after the current node.

Syntax:

//tagname[attribute='attribute_value']//following-sibling::tagname 

//tagname[attribute='attribute_value']//following-sibling::tagname[index]

//tagname[attribute='attribute_value']//following-sibling::attribute

When we use following-sibling axis in xpath expression, we have to use two colons(::) after following-sibling and then the others like attribute or tagname such as input, button, label and so on.

Example:

In the below web page, 2 "p" nodes are highlighted on the same level and both are siblings. If we select the first "p" node as current node(forgot your password?), so the second node(Sign in button) will be the following-sibling of this current node.











 


xpath expression:

//p[@class='lost_password form-group']//following-sibling::p[1]

vii) preceding-sibling

preceding-sibling axis finds all siblings before the current node.

Syntax:

//tagname[attribute='attribute_value']//preceding-sibling::tagname 

//tagname[attribute='attribute_value']//preceding-sibling::tagname[index]

//tagname[attribute='attribute_value']//preceding-sibling::attribute

When we use preceding-sibling axis in xpath expression, we have to use two colons(::) after preceding-sibling and then the others like attribute or tagname such as input, button, label and so on.

Example:

In the below web page, 2 "p" nodes are highlighted on the same level and both are siblings. If we select the second "p" node as current node(Sign in button), so the first node(Forgot your password? link) will be the preceding-sibling of this current node.



 










xpath expression:

//p[@class='submit']//preceding-sibling::p[1]

viii) parent

parent axis finds the parent of the current node.

Syntax:

//tagname[attribute='attribute_value']//parent::tagname 

//tagname[attribute='attribute_value']//parent::tagname[index]

//tagname[attribute='attribute_value']//parent::attribute

When we use parent axis in xpath expression, we have to use two colons(::) after parent and then the others like attribute or tagname such as input, button, label and so on.

Example:

In the below web page, 8 "li" nodes are highlighted on the same level and both are siblings. If we select the any "li" node as current node, so the parent of this current node is as follows image.



 






xpath expression:

//a[@class='top-heading']//parent::li

ix) self

self axis finds the current node. In another word, it represents the node itself.

Syntax:

//tagname[attribute='attribute_value']//self::tagname 

//tagname[attribute='attribute_value']//self::tagname[index]

//tagname[attribute='attribute_value']//self::attribute

When we use self axis in xpath expression, we have to use two colons(::) after self and then the others like attribute or tagname such as input, button, label and so on.

Example:

If we select any node using self axis, it only finds one node as it represents self-element.

From above web image, if we locate Email field using self axis, the xpath expression is as follows.

//*[@id='email']//self::input

x) descendant

descendant axis finds all descendants (children, grandchildren and so on) of the current node. 

Syntax:

//tagname[attribute='attribute_value']//descendant ::tagname 

//tagname[attribute='attribute_value']//descendant ::tagname[index]

//tagname[attribute='attribute_value']//descendant ::attribute

When we use descendant axis in xpath expression, we have to use two colons(::) after descendant and then the others like attribute or tagname such as input, button, label and so on.

Example:

From the bellow web page, we are looking for descendant elements of the current node(<div id="homepagefootersection">).











Here, we are getting 8 "div" nodes matching by using "descendant" axis. If we want to locate any particular element then we have to use the below xpath using index 1,2,3... and so on.

//div[@id='homepagefootersection']//descendant::div[index]

xi) descendant-or-self

descendant-or-self finds the current node and its descendants (children, grandchildren and so on).

Syntax:

//tagname[attribute='attribute_value']//descendant-or-self::tagname 

//tagname[attribute='attribute_value']//descendant-or-self::tagname[index]

//tagname[attribute='attribute_value']//descendant-or-self::tagname[@attribute='attribute_value']

When we use descendant-or-self axis in xpath expression, we have to use two colons(::) after descendant-or-self and then the others like attribute or tagname such as input, button, label and so on.

From the previous example (x) we see there are 8 "div" nodes matching by using "descendant" axis. If we use descendant-or-self axis instead of descendant axis, we can get 9 div nodes including current node(<div id="homepagefootersection">).











xpath expression:

//div[@id='homepagefootersection']//descendant-or-self::div[index]

That is all about different xpath methods. I hope this article will help to build custom xpath.

Sunday, March 19, 2017

Different Locators in Selenium WebDriver

 What is a locator?

Locator basically identifies a web element uniquely within the webpage. Locator can address how to interact with the specific element. Selenium uses locators to find out the specific web element within the web page.

Different Types of Locators in Selenium

  • id
  • cssSelector
  • name
  • className
  • tagName
  • linkText
  • partialLinkText
  • xpath
Using id as locator:
For example, to find out the search box we can use id=search as follows.



                     






Selenium WebDriver with java code to find out search box using id as follows:  
WebElement searchBox=driver.findElement(By.id ("search"));

For Page Object Pattern: 
@FindBy(id=''search") 
public WebElement searchBox;

Using cssSelector as locator:
For example, to find out search box we can use cssSelector=tagName#id as follows.












Selenium WebDriver with java code to find out search box using cssSelector as follows: 
WebElement searchBox= driver.findElement(By.cssSelector("input#search"));

For Page Object Pattern: 
@FindBy(cssSelector=''input#search")
public WebElement searchBox;


Using name attribute as locator:
For example, to find out search box we can use name=q as follows.








Selenium WebDriver with java code to find out search box using name attribute as follows: 
WebElement searchBox= driver.findElement(By.name("q"));

For Page Object Pattern: 
@FindBy(name=''q")
public WebElement searchBox;

Using className as locator:
For example, to find out search box we can use className=text as follows.
















Selenium WebDriver with java code to find out search box using className as follows: 
WebElement searchBox= driver.findElement(By.className("text"));

For Page Object Pattern: 
@FindBy(className=''text")
public WebElement searchBox;


Using tagName as locator:
For example, to find out "About US" menu we can use tagName=a as follows.












Selenium WebDriver with java code to find out "ABOUT US" menu using tagName as follows: 
WebElement aboutUs= driver.findElement(By.tagName("a"));

For Page Object Pattern: 
@FindBy(tagName=''a")
public WebElement aboutUs;

Using linkText as locator:
For example, to find out "BLOG" link we can use linkText=Blog as follows.









Selenium WebDriver with java code to find out "Blog" link using linkText as follows: 
WebElement blogLink= driver.findElement(By.linkText("Blog"));

For Page Object Pattern: 
@FindBy(linkText=''Blog")
public WebElement blogLink;

Using partialLinkText as locator:
For example, to find out "ABOUT US" link we can use partialLinkText=About as follows.








Selenium WebDriver with java code to find out "ABOUT US" link using partialLinkText as follows: 
WebElement aboutUsLink= driver.findElement(By.partialLinkText("About"));

For Page Object Pattern: 
@FindBy(partialLinkText=''About")
public WebElement aboutUsLink;

Using xpath as locator:
In selenium there are two types of xpath.
  1. Absolute xpath
  2. Relative xpath 
Absolute xpath: This xpath is used to find out full path from the root Element(/html/body) to the expected element. Absolute xpath begins with single forward slash(/). 
For example, to find out the search box we can use absolute xpath=/html/body/div[4]/div/div[2]/ul/li[6]/form/input[2] as follows.













Selenium WebDriver with java code to find out SearchBox using absolute xpath as follows: 
WebElement searchBox= driver.findElement(By.xpath("/html/body/div[4]/div/div[2]/ul/li[6]/form/input[2]"));

For Page Object Pattern: 
@FindBy(xpath=''/html/body/div[4]/div/div[2]/ul/li[6]/form/input[2]")
public WebElement searchBox

Absolute xpath has a drawback. If any webElement is added or removed from HTML code in future, then the hierarchy of elements will break, as a result, absolute xpath will not function in this case. So for proper functioning need to build absolute Xpath again as per latest coding structure.

Relative xpath: This xpath starts from the anywhere of HTML DOM structure. Relative xpath begins with double forward slash (//). It can find elements anywhere on the webpage that's why relative xpath is always preferred as it is not a complete path from the root element.

For example, to find out the search box we can use relative xpath=//input[@id='search'] as follows.












Selenium WebDriver with java code to find out SearchBox using relative xpath as follows: 
WebElement searchBox= driver.findElement(By.xpath("//input[@id='search']"));

For Page Object Pattern: 
@FindBy(xpath=''//input[@id='search']")
public WebElement searchBox


%3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20value%3D%22ID%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22260%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%223%22%20value%3D%22Name%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22300%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%224%22%20value%3D%22Link%20Text%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22420%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%225%22%20value%3D%22Partial%20Link%20Text%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22460%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%226%22%20value%3D%22xpath%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22540%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%227%22%20style%3D%22edgeStyle%3DorthogonalEdgeStyle%3Brounded%3D0%3BorthogonalLoop%3D1%3BjettySize%3Dauto%3Bhtml%3D1%3BexitX%3D0.5%3BexitY%3D0%3BexitDx%3D0%3BexitDy%3D0%3B%22%20edge%3D%221%22%20source%3D%228%22%20parent%3D%221%22%3E%3CmxGeometry%20relative%3D%221%22%20as%3D%22geometry%22%3E%3CmxPoint%20x%3D%22245%22%20y%3D%22520%22%20as%3D%22targetPoint%22%2F%3E%3C%2FmxGeometry%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%228%22%20value%3D%22CSS%20Selector%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22500%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%229%22%20value%3D%22class%20name%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22340%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%2210%22%20value%3D%22tag%20name%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22380%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E

%3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20value%3D%22ID%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22260%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%223%22%20value%3D%22Name%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22300%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%224%22%20value%3D%22Link%20Text%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22420%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%225%22%20value%3D%22Partial%20Link%20Text%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22460%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%226%22%20value%3D%22xpath%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22540%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%227%22%20style%3D%22edgeStyle%3DorthogonalEdgeStyle%3Brounded%3D0%3BorthogonalLoop%3D1%3BjettySize%3Dauto%3Bhtml%3D1%3BexitX%3D0.5%3BexitY%3D0%3BexitDx%3D0%3BexitDy%3D0%3B%22%20edge%3D%221%22%20source%3D%228%22%20parent%3D%221%22%3E%3CmxGeometry%20relative%3D%221%22%20as%3D%22geometry%22%3E%3CmxPoint%20x%3D%22245%22%20y%3D%22520%22%20as%3D%22targetPoint%22%2F%3E%3C%2FmxGeometry%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%228%22%20value%3D%22CSS%20Selector%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22500%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%229%22%20value%3D%22class%20name%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22340%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%2210%22%20value%3D%22tag%20name%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22380%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E

%3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20value%3D%22ID%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22260%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%223%22%20value%3D%22Name%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22300%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%224%22%20value%3D%22Link%20Text%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22420%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%225%22%20value%3D%22Partial%20Link%20Text%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22460%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%226%22%20value%3D%22xpath%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22540%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%227%22%20style%3D%22edgeStyle%3DorthogonalEdgeStyle%3Brounded%3D0%3BorthogonalLoop%3D1%3BjettySize%3Dauto%3Bhtml%3D1%3BexitX%3D0.5%3BexitY%3D0%3BexitDx%3D0%3BexitDy%3D0%3B%22%20edge%3D%221%22%20source%3D%228%22%20parent%3D%221%22%3E%3CmxGeometry%20relative%3D%221%22%20as%3D%22geometry%22%3E%3CmxPoint%20x%3D%22245%22%20y%3D%22520%22%20as%3D%22targetPoint%22%2F%3E%3C%2FmxGeometry%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%228%22%20value%3D%22CSS%20Selector%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22500%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%229%22%20value%3D%22class%20name%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22340%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%2210%22%20value%3D%22tag%20name%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22380%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E

%3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20value%3D%22ID%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22260%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%223%22%20value%3D%22Name%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22300%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%224%22%20value%3D%22Link%20Text%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22420%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%225%22%20value%3D%22Partial%20Link%20Text%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22460%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%226%22%20value%3D%22xpath%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22540%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%227%22%20style%3D%22edgeStyle%3DorthogonalEdgeStyle%3Brounded%3D0%3BorthogonalLoop%3D1%3BjettySize%3Dauto%3Bhtml%3D1%3BexitX%3D0.5%3BexitY%3D0%3BexitDx%3D0%3BexitDy%3D0%3B%22%20edge%3D%221%22%20source%3D%228%22%20parent%3D%221%22%3E%3CmxGeometry%20relative%3D%221%22%20as%3D%22geometry%22%3E%3CmxPoint%20x%3D%22245%22%20y%3D%22520%22%20as%3D%22targetPoint%22%2F%3E%3C%2FmxGeometry%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%228%22%20value%3D%22CSS%20Selector%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22500%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%229%22%20value%3D%22class%20name%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22340%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3CmxCell%20id%3D%2210%22%20value%3D%22tag%20name%22%20style%3D%22rounded%3D0%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22190%22%20y%3D%22380%22%20width%3D%22110%22%20height%3D%2230%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E