摘要:本文学习了如何使用XPath在XML文档中定位和选择节点。
1 简介
XPath(XML Path Language)是一门在XML文档中查找信息的语言,用于导航和查询XML文档中的节点。
2 版本
2.1 XPath 1.0
1999年,与XSLT 1.0和XQuery1.0配套。
特点:
- 最基础、应用最广泛的版本,几乎所有支持XPath的工具都兼容此版本。
- 支持XML节点的基本选择,提供简单的函数。
- 仅支持四种简单数据类型(字符串、节点集、布尔值、数字),不支持复杂数据结构(序列、映射),函数数量较少。
2.2 XPath 2.0
2007年,与XSLT 2.0和XQuery 1.0配套。
特点:
- 引入了序列(Sequence)概念,支持多个值。
- 增强数据类型,支持整数、浮点数、日期、时间等更精细的类型,并且支持类型检查。
- 新增数百个函数,包括字符串处理,正则表达式、数学运算、集合操作等等。
- 可兼容1.0的语法,但部分行为(比如节点集处理)有调整。
2.3 XPath 3.0
2014年,与XSLT 3.0和XQuery 3.0配套。
特点:
- 进一步强化函数式编程能力,支持传递和定义匿名函数。
- 新增数组(Array)和映射(Map)数据结构,支持更复杂的数据组织。
- 扩展字符串和正则表达式功能,支持多行字符串处理。
- 引入模块(Module)机制,方便函数复用。
2.4 XPath 3.1
2017年,与XSLT 3.0和XQuery 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文档为例:
1 |
|
测试网站:
https://magictool.ai/tool/xpath-tester/zh/
5 语法
5.1 表达式
XPath使用表达式来选取XML文档中的节点或节点集。
语法:
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属性为1的student元素节点 - 使用
//student[@student_id][@student_id='1']获取student_id属性存在并且teacher_id属性为1的student元素节点
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属性为1和2的teacher元素节点
5.2.1.5 运算符
运算符:
- 数学运算符:支持数学加减乘除运算符
- 比较运算符:支持比较运算符
- 条件运算符:支持条件运算符
示例:
- 使用
//teacher[@teacher_id and @teacher_id='1']获取teacher_id属性存在并且teacher_id属性为1的teacher元素节点 - 使用
//teacher[@teacher_id='1' or @teacher_id='2']获取teacher_id属性为1和2的teacher元素节点 - 使用
//teacher[@teacher_id and not(@teacher_id='1')]获取有teacher_id属性并且teacher_id属性不为1的teacher元素节点
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子节点
条