在 Web 开发和自动化测试中,XPath 是一个非常强大的工具,允许开发者和测试人员以精确和灵活的方式选择和操作 XML 和 HTML 文档中的数据。
XPath 使用路径表达式来选择节点或节点集。这些表达式类似于文件系统中的路径,指定了到目标节点的路径。
一、常用定位符号
使用XPATH定位页面上的元素时,常用的有下面符号:
从文档的任何位置开始查找
//
- 从文档的任何位置开始查找元素:
使用 //
表示对整个 HTML 文档进行搜索,而不是从特定节点开始。
例如,//div
会匹配页面上的所有 <div>
元素。
从根节点或相对于当前节点的直接子节点开始查找
/
- 从根节点或相对于当前节点的直接子节点开始查找:
当位于表达式的开头时,它表示从根节点(即 HTML 文档的最顶层)开始搜索。
当用在两个节点名称之间时,如 A/B
,它表示选择 A
节点的直接子节点 B
。
当前节点
.
- 代表当前节点:
在 XPath 中,.
表示当前节点。这在使用相对路径时特别有用。
当前节点的父节点
..
- 代表当前节点的父节点:
用于向上移动到当前节点的父节点。
选择属性
@
- 用于选择属性:
用于选择元素的属性。例如,//@id
将选择所有具有 id
属性的元素。
任何元素节点
*
- 代表任何元素节点
例如,//*
将选择文档中的所有元素,而 div/*
将选择所有作为 <div>
直接子元素的节点。
条件
[ ]
- 条件:
用于在查找元素时提供额外条件。例如,//div[@class='example']
将匹配所有 class
属性为 "example"
的 <div>
元素。
或操作符
|
- 或操作符:
用于组合多个查询,返回任一查询的结果。例如,//div | //span
将匹配所有的 <div>
和 <span>
元素。
例子: 选择当前节点的任意一级子节点
在 XPath 中,要表示当前节点的任何一级子节点,你可以使用以下两种方法:
使用 *
符号:
如果你想选择当前节点下的所有子节点(无论是直接子节点还是更深层的子节点),你可以使用 *
符号。例如,.*
将会选择当前节点下的所有子节点。
使用 //
符号:
另一种方法是使用 //
符号,当它与点符号 .
结合使用时,含义会稍有不同,它代表从当前位置开始的任何层次的子节点。例如,.//*
会选择当前节点下的所有子节点,无论这些子节点位于哪一层。
这两种方法在不同的情境下有不同的用途。使用 *
时,它只考虑直接子节点。而使用 //
时,它考虑所有后代节点,不论它们的层级深度如何。
二、多种轴(axis)
XPath 使用轴来定义节点的相对位置(如子节点、父节点、同级节点等)。
祖先及父节点轴
选择当前节点的祖先及父节点
祖先节点
包括:
ancestor
: 选取当前节点的所有祖先节点。ancestor-or-self
: 选取当前节点以及它的所有祖先节点。parent
: 选取当前节点的父节点。
后代节点
包括:
child
: 选取当前节点的直接子节点。descendant
: 选取当前节点的所有后代节点。descendant-or-self
: 选取当前节点以及它的所有后代节点。
例如,//div/descendant::*
将选择所有 <div>
元素内的后代元素。
兄弟及自身节点
包括:
self
: 选取当前节点本身。following-sibling
: 选取当前节点之后的所有兄弟节点,仅限于在当前节点之后的那些兄弟节点。preceding-sibling
: 选取当前节点之前的所有兄弟节点,仅限于在当前节点之前的那些兄弟节点。following
: 选取文档中当前节点的结束标签之后的所有节点,这包括了不仅仅是兄弟节点,还有兄弟的后代、父元素的后续兄弟及其后代等。preceding
: 选取文档中当前节点的开始标签之前的所有节点,这包括了不仅仅是兄弟节点,还有兄弟的后代、父元素的后续兄弟及其后代等。
例如,//div/preceding-sibling::*
将选择所有在文档中出现在任意 <div>
元素之前的兄弟节点。 //div/following-sibling::*
将选择所有跟随在任意 <div>
元素后面的兄弟节点。
属性和命名空间轴
包括:
attribute
或@
: 选取当前节点的所有属性。例如,//div/attribute::*
或//div/@*
将选择所有<div>
元素的所有属性。namespace
: 选取当前节点的所有命名空间节点(主要用于 XML,HTML 中较少使用)。
双冒号
在 XPath 中,双冒号 ::
用作轴名称和节点测试之间的分隔符。它是 XPath 语法的一部分,用于明确指定轴和要在该轴上进行的节点选择。每个轴指定了一个节点集合的相对位置,而双冒号 ::
后面跟随的部分则定义了在这个节点集合中要选取哪些特定类型的节点。
举例来说:
在表达式 ancestor::div
中:
ancestor
是轴名称,表示要选择所有祖先节点。
::
是分隔符,用于分隔轴名称和节点测试。
div
是节点测试,表示在指定轴上选择所有 <div>
元素。
这种结构使得 XPath 表达式既精确又易于理解。通过使用不同的轴和节点测试,你可以创建出非常具体和灵活的查询来选择 XML 或 HTML 文档中的元素。
三、常用函数
XPath 包含了一系列内置函数,这里主要介绍跟文本有关的。
节点的文本内容
text()
: 选择节点的文本内容。
例如,//div/text()
将选择所有 <div>
元素的文本内容。
当前节点的所有子节点
node()
: 选择当前节点的所有子节点,包括元素节点、文本节点和属性节点等。
例如,//div/node()
将选择所有 <div>
元素的子节点。
当前节点集中的最后一个节点
last()
: 函数,返回当前节点集中的最后一个节点的位置。
例如,//(div)[last()]
将选择最后一个 <div>
元素。
父节点中的位置
position()
: 函数,返回当前节点在其父节点中的位置。
例如,//div[position()=1]
将选择每个父元素中的第一个 <div>
元素。
例子:选择最后几个
在 XPath 中,last()
函数用于选择节点集中的最后一个节点。然而,如果你想选择最后几个节点,而不仅仅是最后一个,你需要稍微修改你的 XPath 表达式。
你可以通过结合 last()
函数和位置(position()
)函数来实现这个目的。例如,如果你想选择最后三个 <div>
元素,你可以使用以下 XPath 表达式:
//div[position() >= last()-2]
这个表达式的工作原理如下:
last()
返回节点集中的最后一个节点的位置。position()
返回当前节点在其父节点中的位置。- 通过
position() >= last()-2
,表达式选择位置在倒数第三个或更后的所有<div>
元素。
通过调整 last()-2
中的数字,你可以选择最后任意数量的元素。例如,如果你想选择最后五个元素,你可以使用 last()-4
。这种方法提供了灵活性来选择节点集中的最后几个节点。
包含某个文本
在 XPath 中,如果你想找到一个标签的属性包含特定文本的元素,可以使用 contains()
函数。这个函数允许你检查一个属性值是否包含一些特定的文本。下面是一些示例
假设你想找到所有 class
属性中包含 "example"
文本的 <div>
元素,你可以这样写:
//div[contains(@class, 'example')]
如果你想找到 href
属性包含 "http"
的所有 <a>
标签,你可以使用:
//a[contains(@href, 'http')]
对于一个更通用的例子,如果你想找到任何标签的 id
属性包含 "unique"
文本,你可以使用:
//*[@id][contains(@id, 'unique')]
常用的 XPath 字符比较函数
contains(string1, string2)
:
检查 string1
是否包含 string2
。如果 string1
包含 string2
,则返回 true
;否则返回 false
。
例如,contains('Hello World', 'World')
返回 true
。
starts-with(string1, string2)
:
检查 string1
是否以 string2
开始。如果是,返回 true
;否则返回 false
。
例如,starts-with('Hello World', 'Hello')
返回 true
。
ends-with(string1, string2)
:
在 XPath 2.0 及更高版本中可用
检查 string1
是否以 string2
结尾。如果是,返回 true
;否则返回 false
。
例如,ends-with('Hello World', 'World')
返回 true
。
string-length(string)
:
返回 string
的长度(字符数)。
例如,string-length('Hello')
返回 5
。
normalize-space(string)
:
去除 string
中的前导和尾随空白,并将序列中的空格替换为单个空格。
例如,normalize-space(' Hello World ')
返回 'Hello World'
。
substring(string, start, length)
:
从 string
中提取子字符串,开始于 start
位置,长度为 length
。
例如,substring('Hello World', 7, 5)
返回 'World'
。
translate(string, from, to)
:
在 string
中替换 from
字符集中的字符为 to
字符集中的相应字符。
例如,translate('Hello World', 'od', 'ab')
返回 'Hella Warlb'
。
concat(string1, string2, ...)
:
连接两个或多个字符串。
例如,concat('Hello', ' ', 'World')
返回 'Hello World'
。
upper-case(string)
和 lower-case(string)
:
在 XPath 2.0 及更高版本中可用
分别将字符串转换为大写或小写。
例如,upper-case('Hello')
返回 'HELLO'
,lower-case('Hello')
返回 'hello'
。
这些函数在 XPath 表达式中非常有用,特别是在需要对文本内容进行过滤或者处理时。
四、总结
理解这些符号和它们的用法对于有效使用 XPath 在 Selenium 中进行元素定位是非常重要的。这些基础知识将帮助你编写更精确和灵活的自动化测试脚本。