ctrlcv-dev.comgithub

Xpathcheatsheet

贡献者:BAI

测试工具

Xpath 测试工具

在浏览器的 Console 中测试

JS
$x("//div");

选择器

后代选择器

CSSXpath?
h1//h1?
div p//div//p?
ul > li//ul/li?
ul > li > a//ul/li/a
div > *//div/*
----------
:root/?
:root > body/body

属性选择器

CSSXpath?
#id//*[@id="id"]?
.class//*[@class="class"] ...kinda
input[type="submit"]//input[@type="submit"]
a#abc[for="xyz"]//a[@id="abc"][@for="xyz"]?
a[rel]//a[@rel]
----------
a[href^='/']//a[starts-with(@href, '/')]?
a[href$='pdf']//a[ends-with(@href, '.pdf')]
a[href*='://']//a[contains(@href, '://')]
a[rel~='help']//a[contains(@rel, 'help')] ...kinda

顺序选择器

CSSXpath?
ul > li:first-child//ul/li[1]?
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()]

相邻节点(Sibling)选择器

CSSXpath?
h1 ~ ul//h1/following-sibling::ul?
h1 + ul//h1/following-sibling::ul[1]
h1 ~ #id//h1/following-sibling::[@id="id"]

jQuery

CSSXpath?
$('ul > li').parent()//ul/li/..?
$('li').closest('section')//li/ancestor-or-self::section
$('a').attr('href')//a/@href?
$('span').text()//span/text()

其他

CSSXpath?
h1:not([id])//h1[not(@id)]?
Text match//button[text()="Submit"]?
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]?
Union (joins results)`//a//div`?

类检查

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).

表达式

步和轴

//ul/a[@id='link']

XPath 前缀

前缀示例说明
////hr[@class='edge']任何位置
././a相对位置
//html/body/div根元素

轴(Axis)

示例说明
///ul/li/a直接后代
////[@id="list"]//a全部后代

/ 选取直接的后代. 用 // 选择全部后代

步(Steps)

XPATH
//div
//div[@name='box']
//[@id='link']

每一"步"可以有一个元素名和一个谓词。都是可选的。

BASH
//a/text()
//a/@href
//a/*

谓词(Predicate)

谓词

BASH
//div[true()]
//div[@class="head"]
//div[@class="head"][@id="top"]

操作符

BASH
//a[@id = "xyz"]
//a[@id != "xyz"]
//a[@price > 25]
BASH
# 与或非
//div[@id="head" and position()=2]
//div[(x and y) or not(z)]

使用节点

BASH
# 在函数中使用
//ul[count(li) > 2]
//ul[count(li[@class='hide']) > 0]
BASH
# 下面结果返回有 li 标签的 ul
//ul[li]

你也可以在节点中使用谓词

索引

BASH
//a[1] # 第一个 <a>
//a[last()] # 最后一个 <a>
//ol/li[2] # 第二个 <li>
//ol/li[position()=2] # 同上
//ol/li[position()>1] # 不是第一个元素,同 :not(:first-child)

链的顺序

BASH
a[1][@href='/']
a[@href='/'][1]

前后顺序是很重要的,上面两个的结果是不一样的

嵌套谓词

BASH
//section[.//h1[@id='hi']]

上面的结果返回子节点中含有 id='hi' 属性的 <h1><section>

函数

节点函数

BASH
name() # //[starts-with(name(), 'h')]
text() # //button[text()="Submit"]
# //button/text()
lang(str)
namespace-uri()
BASH
count() # //table[count(tr)=1]
position() # //ol/li[position()=2]

布尔函数

BASH
not(expr) # button[not(starts-with(text(),"Submit"))]

字符串函数

BASH
contains() # font[contains(@class,"head")]
starts-with() # font[starts-with(@class,"head")]
ends-with() # font[ends-with(@class,"head")]
BASH
concat(x,y)
substring(str, start, len)
substring-before("01/02", "/") #=> 01
substring-after("01/02", "/") #=> 02
translate()
normalize-space()
string-length()

类型转换

BASH
string()
number()
boolean()

轴(Axis)

轴的使用示例

BASH
//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 | | 轴 | 步 | 轴 | 步 |

子轴

BASH
# 下面两种写法等效
//ul/li/a
//child::ul/child::li/child::a
BASH
# 下面两种写法等效
# 下面的能成功执行时因为 `child::li` 是正确的,所以谓词成立
//ul[li]
//ul[child::li]
BASH
# 下面两种写法等效
//ul[count(li) > 2]
//ul[count(child::li) > 2]

Descendant-or-self 轴

BASH
# 下面两种写法等效
//div//h4
//div/descendant-or-self::h4

//descendant-or-self:: 轴的简写.

BASH
# 下面两种写法等效
//ul//[last()]
//ul/descendant-or-self::[last()]

其他的轴

缩写说明
ancestor
ancestor-or-self
---------
attribute@@hrefattribute::href 的缩写
childdivchild::div 的缩写
descendant
descendant-or-self/////descendant-or-self::node()/ 的缩写
namespace
---------
self..self::node() 的缩写
parent....parent::node() 的缩写
---------
following
following-sibling
preceding
preceding-sibling

联合(Union)

BASH
//a | //span

可以使用 | 来结合两个表达式

更多的示例

示例

BASH
//* # 全部元素
count(//*) # 统计全部元素数量
(//h1)[1]/text() # 第一个 H1 标签中的文字
//li[span] # 找到包含 <span> 的 <li> 标签
//ul/li/.. # 使用 '..' 去选择父级元素

寻找父级元素

BASH
//section[h1[@id='section-name']]

找一个直接包含h1#section-name<section>

BASH
//section[//h1[@id='section-name']]

找一个直接包含 h1#section-name<section>(可以不是直接子节点)

查找最近子节点

BASH
./ancestor-or-self::[@class="box"]

属性

BASH
//item[@price > 2*@discount]