--- title: Xpath layout: default --- ### Descendant selectors | CSS | Xpath | ? | | ---- | ---- | -- | | `h1` | `//h1` | [?](#prefixes) | | `div p` | `//div//p` | [?](#axes) | | `ul > li` | `//ul/li` | [?](#axes) | | `ul > li > a` | `//ul/li/a` | | | `div > *` | `//div/*` | | | ---- | ---- | -- | | `:root` | `/` | [?](#prefixes) | | `:root > body` | `/body` | | {:.greycode.no-head.xp} ### Attribute selectors | CSS | Xpath | ? | | ---- | ---- | -- | | `#id` | `//[@id="id"]` | [?](#predicates) | | `.class` | `//[@class="class"]` *...[kinda](#class-check)* | | | `input[type="submit"]` | `//input[@type="submit"]` | | | `a#abc[for="xyz"]` | `//a[@id="abc"][@for="xyz"]` | [?](#chaining-order) | | `a[rel]` | `//a[@rel]` | | | ---- | ---- | -- | | `a[href^='/']` | `//a[starts-with(@href, '/')]` | [?](#string-functions) | | `a[href$='pdf']` | `//a[ends-with(@href, '.pdf')]` | | | `a[href~='://']` | `//a[contains(@href, '://')]` *...[kinda](#class-check)* | | {:.greycode.no-head.xp} ### Attribute selectors | CSS | Xpath | ? | | ---- | ---- | -- | | `ul > li:first-child` | `//ul/li[1]` | [?](#indexing) | | `ul > li:nth-child(2)` | `//ul/li[2]` | | | `ul > li:last-child` | `//ul/li[last()]` | | | `li#id:first-child` | `//li[@id="id"][1]` | | | `a:first-child` | `//a[1]` | | | `a:last-child` | `//a[last()]` | | {:.greycode.no-head.xp} ### Siblings | CSS | Xpath | ? | | ---- | ---- | -- | | `h1 ~ ul` | `//h1/following-sibling::ul` | [?](#other-axes) | | `h1 + ul` | `//h1/following-sibling::ul[1]` | | | `h1 ~ #id` | `//h1/following-sibling::[@id="id"]` | | {:.greycode.no-head.xp} ### jQuery | CSS | Xpath | ? | | ---- | ---- | -- | | `$('ul > li').parent()` | `//ul/li/..` | [?](#other-axes) | | `$('li').closest('section')` | `//li/ancestor-or-self::section` | | | `$('a').attr('href')` | `//a/@href` | [?](#steps) | | `$('span').text()` | `//span/text()` | | {:.greycode.no-head.xp} ### Other things | CSS | Xpath | ? | | ---- | ---- | -- | | `h1:not([id])` | `//h1[not(@id)]` | [?](#boolean-functions) | | Text match | `//button[text()="Submit"]` | [?](#operators) | | Text match (substring) | `//button[contains(text(),"Go")]` | | | Arithmetic | `//product[@price > 2.50]` | | | Has children | `//ul[*]` | | | Has children (specific) | `//ul[li]` | | | Or logic | `//a[@name or @href]` | [?](#operators) | | Union (joins results) | `//a | //div` | [?](#unions) | {:.greycode.no-head.xp} ### Class check Xpath doesn't have the "check if part of space-separated list" operator, so this is the workaround ([source](http://pivotallabs.com/xpath-css-class-matching/)): ```sh //div[contains(concat(' ',normalize-space(@class),' '),' foobar ')] ``` Expressions ----------- ### Prefixes Begin your expression with any of these. | Prefix | Example | | --- | --- | | `//` *anywhere* | `//hr[@class='edge']` | | `./` *relative* | `./a` | | `/` *root* | `/html/body/div` | {:.greycode.no-head} ### Axes Separate your steps with `/`. Use two (`//`) if you don't want to select direct children. | Axis | Example | | --- | --- | | `/` *child* | `//ul/li/a` | | `//` *descendant* | `//[@id="list"]//a` | {:.greycode.no-head} ### Steps A step may have an element name (`div`) and [predicates](#predicate) (`[...]`). Both are optional. ```sh //div //div[@name='box'] //[@id='link'] ``` They can also be these other things. ```sh //a/text() #=> "Go home" //a/@href #=> "index.html" //a/* #=> All a's child elements ``` Predicates ---------- ### Predicates (`[...]`) Restricts a nodeset only if some condition is true. They can be chained. ```sh //div[true()] //div[@class="head"] //div[@class="head"][@id="top"] ``` ### Operators Use comparison and logic operators to make conditionals. ```sh # Comparison //a[@id = "xyz"] //a[@id != "xyz"] //a[@price > 25] ``` ```sh # Logic (and/or) //div[@id="head" and position()=2] //div[(x and y) or not(z)] ``` ### Using nodes You can use nodes inside predicates. ```sh # Use them inside functions //ul[count(li) > 2] //ul[count(li[@class='hide']) > 0] ``` ```sh # This returns `