XPath(XML Path Language)是一种用于在 XML 文档中定位和选择节点的语言。它提供了一种简洁而强大的方式来查询 XML 文档中的数据,类似于 SQL 在关系数据库中的作用。
XPath 的基本概念
节点类型
XPath 将 XML 文档视为节点树,包含以下节点类型:
- 元素节点:XML 元素
- 属性节点:元素的属性
- 文本节点:元素或属性中的文本内容
- 命名空间节点:元素的命名空间
- 处理指令节点:XML 处理指令
- 注释节点:XML 注释
- 文档节点:整个文档的根节点
XPath 语法
1. 基本路径表达式
xml<!-- 示例 XML --> <bookstore> <book category="web"> <title lang="en">XML Guide</title> <author>John Doe</author> <price>39.95</price> </book> <book category="database"> <title lang="en">SQL Basics</title> <author>Jane Smith</author> <price>29.99</price> </book> </bookstore>
xpath/* 选择文档节点(根节点) /bookstore 选择根元素 bookstore /bookstore/book 选择 bookstore 下的所有 book 元素 //book 选择文档中所有的 book 元素 bookstore//book 选择 bookstore 后代中的所有 book 元素
2. 谓语(Predicates)
谓语用于查找特定的节点,放在方括号 [] 中:
xpath/bookstore/book[1] 选择第一个 book 元素 /bookstore/book[last()] 选择最后一个 book 元素 /bookstore/book[position()<3] 选择前两个 book 元素 //book[@category='web'] 选择 category 属性为 'web' 的 book 元素 //book[price>35] 选择 price 大于 35 的 book 元素
3. 通配符
xpath* 匹配任何元素节点 @* 匹配任何属性节点 node() 匹配任何类型的节点 //book/* 选择 book 元素的所有子元素
4. 轴(Axes)
轴定义了相对于当前节点的节点集合:
xpathancestor 选择当前节点的所有祖先节点 ancestor-or-self 选择当前节点及其所有祖先节点 attribute 选择当前节点的所有属性节点 child 选择当前节点的所有子节点 descendant 选择当前节点的所有后代节点 descendant-or-self 选择当前节点及其所有后代节点 following 选择文档中当前节点之后的所有节点 following-sibling 选择当前节点之后的所有同级节点 namespace 选择当前节点的所有命名空间节点 parent 选择当前节点的父节点 preceding 选择文档中当前节点之前的所有节点 preceding-sibling 选择当前节点之前的所有同级节点 self 选择当前节点本身
5. 运算符
xpath算术运算符:+ - * div mod 比较运算符:= != < > <= >= 布尔运算符:and or not()
XPath 函数
节点集函数
xpathcount(//book) 统计 book 元素的数量 id('b1') 选择 ID 为 'b1' 的元素 local-name() 返回节点的本地名称 namespace-uri() 返回节点的命名空间 URI name() 返回节点的名称
字符串函数
xpathstring() 将节点转换为字符串 concat('Hello', ' ', 'World') 连接字符串 starts-with(text, 'XML') 检查是否以指定字符串开头 contains(text, 'XML') 检查是否包含指定字符串 substring(text, 1, 3) 提取子字符串 string-length(text) 返回字符串长度 normalize-space(text) 规范化空白字符 translate(text, 'abc', 'XYZ') 字符替换
布尔函数
xpathboolean() 转换为布尔值 not() 逻辑非 true() 返回 true false() 返回 false lang() 检查语言设置
数字函数
xpathnumber() 转换为数字 sum(//price) 计算总和 floor(3.7) 向下取整 ceiling(3.2) 向上取整 round(3.7) 四舍五入
XPath 实际应用示例
1. Java 中使用 XPath
javaimport javax.xml.xpath.*; import org.w3c.dom.*; XPathFactory factory = XPathFactory.newInstance(); XPath xpath = factory.newXPath(); // 解析 XML 文档 DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = docFactory.newDocumentBuilder(); Document doc = builder.parse(new File("books.xml")); // 执行 XPath 查询 String expression = "//book[@category='web']/title/text()"; String title = xpath.evaluate(expression, doc, XPathConstants.STRING); System.out.println("Title: " + title); // 获取节点列表 NodeList books = (NodeList) xpath.evaluate("//book", doc, XPathConstants.NODESET); for (int i = 0; i < books.getLength(); i++) { Element book = (Element) books.item(i); System.out.println(book.getAttribute("category")); }
2. Python 中使用 XPath(lxml)
pythonfrom lxml import etree # 解析 XML 文档 tree = etree.parse("books.xml") # 执行 XPath 查询 titles = tree.xpath("//book[@category='web']/title/text()") for title in titles: print(f"Title: {title}") # 获取属性 categories = tree.xpath("//book/@category") for category in categories: print(f"Category: {category}") # 使用函数 total_price = sum(tree.xpath("//book/price/text()")) print(f"Total price: {total_price}")
3. JavaScript 中使用 XPath
javascript// 解析 XML const parser = new DOMParser(); const xmlDoc = parser.parseFromString(xmlString, "text/xml"); // 执行 XPath 查询 const result = xmlDoc.evaluate( "//book[@category='web']/title", xmlDoc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null ); for (let i = 0; i < result.snapshotLength; i++) { const node = result.snapshotItem(i); console.log(node.textContent); }
XPath 与 XQuery 的关系
XQuery 是基于 XPath 构建的查询语言,扩展了 XPath 的功能:
- XPath:用于定位和选择节点
- XQuery:用于查询、转换和构造 XML 数据
XPath 最佳实践
- 使用绝对路径:当文档结构固定时,使用绝对路径提高性能
- 避免使用
//://会搜索整个文档,影响性能 - 使用谓词过滤:尽早过滤节点,减少处理的数据量
- 利用索引:在大型文档中,考虑使用索引优化查询
- 缓存查询结果:对于频繁执行的查询,缓存结果
XPath 是处理 XML 数据的强大工具,掌握 XPath 可以大大提高 XML 数据处理的效率和灵活性。