--- title: Xpath category: HTML tags: [Featured] weight: -5 description: | $x('//div//p//*') == $('div p *'), $x('//[@id="item"]') == $('#item'), and many other Xpath examples. --- ## Testing ### Xpath test bed {: .-intro} Test queries in the Xpath test bed: - [Xpath test bed](http://www.whitebeam.org/library/guide/TechNotes/xpathtestbed.rhtm) _(whitebeam.org)_ ### Browser console ```js $x("//div") ``` Works in Firefox and Chrome. ## Selectors ### 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` | | {: .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, '://')]` | | | `a[rel~='help']` | `//a[contains(@rel, 'help')]` *...[kinda](#class-check)* | | {: .xp} ### Order selectors | CSS | Xpath | ? | | ---- | ---- | -- | | `ul > li:first-of-type` | `//ul/li[1]` | [?](#indexing) | | `ul > li:nth-of-type(2)` | `//ul/li[2]` | | | `ul > li:last-of-type` | `//ul/li[last()]` | | | `li#id:first-of-type` | `//li[1][@id="id"]` | [?](#chaining-order) | | `a:first-child` | `//*[1][name()="a"]` | | | `a:last-child` | `//*[last()][name()="a"]` | | {: .xp} ### Siblings | CSS | Xpath | ? | | ---- | ---- | -- | | `h1 ~ ul` | `//h1/following-sibling::ul` | [?](#using-axes) | | `h1 + ul` | `//h1/following-sibling::ul[1]` | | | `h1 ~ #id` | `//h1/following-sibling::[@id="id"]` | | {: .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()` | | {: .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) | {: .xp} ### Class check ```bash //div[contains(concat(' ',normalize-space(@class),' '),' foobar ')] ``` 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/)). Expressions ----------- ### Steps and axes | `//` | `ul` | `/` | `a[@id='link']` | | Axis | Step | Axis | Step | {: .-css-breakdown} ### Prefixes | Prefix | Example | What | | --- | --- | --- | | `//` | `//hr[@class='edge']` | Anywhere | | `./` | `./a` | Relative | | `/` | `/html/body/div` | Root | {: .-headers} Begin your expression with any of these. ### Axes | Axis | Example | What | | --- | --- | --- | | `/` | `//ul/li/a` | Child | | `//` | `//[@id="list"]//a` | Descendant | {: .-headers} Separate your steps with `/`. Use two (`//`) if you don't want to select direct children. ### Steps ```bash //div //div[@name='box'] //[@id='link'] ``` A step may have an element name (`div`) and [predicates](#predicate) (`[...]`). Both are optional. They can also be these other things: ```bash //a/text() #=> "Go home" //a/@href #=> "index.html" //a/* #=> All a's child elements ``` Predicates ---------- ### Predicates ```bash //div[true()] //div[@class="head"] //div[@class="head"][@id="top"] ``` Restricts a nodeset only if some condition is true. They can be chained. ### Operators ```bash # Comparison //a[@id = "xyz"] //a[@id != "xyz"] //a[@price > 25] ``` ```bash # Logic (and/or) //div[@id="head" and position()=2] //div[(x and y) or not(z)] ``` Use comparison and logic operators to make conditionals. ### Using nodes ```bash # Use them inside functions //ul[count(li) > 2] //ul[count(li[@class='hide']) > 0] ``` ```bash # This returns `