抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

摘要:本文学习了如何使用XPath在XML文档中定位和选择节点。

1 简介

XPath(XML Path Language)是一门在XML文档中查找信息的语言,用于导航和查询XML文档中的节点。

2 版本

2.1 XPath 1.0

1999年,与XSLT 1.0XQuery1.0配套。

特点:

  • 最基础、应用最广泛的版本,几乎所有支持XPath的工具都兼容此版本。
  • 支持XML节点的基本选择,提供简单的函数。
  • 仅支持四种简单数据类型(字符串、节点集、布尔值、数字),不支持复杂数据结构(序列、映射),函数数量较少。

2.2 XPath 2.0

2007年,与XSLT 2.0XQuery 1.0配套。

特点:

  • 引入了序列(Sequence)概念,支持多个值。
  • 增强数据类型,支持整数、浮点数、日期、时间等更精细的类型,并且支持类型检查。
  • 新增数百个函数,包括字符串处理,正则表达式、数学运算、集合操作等等。
  • 可兼容1.0的语法,但部分行为(比如节点集处理)有调整。

2.3 XPath 3.0

2014年,与XSLT 3.0XQuery 3.0配套。

特点:

  • 进一步强化函数式编程能力,支持传递和定义匿名函数。
  • 新增数组(Array)和映射(Map)数据结构,支持更复杂的数据组织。
  • 扩展字符串和正则表达式功能,支持多行字符串处理。
  • 引入模块(Module)机制,方便函数复用。

2.4 XPath 3.1

2017年,与XSLT 3.0XQuery 3.1配套。

特点:

  • 在3.0基础上增加对JSON的原生支持,可直接解析和操作JSON数据。
  • 增强数组和映射的操作函数,完善类型系统。

3 概念

XPath的核心概念:

  • 节点(Node):XML文档中的每个部分都可以看做节点
  • 表达式(Expression):选择节点的路径表达式
  • 轴(Axis):定义节点间的关系

XPath将XML文档视为节点树,包含七种节点类型:

  • 根节点(Root Node):节点树的起点,包含所有节点,无父节点,唯一的顶层节点。
  • 元素节点(Element Nodes):节点数的核心节点,包含子元素。
  • 属性节点(Attribute Nodes):元素的属性,包含属性名和属性值。
  • 文本节点(Text Nodes):元素的内容,包含文本内容。
  • 命名空间节点 (Namespace Nodes):XML文档中的命名空间声明。
  • 处理指令节点 (Processing Instruction Nodes):XML文档中的处理指令。
  • 注释节点 (Comment Nodes):XML文档中的注释。

节点之间的关系:

  • 父节点(Parent):每个元素和属性都有一个父节点
  • 子节点(Children):元素节点可有零个、一个或多个子节点
  • 兄弟节点(Siblings):拥有相同父节点的节点
  • 祖先节点(Ancestors):当前节点的直接父节点和间接父节点
  • 后代节点(Descendants):当前节点的直接子节点和间接子节点

4 案例

以一个简单的XML文档为例:

school.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?xml version="1.0" encoding="UTF-8"?>
<school address="北京市海淀区">
<name>阳光小学</name>
<teachers>
<teacher id="teacher_1">
<name>李明</name>
<subject>语文</subject>
</teacher>
<teacher id="teacher_2">
<name>赵强</name>
<subject>数学</subject>
</teacher>
</teachers>
<students>
<student id="student_1">
<name>张婷</name>
<gender></gender>
<age>13</age>
<hobbies>
<hobby>画画</hobby>
<hobby>弹琴</hobby>
</hobbies>
</student>
<student id="student_2">
<name>王浩</name>
<gender></gender>
<age>14</age>
<hobbies>
<hobby>跑步</hobby>
<hobby>游泳</hobby>
</hobbies>
</student>
</students>
</school>

测试网站:
https://magictool.ai/tool/xpath-tester/zh/

5 语法

5.1 表达式

XPath使用表达式来选取XML文档中的节点或节点集。

语法:

xpath
1
轴名称::节点测试[谓语]

5.2 选择器

5.2.1 本选择器

5.2.1.1 基础

基础:

  • /:根节点,匹配子节点
  • //:任意元素节点,匹配后代节点
  • .:当前节点位置
  • ..:父节点位置
  • @:属性节点

示例:

  • 使用/school获取根节点
  • 使用/school/name获取school根节点的name子节点
  • 使用/school//name获取school根节点的name后代节点
  • 使用//name获取所有的name元素节点
  • 使用//@address获取所有的address属性节点
5.2.1.2 谓语

谓语:

  • []:查找特定元素节点,多个需要同时满足

示例:

  • 使用//student[@student_id='1']获取student_id属性为1student元素节点
  • 使用//student[@student_id][@student_id='1']获取student_id属性存在并且teacher_id属性为1student元素节点
5.2.1.3 通配符

通配符:

  • *:任意元素节点
  • @*:任意属性节点
  • node():任意子节点,包括元素节点和属性节点,以及文本节点

示例:

  • 使用//hobbies/*获取所有hobbies元素节点的hobby元素节点
  • 使用//@*获取所有属性节点
  • 使用//name/node()获取所有name元素节点的所有节点
5.2.1.4 多选择器

多选择器:

  • |:查找多个条件匹配的节点

示例:

  • 使用//teacher[@teacher_id='1'] | //teacher[@teacher_id='2']获取teacher_id属性为12teacher元素节点
5.2.1.5 运算符

运算符:

  • 数学运算符:支持数学加减乘除运算符
  • 比较运算符:支持比较运算符
  • 条件运算符:支持条件运算符

示例:

  • 使用//teacher[@teacher_id and @teacher_id='1']获取teacher_id属性存在并且teacher_id属性为1teacher元素节点
  • 使用//teacher[@teacher_id='1' or @teacher_id='2']获取teacher_id属性为12teacher元素节点
  • 使用//teacher[@teacher_id and not(@teacher_id='1')]获取有teacher_id属性并且teacher_id属性不为1teacher元素节点

5.2.2 位置选择器

函数:

  • last():获取最后一个元素节点
  • position():获取节点位置,从1开始
  • count():计算节点数量

示例:

  • 使用//teacher[1]获取第一个teacher元素节点
  • 使用//teacher[last()]获取最后一个teacher元素节点
  • 使用//teacher[position()<3]获取前两个teacher元素节点
  • 使用count(//teacher)获取teacher元素节点数量

5.2.3 文本选择器

函数:

  • text():获取节点文本内容
  • contains(字符串1, 字符串2):检查字符串1是否包含字符串2,返回布尔值

示例:

  • 使用//subject[text()="语文"]获取文本内容等于语文subject元素节点
  • 使用//subject[contains(text(), "语文")]获取文本内容包含语文subject元素节点

5.3 轴

轴用于定义相对于当前节点的节点集,使用轴能够基于元素之间的关系进行导航。

常用轴名称:

  • child:当前节点的所有子节点
  • parent:当前节点的父节点
  • ancestor:当前节点的所有祖先节点
  • descendant:当前节点的所有后代节点
  • following-sibling:当前节点之后的所有兄弟节点
  • preceding-sibling:当前节点之前的所有兄弟节点
  • attribute:当前节点的所有属性
  • namespace:当前节点的所有命名空间节点

示例:

  • 使用//teachers/child::teacher获取teachers元素节点的所有teacher子节点

评论