活动公告

系统通知
05-18 21:22
系统通知
通知:本站资源由网友上传分享,如有违规等问题请到版务模块进行投诉,资源失效请在帖子内回复要求补档,会尽快处理!
10-23 09:31

XPath教程源码示例 零基础入门到高级应用的完整学习指南详细解析XML路径语言的语法结构轴谓词表达式函数使用以及实战技巧附丰富源码案例助您轻松掌握节点定位

SunJu_FaceMall

3万

主题

2860

科技点

3万

积分

白金月票

碾压王

积分
32872

塔罗立华奏

<font color=白金月票" /> 发表于 2025-9-4 09:30:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
1. XPath简介

1.1 什么是XPath

XPath(XML Path Language)是一种在XML文档中查找信息的语言。XPath用于在XML文档中通过元素和属性进行导航,它提供了一种简洁、强大的方式来定位XML文档中的节点、属性和文本内容。

XPath是W3C(World Wide Web Consortium)的标准,它被设计用于XSLT(XSL Transformations)、XPointer以及其他XML解析技术中。XPath不仅限于XML文档,还可以用于HTML文档的查询,特别是在网页抓取和数据提取方面有广泛应用。

1.2 XPath的历史和发展

XPath于1999年首次成为W3C推荐标准,随着XML技术的发展,XPath也经历了多次更新:

• XPath 1.0(1999年):最初的版本,提供了基本的路径表达式和函数。
• XPath 2.0(2007年):扩展了数据模型,增加了更多数据类型和函数。
• XPath 3.0(2014年):进一步增强了功能,引入了更高阶的函数和更强大的表达式。
• XPath 3.1(2017年):最新版本,增加了对数组和映射的支持,提供了更丰富的数据处理能力。

1.3 XPath的应用场景

XPath在多个领域有广泛应用:

1. XML文档处理:在XML文档中查找、提取和操作数据。
2. 网页抓取:在HTML文档中定位元素,提取所需信息。
3. XSLT转换:在XSLT样式表中定位源XML文档中的节点。
4. XML Schema:在XML Schema定义中引用和验证节点。
5. 自动化测试:在Selenium等自动化测试工具中定位网页元素。
6. 数据集成:在不同系统间集成和转换XML数据。

2. XPath基础语法

2.1 节点类型

在XPath中,有七种类型的节点:

1. 元素节点:XML文档中的元素,如<book>、<title>等。
2. 属性节点:元素的属性,如id="book1"。
3. 文本节点:元素包含的文本内容。
4. 命名空间节点:元素的命名空间。
5. 处理指令节点:XML文档的处理指令。
6. 注释节点:XML文档中的注释。
7. 文档根节点:整个XML文档的根节点。

2.2 基本路径表达式

XPath使用路径表达式来选取XML文档中的节点或节点集。这些路径表达式类似于文件系统中的路径。

以下是一些基本的路径表达式:

• nodename:选取所有名为nodename的子节点。
• /:从根节点选取。
• //:从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
• .:选取当前节点。
• ..:选取当前节点的父节点。
• @:选取属性。

2.3 绝对路径与相对路径

XPath路径可以分为绝对路径和相对路径:

• 绝对路径:以根节点开始,用/表示。例如,/bookstore/book表示从根节点开始,选择bookstore下的所有book元素。
• 相对路径:以当前节点开始,不使用/开头。例如,book/title表示从当前节点选择book元素下的所有title元素。

让我们通过一个示例XML文档来说明这些概念:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <bookstore>
  3.   <book category="cooking">
  4.     <title lang="en">Everyday Italian</title>
  5.     <author>Giada De Laurentiis</author>
  6.     <year>2005</year>
  7.     <price>30.00</price>
  8.   </book>
  9.   <book category="children">
  10.     <title lang="en">Harry Potter</title>
  11.     <author>J.K. Rowling</author>
  12.     <year>2005</year>
  13.     <price>29.99</price>
  14.   </book>
  15.   <book category="web">
  16.     <title lang="en">Learning XML</title>
  17.     <author>Erik T. Ray</author>
  18.     <year>2003</year>
  19.     <price>39.95</price>
  20.   </book>
  21. </bookstore>
复制代码

基于这个XML文档,以下是一些XPath表达式及其含义:

• /bookstore:选取根元素bookstore。
• bookstore/book:选取bookstore下所有book子元素。
• //book:选取文档中所有book元素,无论它们在文档中的位置。
• bookstore//book:选取bookstore元素后代中的所有book元素。
• //@category:选取所有名为category的属性。
• /bookstore/book[1]:选取bookstore下的第一个book元素。
• /bookstore/book[last()]:选取bookstore下的最后一个book元素。
• /bookstore/book[price>35]:选取bookstore下price元素值大于35的所有book元素。

3. XPath轴(Axes)详解

3.1 轴的概念

XPath轴定义了相对于当前节点的节点集。轴可以理解为从当前节点出发,可以到达的节点集合的方向。XPath提供了13种不同的轴,每种轴代表不同的导航方向。

3.2 各种轴及其用法

以下是XPath中可用的轴及其描述:

1. ancestor:选取当前节点的所有祖先(父、祖父等)。
2. ancestor-or-self:选取当前节点的所有祖先以及当前节点本身。
3. attribute:选取当前节点的所有属性。
4. child:选取当前节点的所有子元素。
5. descendant:选取当前节点的所有后代(子、孙等)。
6. descendant-or-self:选取当前节点的所有后代以及当前节点本身。
7. following:选取文档中当前节点的结束标签之后的所有节点。
8. following-sibling:选取当前节点之后的所有同级节点。
9. namespace:选取当前节点的所有命名空间节点。
10. parent:选取当前节点的父节点。
11. preceding:选取文档中当前节点的开始标签之前的所有节点。
12. preceding-sibling:选取当前节点之前的所有同级节点。
13. self:选取当前节点。

3.3 轴的缩写形式

为了简化XPath表达式的编写,一些常用的轴有缩写形式:

• child::可以省略,例如child::book可以简写为book。
• attribute::可以缩写为@,例如attribute::category可以简写为@category。
• //是/descendant-or-self::node()/的缩写。
• .是self::node()的缩写。
• ..是parent::node()的缩写。

3.4 轴使用示例

让我们使用之前的XML文档来演示各种轴的使用:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <bookstore>
  3.   <book category="cooking">
  4.     <title lang="en">Everyday Italian</title>
  5.     <author>Giada De Laurentiis</author>
  6.     <year>2005</year>
  7.     <price>30.00</price>
  8.   </book>
  9.   <book category="children">
  10.     <title lang="en">Harry Potter</title>
  11.     <author>J.K. Rowling</author>
  12.     <year>2005</year>
  13.     <price>29.99</price>
  14.   </book>
  15.   <book category="web">
  16.     <title lang="en">Learning XML</title>
  17.     <author>Erik T. Ray</author>
  18.     <year>2003</year>
  19.     <price>39.95</price>
  20.   </book>
  21. </bookstore>
复制代码

假设当前节点是第一个book元素的title节点(<title lang="en">Everyday Italian</title>),以下是一些使用轴的XPath表达式及其含义:

• ancestor::book:选取当前节点的祖先节点中名为book的节点。
• ancestor-or-self::*:选取当前节点及其所有祖先节点。
• attribute::lang:选取当前节点的lang属性,等同于@lang。
• child::text():选取当前节点的文本子节点,等同于text()。
• descendant::*:选取当前节点的所有后代元素节点。
• descendant-or-self::*:选取当前节点及其所有后代元素节点。
• following::book:选取当前节点之后的所有book元素。
• following-sibling::*:选取当前节点之后的所有同级元素节点。
• parent::*:选取当前节点的父元素节点,等同于..。
• preceding::book:选取当前节点之前的所有book元素。
• preceding-sibling::*:选取当前节点之前的所有同级元素节点。
• self::*:选取当前节点本身,等同于.。

4. XPath谓词(Predicates)

4.1 谓词的基本概念

谓词用于查找某个特定的节点或者包含某个指定值的节点,它们被嵌在方括号[]中。谓词可以看作是一种过滤条件,用于从节点集中选择满足特定条件的节点。

4.2 谓词中的运算符

XPath谓词中可以使用多种运算符:

1. 比较运算符:=:等于!=:不等于<:小于<=:小于等于>:大于>=:大于等于
2. =:等于
3. !=:不等于
4. <:小于
5. <=:小于等于
6. >:大于
7. >=:大于等于
8. 布尔运算符:and:逻辑与or:逻辑或not():逻辑非
9. and:逻辑与
10. or:逻辑或
11. not():逻辑非
12. 其他运算符:|:联合(计算两个节点集)+:加法-:减法*:乘法div:除法mod:取模
13. |:联合(计算两个节点集)
14. +:加法
15. -:减法
16. *:乘法
17. div:除法
18. mod:取模

比较运算符:

• =:等于
• !=:不等于
• <:小于
• <=:小于等于
• >:大于
• >=:大于等于

布尔运算符:

• and:逻辑与
• or:逻辑或
• not():逻辑非

其他运算符:

• |:联合(计算两个节点集)
• +:加法
• -:减法
• *:乘法
• div:除法
• mod:取模

4.3 谓词使用示例

继续使用之前的XML文档,以下是一些使用谓词的XPath表达式及其含义:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <bookstore>
  3.   <book category="cooking">
  4.     <title lang="en">Everyday Italian</title>
  5.     <author>Giada De Laurentiis</author>
  6.     <year>2005</year>
  7.     <price>30.00</price>
  8.   </book>
  9.   <book category="children">
  10.     <title lang="en">Harry Potter</title>
  11.     <author>J.K. Rowling</author>
  12.     <year>2005</year>
  13.     <price>29.99</price>
  14.   </book>
  15.   <book category="web">
  16.     <title lang="en">Learning XML</title>
  17.     <author>Erik T. Ray</author>
  18.     <year>2003</year>
  19.     <price>39.95</price>
  20.   </book>
  21. </bookstore>
复制代码

• /bookstore/book[1]:选取bookstore下的第一个book元素。
• /bookstore/book[last()]:选取bookstore下的最后一个book元素。
• /bookstore/book[position()<3]:选取bookstore下的前两个book元素。
• /bookstore/book[price>35]:选取bookstore下price元素值大于35的所有book元素。
• //book[@category='web']:选取所有category属性值为web的book元素。
• //title[@lang]:选取所有具有lang属性的title元素。
• //title[@lang='en']:选取所有lang属性值为en的title元素。
• /bookstore/book[price>30 and price<40]:选取bookstore下price元素值大于30且小于40的所有book元素。
• /bookstore/book[year=2005 or year=2003]:选取bookstore下year元素值为2005或2003的所有book元素。

5. XPath表达式

5.1 路径表达式

路径表达式是XPath中最常用的表达式类型,用于选择XML文档中的节点集。路径表达式可以是绝对路径(从根节点开始)或相对路径(从当前节点开始)。

以下是一些路径表达式的示例:

• /bookstore/book/title:选取bookstore下所有book元素的所有title元素。
• //title:选取文档中所有的title元素。
• bookstore//title:选取bookstore元素后代中的所有title元素。
• //book/title[@lang]:选取所有book元素下具有lang属性的title元素。
• //book[@category='web']/title:选取所有category属性为web的book元素下的title元素。

5.2 布尔表达式

布尔表达式用于计算真值或假值,常用于谓词中。布尔表达式可以使用比较运算符、布尔运算符和XPath函数。

以下是一些布尔表达式的示例:

• @category = 'web':如果category属性值为web,则返回true。
• price > 30:如果price元素值大于30,则返回true。
• @category = 'web' and price > 30:如果category属性值为web且price元素值大于30,则返回true。
• @category = 'web' or @category = 'cooking':如果category属性值为web或cooking,则返回true。
• not(@category = 'web'):如果category属性值不为web,则返回true。

5.3 数值表达式

数值表达式用于执行数值计算,可以用于谓词中或其他需要数值计算的场合。

以下是一些数值表达式的示例:

• price + 5:price元素值加5。
• price * 1.1:price元素值乘以1.1。
• price div 2:price元素值除以2。
• (price + shipping) * tax:price元素值加上shipping元素值,然后乘以tax元素值。
• position() mod 2 = 0:如果当前位置是偶数,则返回true。

5.4 字符串表达式

字符串表达式用于处理文本数据,可以使用字符串函数和字符串连接操作。

以下是一些字符串表达式的示例:

• concat(title, ' by ', author):连接title、’ by ‘和author元素值。
• substring(title, 1, 3):提取title元素值的前3个字符。
• string-length(title):计算title元素值的长度。
• contains(title, 'XML'):如果title元素值包含’XML’,则返回true。
• starts-with(title, 'Learning'):如果title元素值以’Learning’开头,则返回true。
• normalize-space(title):去除title元素值的前后空格,并将内部连续空格替换为单个空格。

6. XPath函数

XPath提供了丰富的函数库,用于处理节点集、字符串、布尔值和数值。这些函数可以在XPath表达式中使用,以增强XPath的表达能力和灵活性。

6.1 节点集函数

节点集函数用于处理节点集:

1. last():返回当前上下文中的最后一个节点的位置。
2. position():返回当前节点的位置。
3. count(node-set):返回节点集中的节点数量。
4. id(string):根据ID选择元素。
5. local-name(node-set):返回节点集中第一个节点的本地名称。
6. namespace-uri(node-set):返回节点集中第一个节点的命名空间URI。
7. name(node-set):返回节点集中第一个节点的完整名称。

示例:

• book[position()=last()]:选择最后一个book元素。
• book[count(author)>1]:选择包含多个author元素的book元素。
• id('book1'):选择ID为book1的元素。
• *[local-name()='book']:选择本地名称为book的所有元素。

6.2 字符串函数

字符串函数用于处理字符串:

1. string(object):将对象转换为字符串。
2. concat(string, string, ...):连接多个字符串。
3. starts-with(string, string):检查第一个字符串是否以第二个字符串开头。
4. contains(string, string):检查第一个字符串是否包含第二个字符串。
5. substring-before(string, string):返回第一个字符串中第二个字符串出现之前的部分。
6. substring-after(string, string):返回第一个字符串中第二个字符串出现之后的部分。
7. substring(string, start, length):返回字符串的子串。
8. string-length(string):返回字符串的长度。
9. normalize-space(string):去除字符串的前后空格,并将内部连续空格替换为单个空格。
10. translate(string, string, string):替换字符串中的字符。

示例:

• book[starts-with(title, 'Learning')]:选择title以’Learning’开头的book元素。
• book[contains(title, 'XML')]:选择title包含’XML’的book元素。
• book[string-length(title)>10]:选择title长度大于10的book元素。
• concat(title, ' by ', author):连接title、’ by ‘和author元素值。
• translate(title, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'):将title转换为小写。

6.3 布尔函数

布尔函数用于处理布尔值:

1. boolean(object):将对象转换为布尔值。
2. not(boolean):对布尔值取反。
3. true():返回true。
4. false():返回false。
5. lang(string):检查上下文节点的语言是否与指定的语言匹配。

示例:

• book[boolean(author)]:选择具有author元素的book元素。
• book[not(price>30)]:选择price不大于30的book元素。
• book[true()]:选择所有book元素(总是返回true)。
• book[false()]:不选择任何book元素(总是返回false)。
• book[lang('en')]:选择语言为英语的book元素。

6.4 数值函数

数值函数用于处理数值:

1. number(object):将对象转换为数值。
2. sum(node-set):返回节点集中所有节点的数值总和。
3. floor(number):返回不大于number的最大整数。
4. ceiling(number):返回不小于number的最小整数。
5. round(number):返回number的四舍五入整数。

示例:

• sum(book/price):计算所有book元素的price元素值的总和。
• book[floor(price)=30]:选择price元素值的整数部分为30的book元素。
• book[ceiling(price)=31]:选择price元素值的向上取整为31的book元素。
• book[round(price)=30]:选择price元素值的四舍五入为30的book元素。

7. XPath实战技巧

7.1 常见问题和解决方案

当XML文档使用命名空间时,XPath查询可能会遇到问题。这是因为XPath表达式中的元素名称必须与XML文档中的命名空间URI匹配。

解决方案:

1. 在XPath处理器中注册命名空间前缀和URI。
2. 在XPath表达式中使用已注册的命名空间前缀。

例如,对于以下XML文档:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <ns:bookstore xmlns:ns="http://example.com/bookstore">
  3.   <ns:book category="cooking">
  4.     <ns:title lang="en">Everyday Italian</ns:title>
  5.     <ns:author>Giada De Laurentiis</ns:author>
  6.     <ns:year>2005</ns:year>
  7.     <ns:price>30.00</ns:price>
  8.   </ns:book>
  9. </ns:bookstore>
复制代码

在Java中,可以使用以下代码处理命名空间:
  1. import javax.xml.parsers.DocumentBuilder;
  2. import javax.xml.parsers.DocumentBuilderFactory;
  3. import javax.xml.xpath.XPath;
  4. import javax.xml.xpath.XPathConstants;
  5. import javax.xml.xpath.XPathExpression;
  6. import javax.xml.xpath.XPathFactory;
  7. import org.w3c.dom.Document;
  8. import org.w3c.dom.NodeList;
  9. public class XPathNamespaceExample {
  10.     public static void main(String[] args) throws Exception {
  11.         // 创建DocumentBuilder
  12.         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  13.         factory.setNamespaceAware(true);
  14.         DocumentBuilder builder = factory.newDocumentBuilder();
  15.         
  16.         // 解析XML文档
  17.         Document document = builder.parse("bookstore.xml");
  18.         
  19.         // 创建XPath
  20.         XPathFactory xpathFactory = XPathFactory.newInstance();
  21.         XPath xpath = xpathFactory.newXPath();
  22.         
  23.         // 设置命名空间上下文
  24.         xpath.setNamespaceContext(new SimpleNamespaceContext());
  25.         
  26.         // 创建XPath表达式
  27.         XPathExpression expr = xpath.compile("//ns:book[ns:price>30]");
  28.         
  29.         // 执行XPath表达式
  30.         NodeList nodes = (NodeList) expr.evaluate(document, XPathConstants.NODESET);
  31.         
  32.         // 输出结果
  33.         for (int i = 0; i < nodes.getLength(); i++) {
  34.             System.out.println(nodes.item(i).getTextContent());
  35.         }
  36.     }
  37. }
  38. class SimpleNamespaceContext implements javax.xml.namespace.NamespaceContext {
  39.     @Override
  40.     public String getNamespaceURI(String prefix) {
  41.         if (prefix.equals("ns")) {
  42.             return "http://example.com/bookstore";
  43.         }
  44.         return null;
  45.     }
  46.    
  47.     @Override
  48.     public String getPrefix(String namespaceURI) {
  49.         if (namespaceURI.equals("http://example.com/bookstore")) {
  50.             return "ns";
  51.         }
  52.         return null;
  53.     }
  54.    
  55.     @Override
  56.     public java.util.Iterator<String> getPrefixes(String namespaceURI) {
  57.         java.util.Set<String> prefixes = new java.util.HashSet<String>();
  58.         if (namespaceURI.equals("http://example.com/bookstore")) {
  59.             prefixes.add("ns");
  60.         }
  61.         return prefixes.iterator();
  62.     }
  63. }
复制代码

当需要基于多个条件查询节点时,可以使用布尔运算符(and、or)和谓词组合。

例如,要选择category属性为web且price大于30的book元素:
  1. //book[@category='web' and price>30]
复制代码

要选择category属性为web或cooking的book元素:
  1. //book[@category='web' or @category='cooking']
复制代码

要查询包含特定文本内容的元素,可以使用text()函数和contains()函数。

例如,要选择title元素包含”XML”的book元素:
  1. //book[contains(title, 'XML')]
复制代码

要选择title元素文本为”Learning XML”的book元素:
  1. //book[title/text()='Learning XML']
复制代码

7.2 性能优化技巧

以//开头的XPath表达式会搜索整个文档,性能较差。如果可能,应该使用更具体的路径。

例如,以下表达式:
  1. //title
复制代码

可以优化为:
  1. /bookstore/book/title
复制代码

尽早使用谓词过滤节点集,减少后续处理的节点数量。

例如,以下表达式:
  1. /bookstore/book[price>30]/title
复制代码

比以下表达式更高效:
  1. /bookstore/book/title[../price>30]
复制代码

在谓词中使用函数会增加计算复杂度,降低性能。如果可能,应该使用简单的比较操作。

例如,以下表达式:
  1. //book[contains(title, 'XML')]
复制代码

比以下表达式更高效:
  1. //book[substring(title, 1, 3)='XML']
复制代码

如果XML文档很大,可以考虑使用索引来提高XPath查询性能。一些XPath处理器支持索引功能,可以预先构建索引来加速查询。

7.3 最佳实践

尽量使用明确的路径表达式,避免使用过于通用的表达式。明确的路径表达式更易于理解和维护。

例如,以下表达式:
  1. /bookstore/book[1]/title
复制代码

比以下表达式更明确:
  1. //title[1]
复制代码

对于复杂的XPath表达式,可以考虑使用变量和函数来提高可读性和可维护性。

例如,以下表达式:
  1. //book[price>30 and @category='web' or price>25 and @category='cooking']
复制代码

可以重构为:
  1. //book[(price>30 and @category='web') or (price>25 and @category='cooking')]
复制代码

为复杂的XPath表达式添加注释和文档,以帮助其他开发人员理解其用途和工作原理。

例如:
  1. <!-- 选择价格高于30的web类书籍或价格高于25的cooking类书籍 -->
  2. //book[(price>30 and @category='web') or (price>25 and @category='cooking')]
复制代码

测试和验证XPath表达式,确保它们在各种情况下都能正常工作。可以使用XPath测试工具或编写单元测试来验证XPath表达式的正确性。

8. 综合案例

8.1 复杂XML文档的查询

让我们考虑一个更复杂的XML文档,展示XPath的高级应用:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <library xmlns="http://example.com/library">
  3.   <books>
  4.     <book id="b1" category="fiction">
  5.       <title lang="en">The Great Gatsby</title>
  6.       <author>F. Scott Fitzgerald</author>
  7.       <publish_date>1925-04-10</publish_date>
  8.       <price currency="USD">15.99</price>
  9.       <reviews>
  10.         <review rating="5">A masterpiece of American literature.</review>
  11.         <review rating="4">Beautifully written, but somewhat dated.</review>
  12.       </reviews>
  13.     </book>
  14.     <book id="b2" category="science">
  15.       <title lang="en">A Brief History of Time</title>
  16.       <author>Stephen Hawking</author>
  17.       <publish_date>1988-04-01</publish_date>
  18.       <price currency="GBP">18.50</price>
  19.       <reviews>
  20.         <review rating="5">Mind-blowing exploration of the universe.</review>
  21.         <review rating="4">Complex but rewarding.</review>
  22.         <review rating="3">Too technical for my taste.</review>
  23.       </reviews>
  24.     </book>
  25.     <book id="b3" category="fiction">
  26.       <title lang="fr">Le Petit Prince</title>
  27.       <author>Antoine de Saint-Exupéry</author>
  28.       <publish_date>1943-04-06</publish_date>
  29.       <price currency="EUR">12.99</price>
  30.       <reviews>
  31.         <review rating="5">A timeless classic for all ages.</review>
  32.         <review rating="5">Beautiful and profound.</review>
  33.       </reviews>
  34.     </book>
  35.   </books>
  36.   <members>
  37.     <member id="m1">
  38.       <name>John Doe</name>
  39.       <joined>2020-01-15</joined>
  40.       <borrowed_books>
  41.         <book_ref ref="b1" borrow_date="2023-01-10" return_date="2023-01-24"/>
  42.         <book_ref ref="b2" borrow_date="2023-02-05" return_date="2023-02-19"/>
  43.       </borrowed_books>
  44.     </member>
  45.     <member id="m2">
  46.       <name>Jane Smith</name>
  47.       <joined>2021-03-22</joined>
  48.       <borrowed_books>
  49.         <book_ref ref="b3" borrow_date="2023-01-15" return_date="2023-01-29"/>
  50.       </borrowed_books>
  51.     </member>
  52.   </members>
  53. </library>
复制代码

1. 选择所有fiction类别的书籍:
  1. //book[@category='fiction']
复制代码

1. 选择所有价格高于15的书籍:
  1. //book[price>15]
复制代码

1. 选择所有评论评分高于4的书籍:
  1. //book[reviews/review/@rating>4]
复制代码

1. 选择所有作者为”Stephen Hawking”的书籍:
  1. //book[author='Stephen Hawking']
复制代码

1. 选择所有在1925年之后出版的书籍:
  1. //book[publish_date>'1925-12-31']
复制代码

1. 选择所有货币为USD的书籍:
  1. //book[price/@currency='USD']
复制代码

1. 选择所有标题包含”History”的书籍:
  1. //book[contains(title, 'History')]
复制代码

1. 选择所有评论数量大于2的书籍:
  1. //book[count(reviews/review)>2]
复制代码

1. 选择所有平均评分高于4的书籍:
  1. //book[sum(reviews/review/@rating) div count(reviews/review)>4]
复制代码

1. 选择所有被借出的书籍:
  1. //book[@id=//book_ref/@ref]
复制代码

以下是一个Java代码示例,展示如何使用XPath查询上述XML文档:
  1. import javax.xml.parsers.DocumentBuilder;
  2. import javax.xml.parsers.DocumentBuilderFactory;
  3. import javax.xml.xpath.XPath;
  4. import javax.xml.xpath.XPathConstants;
  5. import javax.xml.xpath.XPathExpression;
  6. import javax.xml.xpath.XPathFactory;
  7. import org.w3c.dom.Document;
  8. import org.w3c.dom.NodeList;
  9. public class LibraryXPathExample {
  10.     public static void main(String[] args) throws Exception {
  11.         // 创建DocumentBuilder
  12.         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  13.         factory.setNamespaceAware(true);
  14.         DocumentBuilder builder = factory.newDocumentBuilder();
  15.         
  16.         // 解析XML文档
  17.         Document document = builder.parse("library.xml");
  18.         
  19.         // 创建XPath
  20.         XPathFactory xpathFactory = XPathFactory.newInstance();
  21.         XPath xpath = xpathFactory.newXPath();
  22.         
  23.         // 设置命名空间上下文
  24.         xpath.setNamespaceContext(new LibraryNamespaceContext());
  25.         
  26.         // 查询1:选择所有fiction类别的书籍
  27.         System.out.println("Fiction books:");
  28.         XPathExpression expr1 = xpath.compile("//lib:book[@category='fiction']");
  29.         NodeList nodes1 = (NodeList) expr1.evaluate(document, XPathConstants.NODESET);
  30.         for (int i = 0; i < nodes1.getLength(); i++) {
  31.             System.out.println(nodes1.item(i).getTextContent());
  32.         }
  33.         
  34.         // 查询2:选择所有价格高于15的书籍
  35.         System.out.println("\nBooks with price > 15:");
  36.         XPathExpression expr2 = xpath.compile("//lib:book[lib:price>15]");
  37.         NodeList nodes2 = (NodeList) expr2.evaluate(document, XPathConstants.NODESET);
  38.         for (int i = 0; i < nodes2.getLength(); i++) {
  39.             System.out.println(nodes2.item(i).getTextContent());
  40.         }
  41.         
  42.         // 查询3:选择所有评论评分高于4的书籍
  43.         System.out.println("\nBooks with review rating > 4:");
  44.         XPathExpression expr3 = xpath.compile("//lib:book[lib:reviews/lib:review/@rating>4]");
  45.         NodeList nodes3 = (NodeList) expr3.evaluate(document, XPathConstants.NODESET);
  46.         for (int i = 0; i < nodes3.getLength(); i++) {
  47.             System.out.println(nodes3.item(i).getTextContent());
  48.         }
  49.         
  50.         // 查询4:选择所有平均评分高于4的书籍
  51.         System.out.println("\nBooks with average rating > 4:");
  52.         XPathExpression expr4 = xpath.compile("//lib:book[sum(lib:reviews/lib:review/@rating) div count(lib:reviews/lib:review)>4]");
  53.         NodeList nodes4 = (NodeList) expr4.evaluate(document, XPathConstants.NODESET);
  54.         for (int i = 0; i < nodes4.getLength(); i++) {
  55.             System.out.println(nodes4.item(i).getTextContent());
  56.         }
  57.         
  58.         // 查询5:选择所有被借出的书籍
  59.         System.out.println("\nBorrowed books:");
  60.         XPathExpression expr5 = xpath.compile("//lib:book[@id=//lib:book_ref/@ref]");
  61.         NodeList nodes5 = (NodeList) expr5.evaluate(document, XPathConstants.NODESET);
  62.         for (int i = 0; i < nodes5.getLength(); i++) {
  63.             System.out.println(nodes5.item(i).getTextContent());
  64.         }
  65.     }
  66. }
  67. class LibraryNamespaceContext implements javax.xml.namespace.NamespaceContext {
  68.     @Override
  69.     public String getNamespaceURI(String prefix) {
  70.         if (prefix.equals("lib")) {
  71.             return "http://example.com/library";
  72.         }
  73.         return null;
  74.     }
  75.    
  76.     @Override
  77.     public String getPrefix(String namespaceURI) {
  78.         if (namespaceURI.equals("http://example.com/library")) {
  79.             return "lib";
  80.         }
  81.         return null;
  82.     }
  83.    
  84.     @Override
  85.     public java.util.Iterator<String> getPrefixes(String namespaceURI) {
  86.         java.util.Set<String> prefixes = new java.util.HashSet<String>();
  87.         if (namespaceURI.equals("http://example.com/library")) {
  88.             prefixes.add("lib");
  89.         }
  90.         return prefixes.iterator();
  91.     }
  92. }
复制代码

8.2 XPath在网页抓取中的应用

XPath在网页抓取和数据提取中非常有用。许多网页抓取工具和库(如Scrapy、BeautifulSoup、Selenium等)都支持使用XPath来定位和提取HTML元素。

以下是一个使用Python和lxml库进行网页抓取的示例:
  1. from lxml import html
  2. import requests
  3. # 获取网页内容
  4. url = "https://example.com/books"
  5. page = requests.get(url)
  6. tree = html.fromstring(page.content)
  7. # 使用XPath提取数据
  8. # 提取所有书籍的标题
  9. titles = tree.xpath('//div[@class="book"]/h2/text()')
  10. # 提取所有书籍的作者
  11. authors = tree.xpath('//div[@class="book"]/p[@class="author"]/text()')
  12. # 提取所有书籍的价格
  13. prices = tree.xpath('//div[@class="book"]/p[@class="price"]/text()')
  14. # 打印提取的数据
  15. for title, author, price in zip(titles, authors, prices):
  16.     print(f"Title: {title}")
  17.     print(f"Author: {author}")
  18.     print(f"Price: {price}")
  19.     print("-" * 50)
复制代码

8.3 XPath在XSLT中的应用

XPath在XSLT(XSL Transformations)中扮演着核心角色,用于选择和匹配XML文档中的节点,以便进行转换。

以下是一个XSLT样式表示例,展示如何使用XPath转换XML文档:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  3.   <xsl:output method="html" indent="yes"/>
  4.   
  5.   <!-- 匹配根节点 -->
  6.   <xsl:template match="/">
  7.     <html>
  8.       <head>
  9.         <title>Bookstore</title>
  10.       </head>
  11.       <body>
  12.         <h1>Bookstore</h1>
  13.         <table border="1">
  14.           <tr>
  15.             <th>Title</th>
  16.             <th>Author</th>
  17.             <th>Year</th>
  18.             <th>Price</th>
  19.           </tr>
  20.           <!-- 选择所有book元素 -->
  21.           <xsl:for-each select="//book">
  22.             <tr>
  23.               <td><xsl:value-of select="title"/></td>
  24.               <td><xsl:value-of select="author"/></td>
  25.               <td><xsl:value-of select="year"/></td>
  26.               <td><xsl:value-of select="price"/></td>
  27.             </tr>
  28.           </xsl:for-each>
  29.         </table>
  30.         
  31.         <h2>Books by Category</h2>
  32.         <xsl:for-each select="//book[not(@category=preceding-sibling::book/@category)]">
  33.           <xsl:sort select="@category"/>
  34.           <h3><xsl:value-of select="@category"/></h3>
  35.           <ul>
  36.             <!-- 选择相同类别的所有书籍 -->
  37.             <xsl:for-each select="//book[@category=current()/@category]">
  38.               <xsl:sort select="title"/>
  39.               <li><xsl:value-of select="title"/> - <xsl:value-of select="author"/></li>
  40.             </xsl:for-each>
  41.           </ul>
  42.         </xsl:for-each>
  43.         
  44.         <h2>Expensive Books (Price > 30)</h2>
  45.         <ul>
  46.           <!-- 选择价格大于30的书籍 -->
  47.           <xsl:for-each select="//book[price>30]">
  48.             <xsl:sort select="price" order="descending"/>
  49.             <li><xsl:value-of select="title"/> - <xsl:value-of select="price"/></li>
  50.           </xsl:for-each>
  51.         </ul>
  52.       </body>
  53.     </html>
  54.   </xsl:template>
  55. </xsl:stylesheet>
复制代码

这个XSLT样式表将XML文档转换为HTML格式,包括:

1. 一个包含所有书籍的表格。
2. 按类别分组的书籍列表。
3. 价格高于30的书籍列表,按价格降序排列。

总结

XPath是一种强大的查询语言,用于在XML文档中查找和提取信息。通过本教程,我们学习了XPath的基本概念、语法结构、轴、谓词、表达式和函数,以及如何在实际应用中使用XPath。

XPath的主要特点包括:

1. 灵活的路径表达式,可以精确地定位XML文档中的节点。
2. 丰富的轴和谓词,提供了多种导航和过滤方式。
3. 强大的函数库,支持字符串、数值、布尔值和节点集的处理。
4. 在XML处理、网页抓取、XSLT转换等领域有广泛应用。

掌握XPath对于处理XML和HTML文档非常重要,它可以帮助我们更高效地提取和操作数据。通过不断练习和实践,您将能够熟练运用XPath解决各种实际问题。

希望本教程能够帮助您从零基础入门,逐步掌握XPath的高级应用,并在实际工作中灵活运用XPath技术。
「七転び八起き(ななころびやおき)」
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则