| title | XPath | |||
|---|---|---|---|---|
| date | 2020-12-19 14:15:43 -0800 | |||
| background | bg-[#77aeeb] | |||
| tags |
|
|||
| categories |
|
|||
| intro | This is an [XPath](https://en.wikipedia.org/wiki/XPath) selectors cheat sheet, which lists commonly used XPath positioning methods and CSS selectors | |||
| plugins |
|
- Xpath test bed (whitebeam.org)
Test in Firefox or Chromium based browser console:
$x('/html/body')
$x('//h1')
$x('//h1')[0].innerText
$x('//a[text()="XPath"]')[0].click()| Xpath | CSS |
|---|---|
//h1 |
h1 |
//div//p |
div p |
//ul/li |
ul > li |
//ul/li/a |
ul > li > a |
//div/* |
div > * |
/ |
:root |
/html/body |
:root > body |
{.show-header}
| Xpath | CSS |
|---|---|
//ul/li[1] |
ul > li:first-child |
//ul/li[2] |
ul > li:nth-child(2) |
//ul/li[last()] |
ul > li:last-child |
//li[@id="id"][1] |
li#id:first-child |
//a[1] |
a:first-child |
//a[last()] |
a:last-child |
{.show-header}
| Xpath | CSS |
|---|---|
//*[@id="id"] |
#id |
//*[@class="class"] |
.class |
//input[@type="submit"] |
input[type="submit"] |
//a[@id="abc"][@for="xyz"] |
a#abc[for="xyz"] |
//a[@rel] |
a[rel] |
//a[starts-with(@href, '/')] |
a[href^='/'] |
//a[ends-with(@href, '.pdf')] |
a[href$='pdf'] |
//a[contains(@href, '://')] |
a[href*='://'] |
//a[contains(@rel, 'help')] |
a[rel~='help'] |
{.show-header}
| Xpath | CSS |
|---|---|
//h1/following-sibling::ul |
h1 ~ ul |
//h1/following-sibling::ul[1] |
h1 + ul |
//h1/following-sibling::[@id="id"] |
h1 ~ #id |
{.show-header}
| Xpath | CSS |
|---|---|
//ul/li/.. |
$('ul > li').parent() |
//li/ancestor-or-self::section |
$('li').closest('section') |
//a/@href |
$('a').attr('href') |
//span/text() |
$('span').text() |
{.show-header}
| Xpath | CSS |
| --------------------------------- | ------------------------- | --------------------- |
| //h1[not(@id)] | h1:not([id]) |
| //button[text()="Submit"] | Text match |
| //button[contains(text(),"Go")] | Text contains (substring) |
| //product[@price > 2.50] | Arithmetic |
| //ul[*] | Has children |
| //ul[li] | Has children (specific) |
| //a[@name or @href] | Or logic |
| //a | //div | Union (joins results) |
{.show-header}
| - | - | - | - |
|---|---|---|---|
// |
ul |
/ |
a[@id='link'] |
| Axis | Step | Axis | Step |
{.left-text}
| Prefix | Example | Means |
|---|---|---|
// |
//hr[@class='edge'] |
Anywhere |
/ |
/html/body/div |
Root |
./ |
./div/p |
Relative |
{.show-header}
| Axis | Example | Means |
|---|---|---|
/ |
//ul/li/a |
Child |
// |
//[@id="list"]//a |
Descendant |
{.show-header}
//div[true()]
//div[@class="head"]
//div[@class="head"][@id="top"]Restricts a nodeset only if some condition is true. They can be chained.
# Comparison
//a[@id = "xyz"]
//a[@id != "xyz"]
//a[@price > 25]# Logic (and/or)
//div[@id="head" and position()=2]
//div[(x and y) or not(z)]# Use them inside functions
//ul[count(li) > 2]
//ul[count(li[@class='hide']) > 0]# Returns `<ul>` that has a `<li>` child
//ul[li]You can use nodes inside predicates.
//a[1] # first <a>
//a[last()] # last <a>
//ol/li[2] # second <li>
//ol/li[position()=2] # same as above
//ol/li[position()>1] #:not(:first-child)Use [] with a number, or last() or position().
a[1][@href='/']
a[@href='/'][1]Order is significant, these two are different.
//section[.//h1[@id='hi']]
This returns <section> if it has an <h1> descendant with id='hi'.
name() # //[starts-with(name(), 'h')]
text() # //button[text()="Submit"]
# //button/text()
lang(str)
namespace-uri()count() # //table[count(tr)=1]
position() # //ol/li[position()=2]contains() # font[contains(@class,"head")]
starts-with() # font[starts-with(@class,"head")]
ends-with() # font[ends-with(@class,"head")]concat(x,y)
substring(str, start, len)
substring-before("01/02", "/") #=> 01
substring-after("01/02", "/") #=> 02
translate()
normalize-space()
string-length()not(expr) # button[not(starts-with(text(),"Submit"))]string()
number()
boolean()//ul/li # ul > li
//ul/child::li # ul > li (same)
//ul/following-sibling::li # ul ~ li
//ul/descendant-or-self::li # ul li
//ul/ancestor-or-self::li # $('ul').closest('li')// |
ul |
/child:: |
li |
| Axis | Step | Axis | Step |
{.left-text}
Steps of an expression are separated by /, usually used to pick child nodes. That's not always true: you can specify a
different "axis" with ::.
# both the same
//ul/li/a
//child::ul/child::li/child::achild:: is the default axis. This makes //a/b/c work.
# both the same
# this works because `child::li` is truthy
//ul[li]
//ul[child::li]# both the same
//ul[count(li) > 2]
//ul[count(child::li) > 2]# both the same
//div//h4
//div/descendant-or-self::h4// is short for the descendant-or-self:: axis.
# both the same
//ul//[last()]
//ul/descendant-or-self::[last()]| Axis | Abbrev | Notes |
|---|---|---|
ancestor |
||
ancestor-or-self |
||
attribute |
@ |
@href is short for attribute::href |
child |
div is short for child::div |
|
descendant |
||
descendant-or-self |
// |
// is short for /descendant-or-self::node()/ |
namespace |
||
self |
. |
. is short for self::node() |
parent |
.. |
.. is short for parent::node() |
following |
||
following-sibling |
||
preceding |
||
preceding-sibling |
{.headers}
There are other axes you can use.
//a | //spanUse | to join two expressions.
//* # all elements
count(//*) # count all elements
(//h1)[1]/text() # text of the first h1 heading
//li[span] # find a <li> with an <span> inside it
# ...expands to //li[child::span]
//ul/li/.. # use .. to select a parent//section[h1[@id='section-name']]Finds a <section> that directly contains h1#section-name
//section[//h1[@id='section-name']]Finds a <section> that contains h1#section-name. (Same as above, but uses descendant-or-self instead of child)
./ancestor-or-self::[@class="box"]Works like jQuery's $().closest('.box').
//item[@price > 2*@discount]Finds <item> and check its attributes
- Devhints (devhints.io)
- Xpath test bed (whitebeam.org)