XPath常见表达式

浏览器控制台的调试方法:

$x('XPath表达式')
demo html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>常见的XPath表达式</title>
</head>
<body>
    <h1>常见的XPath表达式</h1>
    <div id="myDiv">
        <button class="my-unique-button">class是独一无二的button</button>
        <button id="myUniqueButton">id是独一无二的button</button>
        <button>独一无二</button>    
        <button>button内容</button>
        <p>p内容</p>
    </div>
    <button>1</button>
    <button>2</button>

    <button data-type="myType">button</button>
    <button>button内容<span>还有其它内容呢</span></button>

    <div class="myDiv">
        <span>span内容</span>
        <p>p内容</p>
    </div>
    <span>没有任何属性的span</span>
    <span class="text">span内容</span>

    <ul id="ul1">
        <li>li内容1</li>
        <li>li内容2</li>
        <li>li内容3</li>
        <li>li内容4</li>
        <li>li内容5</li>
    </ul>

    <ul id="ul2">
        <li>li内容1</li>
        <li>li内容2</li>
        <li>li内容3</li>
        <li>li内容4</li>
        <li>li内容5</li>
    </ul>

    <ul id="ul3">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
        <li>6</li>
        <li>7</li>
        <li>8</li>
        <li>9</li>
        <li>10</li>
    </ul>

    <ul id="ul4">
        <li>1.<span>haha</span></li>
        <li>2.<span>haha</span></li>
        <li>3.<span>haha</span></li>
        <li>4.<span>haha</span></li>
        <li>5.<span>haha</span></li>
        <li>6.<span>haha</span></li>
        <li>7.<span>haha</span></li>
        <li>8.<span>haha</span></li>
        <li>9.<span>haha</span></li>
        <li>10.<span>haha</span></li>
    </ul>

    <div class="container1">container1</div>
    <div id="container1" class="container1">container2</div>
    <div class="container2">container2</div>

    <div class="product-books">books</div>
    <div class="product-movies">movies</div>
    <div class="product-music">music</div>

    <div id="myDiv2">test for string()<span>span内容</span></div>
</body>
</html>
常见的XPath表达式
找到页面的所有button元素
//button
有data-type这个属性就可以了,不在乎该属性的值是什么
//button[@data-type]
拥有任意属性的span元素
////span[@*]

//button[@class='my-unique-button']

//button[@id='myUniqueButton']

//button[text()='独一无二']

//div[@id='myDiv']/button

//div[@id='myDiv']/following-sibling :: button[1]

根据button里面的文本内容,text()只考虑它自己的文本内容,不考虑它的后代元素的内容
//button[text()="button内容"]

绝对路径与相对路径
绝对路径
html/body/div/p
相对路径
//div/p
*:所有元素
//div[@class="myDiv"]/*
.:当前节点
..:父节点
谓语(Predicates)筛选
位置索引
//ul[@id="ul1"]/li[1]
//ul[@id="ul1"]/li[position() < 4]

属性筛选(带@属性的)
//div[@id='myDiv']

文本筛选(有等号的)
//button[text()='独一无二']


//表达式(带括号的)
//div[not(@class="container1")]
//div[contains(@class, "product")]
//button[contains(text(), "独一无二")]

//button[starts-with(@class, "my")]
//button[starts-with(text(), "独一无二")]
位置索引和集合运算符,位置索引是从1开始计数的而不是0,最后一个的位置索引是last()而不是-1
选择第一个和最后一个
//ul[@id="ul1"]/li[1] | //ul[@id="ul1"]/li[last()]
position的使用
//ul[@id="ul1"]/li[position() < 4]
圆括号的使用:
//ul/li[2]和(//ul/li)[2]
//ul/li[2]会匹配任意的ul下面的第二个li,所以这会显示多个li,假如有多个ul
(//ul/li)[2]会把任意ul下面的li放入一个整体,例如放入一个列表,所以最终这只会显示一个li,因为所有符合条件的li已经放入一个整体了


运算
比较运算符:> = < !> != !<
//ul[@id="ul1"]/li[position() < 4]

算术运算:+ - * div mod
这里.用于表示li本身,实际上表示的的li本身的文本内容,最终选择的是li本身的文本内容%2=1的元素
取余
//ul[@id="ul3"]/li[. mod 2 = 1]
除法
//ul[@id="ul3"]/li[. div 3 = 1]

//ul[@id="ul4"]/li[number(substring-before(normalize-space(node()[1]), '.')) mod 2 = 0]
1. node()[1]:获取 li 下面的第一个子节点(即包含数字和点号的文本节点,如 "1."),避开后面的 <span> 标签。
2. normalize-space(...):去除可能存在的空格或换行符,确保文本干净。
3. substring-before(..., '.'):截取点号 . 字符之前的内容,得到纯数字的字符串(例如将 "2." 变成 "2")。
4. number(...):将字符串转换为数值类型。
5. mod 2 = 0:判断该数值是否为偶数。

逻辑运算符:and or not
//div[@id="container1" and @class="container1"]
not的用法(必须将要取反的内容用圆括号 () 包裹起来)
//ul[@id="ul1"]/li[not(position() < 4)]
//div[not(@class="container1")]
//div[@class="container1" or @class="container2"]
最终返回的是true或者false:
//div[@class="container1"] or //div[@class="container2"] 
函数
text() 当前元素本身的文本,包括换行之类的空白符
//div[@id="myDiv2" and text()="test for string()"]
string() 既包含了元素本身的文本,也包含了后代所有元素的文本
//div[@id="myDiv2" and contains(string(), "span内容")]
//div[@id="myDiv2" and contains(string(), "test for string()")]
测试轴的html:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>XPath 13 轴演示页面</title>
    <style>
        body { font-family: Arial, sans-serif; padding: 20px; line-height: 1.6; }
        div { margin: 8px 0; padding: 10px; border: 1px dashed #aaa; border-radius: 4px; }
        .target { background-color: #fff9c4; border: 2px solid #fbc02d; font-weight: bold; }
    </style>
</head>
<body>

    <!-- 爷爷节点 (ancestor) -->
    <div id="grandparent">爷爷节点 (Grandparent)
        
        <div id="uncle1">叔叔1节点 (Uncle1)</div>
        
        <!-- 父亲节点 (ancestor / parent) -->
        <div id="parent">父亲节点 (Parent)
            
            <!-- 前面的同级节点 (preceding-sibling) -->
            <p id="prev-sib">前面兄弟节点 (Preceding-sibling)</p>
            
            <!-- 【当前节点 / Context Node】 -->
            <div id="target" class="box" data-id="999">
                当前节点 (Target / Context Node)
                <span id="child-1">子节点 1 (Child / Descendant)</span>
                <div id="child-div">
                    <span id="grandchild">孙子节点 (Descendant)</span>
                </div>
            </div>
            
            <!-- 后面的同级节点 (following-sibling) -->
            <p id="next-sib-1">后面兄弟节点 1 (Following-sibling)</p>
            <div id="next-sib-2">后面兄弟节点 2 (Following-sibling)
                <span id="niece">侄子节点 (Following)</span>
            </div>
            
        </div>
        <div id="uncle2">叔叔2节点 (Uncle2)</div>
    </div>

</body>
</html>
13种轴
1. 向下/子孙方向的轴

所有直接子节点,child::是默认的,所以可以省略不写
//*[@id="target"]/child::*
所有直接子节点和后续的任意后代节点
//*[@id="target"]/descendant::*
自身节点和所有直接子节点和后续的任意后代节点
//*[@id="target"]/descendant-or-self::*

2. 向上/祖先方向的轴

父节点
//*[@id="target"]/parent::*
可以通过给定元素类型进行过滤:
//a/parent::p
父节点和任意祖先节点(一直到html,如果有的话)
//*[@id="target"]/ancestor::*
自身节点和父节点和任意祖先节点(一直到html,如果有的话)
//*[@id="target"]/ancestor-or-self::*

3. 同级方向的轴(兄弟节点)

(后面的兄弟):同一层级中在当前节点之后的节点
//*[@id="target"]/following-sibling::*
(前面的兄弟):同一层级中在当前节点之前的节点
//*[@id="target"]/preceding-sibling::*

4. 文档顺序方向的轴

(文档中后续的所有节点):当前标签结束之后,整个 HTML 文档中所有的节点(不含祖先)
//*[@id="target"]/following::*
(文档中前面的所有节点):当前标签开始之前,整个 HTML 文档中所有的节点(不含祖先)
//*[@id="target"]/preceding::*

5. 其他特殊轴
self(自身节点)
//*[@id="target"]/self::*
attribute(属性节点):获取当前节点的所有属性(attribute::* 等于@)
//*[@id="target"]/attribute::*
//*[@id="target"]/@*
namespace(命名空间轴)
说明:用于 XML 命名空间(如带有 xmlns:prefix 的文档)。在普通的 HTML5 网页中几乎用不到,一般会返回空。


::后面可以加元素类型限制条件

//td[text()="颜色"]/preceding-sibling::*/input
//td[text()="颜色"]/following-sibling::td/input

// not、and
//div[@class="ant-card"]//ul/li[not(contains(@title, "一页")) and not(contains(string(), "跳至"))]

其它参考XPath表达式:

提取有title并且title是数字的li
//ul[@class="ant-pagination ant-table-pagination"]/li[@title and string(number(@title)) = @title]

关闭弹窗
//div[not(.//input[contains(@placeholder, "请输入")])]//*[contains(@class, "close")]
在 XPath 中,.//input 的核心意思是:在当前 div 的内部(所有后代中)查找 <input> 标签。

//*[contains(@class,"close")]/ancestor::div[not(contains(@placeholder,"请输入"))]/*[contains(@class,"close")]
//*[contains(@data-testid,"close")]/ancestor:: div[not(contains (@placeholder, "请输入"))]/*[contains(@data-testid,"close")]
处理SVG
先选择离这些svg比较近的div,然后通过local-name()或name()来选中该svg
//div[@class="gb_D"]//*[local-name()="svg"]
获取那些没有svg作为后代元素的li
//ul[@class="ant-pagination ant-table-pagination"]/li[@title and not(.//*[local-name()="svg"])]
获取属性和文本值
获取属性值
//*[@id="myDiv"]/button[1]/@class
获取button自身的文本,不包含它的后代元素的文本
/html/body/button[4]/text()
获取button自身的文本,包含它的后代元素的文本
string(/html/body/button[4])
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容