活动公告

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

掌握XPath 1.0基础用法 轻松解析XML文档的必备技能 从路径表达式到轴导航的全面教程 适合初学者的完整指南

SunJu_FaceMall

3万

主题

2860

科技点

3万

积分

白金月票

碾压王

积分
32872

塔罗立华奏

<font color=白金月票" /> 发表于 2025-9-5 19:50:01 | 显示全部楼层 |阅读模式

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

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

x
1. 引言:XPath的重要性和基本概念

XPath(XML Path Language)是一种用于在XML文档中定位节点的语言,它提供了一种简洁、强大的方式来导航XML文档的树状结构。作为XSLT、XQuery和XPointer等技术的核心组件,XPath已成为处理XML文档的必备技能。

XPath 1.0于1999年成为W3C推荐标准,虽然后续有XPath 2.0和3.0版本,但1.0版本仍然被广泛使用,特别是在许多编程语言的XML处理库中。掌握XPath 1.0的基础用法,将使你能够轻松解析和提取XML文档中的数据,无论是在Web开发、数据集成还是内容管理系统中都大有裨益。

XPath将XML文档视为一个节点树,其中每个元素、属性、文本等都视为一个节点。通过XPath表达式,我们可以精确地定位到文档中的任何节点或节点集合。

2. XPath基础:节点类型和基本语法

2.1 XML文档节点树

在深入XPath之前,我们需要理解XML文档的节点树结构。一个XML文档由以下几种主要节点类型组成:

• 根节点:文档的顶层节点,不是元素节点,而是整个文档的容器
• 元素节点:XML文档中的元素,如<book>,<author>等
• 属性节点:元素的属性,如id="book1"
• 文本节点:元素包含的文本内容
• 注释节点:XML文档中的注释
• 处理指令节点:如<?xml version="1.0"?>等

考虑以下简单的XML文档示例:
  1. <?xml version="1.0"?>
  2. <bookstore>
  3.   <book category="fiction">
  4.     <title lang="en">Harry Potter</title>
  5.     <author>J.K. Rowling</author>
  6.     <year>2005</year>
  7.     <price>29.99</price>
  8.   </book>
  9.   <book category="children">
  10.     <title lang="en">The Wonderful Wizard of Oz</title>
  11.     <author>L. Frank Baum</author>
  12.     <year>1900</year>
  13.     <price>15.99</price>
  14.   </book>
  15. </bookstore>
复制代码

这个文档的节点树结构如下:

• 根节点(代表整个文档)元素节点:bookstore元素节点:book (属性:category=“fiction”)元素节点:title (属性:lang=“en”)文本节点:Harry Potter元素节点:author文本节点:J.K. Rowling元素节点:year文本节点:2005元素节点:price文本节点:29.99元素节点:book (属性:category=“children”)元素节点:title (属性:lang=“en”)文本节点:The Wonderful Wizard of Oz元素节点:author文本节点:L. Frank Baum元素节点:year文本节点:1900元素节点:price文本节点:15.99
• 元素节点:bookstore元素节点:book (属性:category=“fiction”)元素节点:title (属性:lang=“en”)文本节点:Harry Potter元素节点:author文本节点:J.K. Rowling元素节点:year文本节点:2005元素节点:price文本节点:29.99元素节点:book (属性:category=“children”)元素节点:title (属性:lang=“en”)文本节点:The Wonderful Wizard of Oz元素节点:author文本节点:L. Frank Baum元素节点:year文本节点:1900元素节点:price文本节点:15.99
• 元素节点:book (属性:category=“fiction”)元素节点:title (属性:lang=“en”)文本节点:Harry Potter元素节点:author文本节点:J.K. Rowling元素节点:year文本节点:2005元素节点:price文本节点:29.99
• 元素节点:title (属性:lang=“en”)
• 文本节点:Harry Potter
• 元素节点:author
• 文本节点:J.K. Rowling
• 元素节点:year
• 文本节点:2005
• 元素节点:price
• 文本节点:29.99
• 元素节点:book (属性:category=“children”)元素节点:title (属性:lang=“en”)文本节点:The Wonderful Wizard of Oz元素节点:author文本节点:L. Frank Baum元素节点:year文本节点:1900元素节点:price文本节点:15.99
• 元素节点:title (属性:lang=“en”)
• 文本节点:The Wonderful Wizard of Oz
• 元素节点:author
• 文本节点:L. Frank Baum
• 元素节点:year
• 文本节点:1900
• 元素节点:price
• 文本节点:15.99

• 元素节点:bookstore元素节点:book (属性:category=“fiction”)元素节点:title (属性:lang=“en”)文本节点:Harry Potter元素节点:author文本节点:J.K. Rowling元素节点:year文本节点:2005元素节点:price文本节点:29.99元素节点:book (属性:category=“children”)元素节点:title (属性:lang=“en”)文本节点:The Wonderful Wizard of Oz元素节点:author文本节点:L. Frank Baum元素节点:year文本节点:1900元素节点:price文本节点:15.99
• 元素节点:book (属性:category=“fiction”)元素节点:title (属性:lang=“en”)文本节点:Harry Potter元素节点:author文本节点:J.K. Rowling元素节点:year文本节点:2005元素节点:price文本节点:29.99
• 元素节点:title (属性:lang=“en”)
• 文本节点:Harry Potter
• 元素节点:author
• 文本节点:J.K. Rowling
• 元素节点:year
• 文本节点:2005
• 元素节点:price
• 文本节点:29.99
• 元素节点:book (属性:category=“children”)元素节点:title (属性:lang=“en”)文本节点:The Wonderful Wizard of Oz元素节点:author文本节点:L. Frank Baum元素节点:year文本节点:1900元素节点:price文本节点:15.99
• 元素节点:title (属性:lang=“en”)
• 文本节点:The Wonderful Wizard of Oz
• 元素节点:author
• 文本节点:L. Frank Baum
• 元素节点:year
• 文本节点:1900
• 元素节点:price
• 文本节点:15.99

• 元素节点:book (属性:category=“fiction”)元素节点:title (属性:lang=“en”)文本节点:Harry Potter元素节点:author文本节点:J.K. Rowling元素节点:year文本节点:2005元素节点:price文本节点:29.99
• 元素节点:title (属性:lang=“en”)
• 文本节点:Harry Potter
• 元素节点:author
• 文本节点:J.K. Rowling
• 元素节点:year
• 文本节点:2005
• 元素节点:price
• 文本节点:29.99
• 元素节点:book (属性:category=“children”)元素节点:title (属性:lang=“en”)文本节点:The Wonderful Wizard of Oz元素节点:author文本节点:L. Frank Baum元素节点:year文本节点:1900元素节点:price文本节点:15.99
• 元素节点:title (属性:lang=“en”)
• 文本节点:The Wonderful Wizard of Oz
• 元素节点:author
• 文本节点:L. Frank Baum
• 元素节点:year
• 文本节点:1900
• 元素节点:price
• 文本节点:15.99

• 元素节点:title (属性:lang=“en”)
• 文本节点:Harry Potter
• 元素节点:author
• 文本节点:J.K. Rowling
• 元素节点:year
• 文本节点:2005
• 元素节点:price
• 文本节点:29.99

• 元素节点:title (属性:lang=“en”)
• 文本节点:The Wonderful Wizard of Oz
• 元素节点:author
• 文本节点:L. Frank Baum
• 元素节点:year
• 文本节点:1900
• 元素节点:price
• 文本节点:15.99

2.2 XPath基本语法

XPath表达式的基本语法由路径组成,类似于文件系统中的路径。路径由一系列步骤组成,每个步骤通过斜杠(/)分隔。每个步骤包含一个轴(指定选择方向)、一个节点测试(指定选择的节点类型)和零个或多个谓词(过滤条件)。

最基本的XPath表达式是路径表达式,用于在节点树中导航。例如:

• /bookstore:选择根元素bookstore
• /bookstore/book:选择bookstore下的所有book子元素
• /bookstore/book/title:选择所有book元素下的title子元素

XPath表达式可以是绝对路径(从根节点开始)或相对路径(从当前节点开始)。

3. 路径表达式:绝对路径、相对路径和通配符

3.1 绝对路径

绝对路径从根节点开始,以斜杠(/)开头。它指定了从根节点到目标节点的完整路径。

示例:

• /bookstore:选择根元素bookstore
• /bookstore/book:选择bookstore下的所有book子元素
• /bookstore/book/title:选择所有book元素下的title子元素
• /bookstore/book/price:选择所有book元素下的price子元素

3.2 相对路径

相对路径从当前节点开始,不以斜杠开头。它指定了从当前节点到目标节点的路径。

示例:

• book:选择当前节点的所有book子元素
• book/title:选择当前节点的所有book子元素下的title子元素
• author:选择当前节点的所有author子元素

3.3 通配符

XPath提供了几种通配符,用于匹配未知节点:

• *:匹配任何元素节点
• @*:匹配任何属性节点
• node():匹配任何类型的节点(元素、属性、文本、注释等)
• text():匹配文本节点

示例:

• /bookstore/*:选择bookstore下的所有子元素节点
• /bookstore/book/*:选择所有book元素下的所有子元素节点
• /bookstore/book/@*:选择所有book元素的所有属性
• //title[@*]:选择具有任何属性的title元素
• //title/text():选择所有title元素的文本内容

3.4 多路径选择

使用管道符(|)可以组合多个路径表达式,选择匹配任一表达式的节点。

示例:

• /bookstore/book/title | /bookstore/book/author:选择所有book元素下的title和author子元素
• //title | //price:选择文档中所有的title和price元素

4. 谓语(Predicates):使用条件过滤节点

谓语用于过滤节点集合,它放在方括号[]中,可以对选定的节点应用条件。谓语可以包含数字、比较运算符、逻辑运算符和XPath函数。

4.1 基本谓语

示例:

• /bookstore/book[1]:选择第一个book元素
• /bookstore/book[last()]:选择最后一个book元素
• /bookstore/book[position() < 3]:选择前两个book元素
• /bookstore/book[price]:选择包含price子元素的book元素
• /bookstore/book[price > 20]:选择price子元素值大于20的book元素
• /bookstore/book[category = 'fiction']:选择category属性值为’fiction’的book元素

4.2 多条件谓语

可以使用逻辑运算符(and、or)组合多个条件:

• /bookstore/book[price > 20 and price < 30]:选择price子元素值大于20且小于30的book元素
• /bookstore/book[category = 'fiction' or category = 'children']:选择category属性值为’fiction’或’children’的book元素

4.3 嵌套谓语

谓语可以嵌套使用,以实现更复杂的过滤:

• /bookstore/book[title[text() = 'Harry Potter']]:选择title子元素的文本内容为’Harry Potter’的book元素
• /bookstore/book[author[text() = 'J.K. Rowling' or text() = 'L. Frank Baum']]:选择author子元素的文本内容为’J.K. Rowling’或’L. Frank Baum’的book元素

5. XPath轴:不同类型的轴及其用法

XPath轴定义了相对于当前节点的节点集合。轴指定了从当前节点出发,在文档树中移动的方向和范围。XPath 1.0定义了13种轴。

5.1 常用轴

子轴是默认轴,包含当前节点的所有子节点。由于它是默认轴,通常可以省略。

示例:

• child::book:选择当前节点的所有book子元素(等同于book)
• child::*:选择当前节点的所有子元素(等同于*)
• child::text():选择当前节点的所有文本子节点

属性轴包含当前节点的所有属性节点。可以使用简写形式@。

示例:

• attribute::category:选择当前节点的category属性(等同于@category)
• attribute::*:选择当前节点的所有属性(等同于@*)

父轴包含当前节点的父节点。可以使用简写形式..。

示例:

• parent::bookstore:选择当前节点的bookstore父元素(等同于../bookstore,但更准确)
• parent::*:选择当前节点的父元素(等同于..)

后代轴包含当前节点的所有后代节点(子节点、孙节点等)。可以使用简写形式//。

示例:

• descendant::title:选择当前节点的所有title后代元素
• descendant::*:选择当前节点的所有后代元素
• /bookstore/descendant::price:选择bookstore元素的所有price后代元素(等同于/bookstore//price)

祖先轴包含当前节点的所有祖先节点(父节点、祖父节点等)。

示例:

• ancestor::bookstore:选择当前节点的bookstore祖先元素
• ancestor::*:选择当前节点的所有祖先元素

自身轴只包含当前节点本身。可以使用简写形式.。

示例:

• self::book:如果当前节点是book元素,则选择它(等同于.)
• self::*:选择当前节点本身(等同于.)

5.2 其他轴

后代或自身轴包含当前节点本身及其所有后代节点。可以使用简写形式//。

示例:

• descendant-or-self::book:选择当前节点(如果是book元素)及其所有book后代元素
• /bookstore/descendant-or-self::*:选择bookstore元素及其所有后代元素(等同于/bookstore//*)

祖先或自身轴包含当前节点本身及其所有祖先节点。

示例:

• ancestor-or-self::bookstore:选择当前节点(如果是bookstore元素)及其所有bookstore祖先元素
• ancestor-or-self::*:选择当前节点及其所有祖先元素

前轴包含当前节点之前的所有同级节点。

示例:

• preceding-sibling::book:选择当前节点之前的所有book同级元素
• preceding-sibling::*:选择当前节点之前的所有同级元素

后轴包含当前节点之后的所有同级节点。

示例:

• following-sibling::book:选择当前节点之后的所有book同级元素
• following-sibling::*:选择当前节点之后的所有同级元素

前轴包含当前节点之前的所有节点(不包括祖先节点和属性/命名空间节点)。

示例:

• preceding::book:选择当前节点之前的所有book元素
• preceding::*:选择当前节点之前的所有元素

后轴包含当前节点之后的所有节点(不包括后代节点和属性/命名空间节点)。

示例:

• following::book:选择当前节点之后的所有book元素
• following::*:选择当前节点之后的所有元素

命名空间轴包含当前节点的命名空间节点。

示例:

• namespace::*:选择当前节点的所有命名空间节点

5.3 轴的实际应用示例

考虑以下更复杂的XML文档:
  1. <?xml version="1.0"?>
  2. <library>
  3.   <section name="Fiction">
  4.     <shelf id="A1">
  5.       <book category="fiction">
  6.         <title lang="en">Harry Potter</title>
  7.         <author>J.K. Rowling</author>
  8.         <year>2005</year>
  9.         <price>29.99</price>
  10.       </book>
  11.       <book category="fantasy">
  12.         <title lang="en">The Lord of the Rings</title>
  13.         <author>J.R.R. Tolkien</author>
  14.         <year>1954</year>
  15.         <price>39.99</price>
  16.       </book>
  17.     </shelf>
  18.     <shelf id="A2">
  19.       <book category="mystery">
  20.         <title lang="en">The Da Vinci Code</title>
  21.         <author>Dan Brown</author>
  22.         <year>2003</year>
  23.         <price>24.99</price>
  24.       </book>
  25.     </shelf>
  26.   </section>
  27.   <section name="Non-Fiction">
  28.     <shelf id="B1">
  29.       <book category="biography">
  30.         <title lang="en">Steve Jobs</title>
  31.         <author>Walter Isaacson</author>
  32.         <year>2011</year>
  33.         <price>34.99</price>
  34.       </book>
  35.     </shelf>
  36.   </section>
  37. </library>
复制代码

使用轴的XPath表达式示例:

• //book/ancestor::section:选择所有book元素的section祖先元素
• //book/ancestor::library:选择所有book元素的library祖先元素
• //book/descendant::title:选择所有book元素的title后代元素(等同于//book/title)
• //book/following-sibling::book:选择每个book元素之后的所有book同级元素
• //book/preceding-sibling::book:选择每个book元素之前的所有book同级元素
• //price/ancestor::book:选择所有price元素的book祖先元素
• //title/parent::book:选择所有title元素的book父元素(等同于//title/..)
• //title/following::price:选择每个title元素之后的所有price元素
• //title/preceding::author:选择每个title元素之前的所有author元素

6. XPath函数:常用函数介绍

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

6.1 节点集函数

返回当前上下文中的最后一个节点的位置索引。

示例:

• /library/section/book[last()]:选择每个section中的最后一个book元素
• //book[last()]:选择文档中的最后一个book元素

返回当前节点的位置索引。

示例:

• /library/section/book[position() = 1]:选择每个section中的第一个book元素(等同于/library/section/book[1])
• /library/section/book[position() < 3]:选择每个section中的前两个book元素
• /library/section/book[position() mod 2 = 0]:选择每个section中偶数位置的book元素

返回节点集中的节点数量。

示例:

• count(/library/section/book):返回文档中所有book元素的数量
• /library/section[count(book) > 1]:选择包含多于一个book元素的section元素
• //book[count(author) = 1]:选择只包含一个author子元素的book元素

根据ID选择元素。注意:这要求文档有DTD或Schema定义了ID属性。

示例:

• id('A1'):选择ID为’A1’的元素
• id('A1')/book:选择ID为’A1’的元素下的所有book子元素

返回节点的本地名称(不带命名空间前缀)。

示例:

• local-name(//book):返回’book’
• //*[local-name() = 'book']:选择本地名称为’book’的所有元素(不考虑命名空间)

返回节点的命名空间URI。

示例:

• namespace-uri(//book):返回book元素的命名空间URI
• //*[namespace-uri() = 'http://example.com']:选择命名空间URI为’http://example.com’的所有元素

返回节点的限定名称(带命名空间前缀)。

示例:

• name(//book):返回’book’或’ns:book’(如果有命名空间前缀)
• //*[name() = 'book']:选择名称为’book’的所有元素

6.2 字符串函数

将对象转换为字符串。

示例:

• string(//book[1]/price):将第一个book元素的price子元素转换为字符串
• string(42):返回’42’

连接多个字符串。

示例:

• concat('Title: ', //book[1]/title):连接字符串’Title: ‘和第一个book元素的title子元素的文本内容
• concat(//book[1]/author, ' (', //book[1]/year, ')'):连接作者名、括号和出版年份

检查一个字符串是否以另一个字符串开头。

示例:

• //book[starts-with(title, 'Harry')]:选择title子元素文本以’Harry’开头的book元素
• //book[starts-with(@category, 'fic')]:选择category属性以’fic’开头的book元素

检查一个字符串是否包含另一个字符串。

示例:

• //book[contains(title, 'Potter')]:选择title子元素文本包含’Potter’的book元素
• //book[contains(author, 'Rowling')]:选择author子元素文本包含’Rowling’的book元素

返回第一个字符串中在第二个字符串出现之前的部分。

示例:

• substring-before(//book[1]/author, ' '):返回第一个book元素的author子元素文本中第一个空格之前的部分
• substring-before('2005-01-01', '-'):返回’2005’

返回第一个字符串中在第二个字符串出现之后的部分。

示例:

• substring-after(//book[1]/author, ' '):返回第一个book元素的author子元素文本中第一个空格之后的部分
• substring-after('2005-01-01', '-'):返回’01-01’

返回字符串的子串。

示例:

• substring(//book[1]/title, 1, 5):返回第一个book元素的title子元素文本的前5个字符
• substring(//book[1]/author, 3):返回第一个book元素的author子元素文本从第3个字符开始的子串

返回字符串的长度。

示例:

• string-length(//book[1]/title):返回第一个book元素的title子元素文本的长度
• //book[string-length(title) > 10]:选择title子元素文本长度大于10的book元素

规范化字符串,去除前后空格并将内部连续空格替换为单个空格。

示例:

• normalize-space(//book[1]/title):规范化第一个book元素的title子元素的文本
• //book[normalize-space(title) = 'Harry Potter']:选择title子元素文本规范化后等于’Harry Potter’的book元素

替换字符串中的字符。

示例:

• translate(//book[1]/title, 'abc', 'ABC'):将第一个book元素的title子元素文本中的’a’、’b’、’c’替换为’A’、’B’、’C’
• translate(//book[1]/author, 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'):将第一个book元素的author子元素文本中的小写字母转换为大写字母

6.3 布尔函数

将对象转换为布尔值。

示例:

• boolean(//book[1]/price):如果第一个book元素有price子元素,则返回true
• boolean(//book[price > 30]):如果存在price子元素值大于30的book元素,则返回true

返回布尔值的相反值。

示例:

• //book[not(price)]:选择没有price子元素的book元素
• //book[not(@category = 'fiction')]:选择category属性不等于’fiction’的book元素

返回true。

示例:

• //book[true()]:选择所有book元素(等同于//book)

返回false。

示例:

• //book[false()]:不选择任何book元素

检查当前节点的语言是否与指定的语言匹配。

示例:

• //title[lang('en')]:选择语言为英语的title元素
• //book[lang('fr')]:选择语言为法语的book元素

6.4 数字函数

将对象转换为数字。

示例:

• number(//book[1]/price):将第一个book元素的price子元素转换为数字
• number('42'):返回42

返回节点集中所有节点的数值总和。

示例:

• sum(//book/price):返回所有price子元素值的总和
• sum(//book[year > 2000]/price):返回year子元素值大于2000的book元素的price子元素值的总和

返回不大于数字的最大整数。

示例:

• floor(//book[1]/price):返回不大于第一个book元素的price子元素值的最大整数
• floor(29.99):返回29

返回不小于数字的最小整数。

示例:

• ceiling(//book[1]/price):返回不小于第一个book元素的price子元素值的最小整数
• ceiling(29.01):返回30

返回最接近数字的整数。

示例:

• round(//book[1]/price):返回最接近第一个book元素的price子元素值的整数
• round(29.5):返回30

7. 实际应用示例:结合实际XML文档演示XPath的使用

让我们通过一个更复杂的实际XML文档来演示XPath的应用。假设我们有以下表示公司组织结构的XML文档:
  1. <?xml version="1.0"?>
  2. <company name="TechCorp">
  3.   <departments>
  4.     <department id="d1" name="Engineering">
  5.       <manager emp_id="e1">
  6.         <name>Alice Johnson</name>
  7.         <email>alice@techcorp.com</email>
  8.         <phone>123-456-7890</phone>
  9.       </manager>
  10.       <employees>
  11.         <employee emp_id="e2">
  12.           <name>Bob Smith</name>
  13.           <email>bob@techcorp.com</email>
  14.           <phone>234-567-8901</phone>
  15.           <skills>
  16.             <skill>Java</skill>
  17.             <skill>Python</skill>
  18.           </skills>
  19.         </employee>
  20.         <employee emp_id="e3">
  21.           <name>Charlie Brown</name>
  22.           <email>charlie@techcorp.com</email>
  23.           <phone>345-678-9012</phone>
  24.           <skills>
  25.             <skill>C++</skill>
  26.             <skill>JavaScript</skill>
  27.           </skills>
  28.         </employee>
  29.       </employees>
  30.     </department>
  31.     <department id="d2" name="Marketing">
  32.       <manager emp_id="e4">
  33.         <name>Diana Prince</name>
  34.         <email>diana@techcorp.com</email>
  35.         <phone>456-789-0123</phone>
  36.       </manager>
  37.       <employees>
  38.         <employee emp_id="e5">
  39.           <name>Eve Adams</name>
  40.           <email>eve@techcorp.com</email>
  41.           <phone>567-890-1234</phone>
  42.           <skills>
  43.             <skill>SEO</skill>
  44.             <skill>Content Marketing</skill>
  45.           </skills>
  46.         </employee>
  47.       </employees>
  48.     </department>
  49.   </departments>
  50.   <projects>
  51.     <project id="p1" dept_id="d1">
  52.       <name>Website Redesign</name>
  53.       <start_date>2023-01-01</start_date>
  54.       <end_date>2023-06-30</end_date>
  55.       <team>
  56.         <member emp_id="e1" role="Project Manager"/>
  57.         <member emp_id="e2" role="Developer"/>
  58.         <member emp_id="e3" role="Developer"/>
  59.       </team>
  60.     </project>
  61.     <project id="p2" dept_id="d2">
  62.       <name>Product Launch Campaign</name>
  63.       <start_date>2023-03-01</start_date>
  64.       <end_date>2023-09-30</end_date>
  65.       <team>
  66.         <member emp_id="e4" role="Project Manager"/>
  67.         <member emp_id="e5" role="Marketing Specialist"/>
  68.       </team>
  69.     </project>
  70.   </projects>
  71. </company>
复制代码

7.1 基本查询示例
  1. /company/departments/department
复制代码

这个表达式选择所有department元素。
  1. //employee
复制代码

这个表达式选择文档中所有的employee元素,无论它们在哪个部门。
  1. //manager
复制代码

这个表达式选择文档中所有的manager元素。
  1. /company/projects/project
复制代码

这个表达式选择所有project元素。

7.2 条件查询示例
  1. /company/departments/department[@name='Engineering']
复制代码

这个表达式选择name属性为’Engineering’的department元素。
  1. //employee[skills/skill='Java']
复制代码

这个表达式选择拥有Java技能的employee元素。
  1. //project[starts-with(start_date, '2023')]
复制代码

这个表达式选择start_date以’2023’开头的project元素。
  1. //employee[@emp_id='e2']
复制代码

这个表达式选择emp_id属性为’e2’的employee元素。

7.3 复杂查询示例
  1. //manager/name | //manager/email
复制代码

这个表达式选择所有manager元素的name和email子元素。
  1. /company/departments/department[@name='Engineering']//employee
复制代码

这个表达式选择Engineering部门下的所有employee元素。
  1. //project[name='Website Redesign']/team/member
复制代码

这个表达式选择参与”Website Redesign”项目的所有member元素。
  1. //employee[count(skills/skill) > 1]
复制代码

这个表达式选择拥有多于一个skill子元素的employee元素。

7.4 使用函数的查询示例
  1. count(//employee)
复制代码

这个表达式计算文档中所有employee元素的数量。
  1. //employee[contains(name, 'Smith')]
复制代码

这个表达式选择name子元素包含”Smith”的employee元素。

XPath 1.0中没有ends-with函数,但我们可以使用substring和string-length来模拟:
  1. //employee[substring(email, string-length(email) - 10) = 'techcorp.com']
复制代码

这个表达式选择email子元素以”techcorp.com”结尾的employee元素。
  1. //project/start_date
复制代码

这个表达式选择所有project元素的start_date子元素。

7.5 使用轴的查询示例
  1. //department/manager
复制代码

这个表达式选择所有department元素的manager子元素。
  1. //employee/ancestor::department/@name
复制代码

这个表达式选择所有employee元素的department祖先元素的name属性。
  1. //project/preceding::department[@id = ../@dept_id]/@name
复制代码

这个表达式选择所有project元素的dept_id属性所对应的department元素的name属性。
  1. //employee[@emp_id = //project/team/member/@emp_id]
复制代码

这个表达式选择参与项目的所有employee元素。

8. 最佳实践和常见错误

8.1 最佳实践

• 绝对路径(以/开头)从文档根开始,适合精确指定位置。
• 相对路径(不以/开头)从当前节点开始,适合在特定上下文中使用。

选择哪种路径取决于你的需求。如果你知道文档结构并且需要精确位置,使用绝对路径。如果你需要在不同上下文中重用表达式,使用相对路径。

谓词是XPath的强大功能,可以精确过滤节点集合。合理使用谓词可以大大提高XPath表达式的效率和准确性。
  1. //book[category='fiction' and price > 20]
复制代码

这个表达式选择category属性为’fiction’且price子元素大于20的所有book元素。

XPath提供了丰富的函数库,可以处理字符串、数字和布尔值。合理使用这些函数可以简化表达式并提高效率。
  1. //book[contains(title, 'Harry') and number(price) > 20]
复制代码

这个表达式选择title子元素包含’Harry’且price子元素大于20的所有book元素。

过于宽泛的查询(如//*)可能会选择大量节点,降低性能。尽量使用更具体的路径表达式。
  1. //book/title
复制代码

这个表达式比//title更具体,因为它只选择book元素下的title元素。

XPath轴提供了强大的导航能力,可以根据节点之间的关系选择节点。合理使用轴可以简化复杂的查询。
  1. //title/ancestor::book
复制代码

这个表达式选择所有title元素的book祖先元素。

8.2 常见错误

属性使用@前缀,而元素不需要。混淆两者是常见错误。

错误示例:
  1. //book/category  # 错误:category是属性,不是元素
复制代码

正确示例:
  1. //book/@category  # 正确:使用@前缀选择属性
复制代码

XPath是区分大小写的。元素和属性名称必须与XML文档中的完全匹配。

错误示例:
  1. //Book  # 错误:元素名称是book,不是Book
复制代码

正确示例:
  1. //book  # 正确:使用正确的大小写
复制代码

谓语中的表达式必须返回布尔值。错误使用谓语会导致意外结果。

错误示例:
  1. //book[title]  # 这个表达式是正确的,但下面的不是
  2. //book[title/text()]  # 错误:这不是布尔表达式
复制代码

正确示例:
  1. //book[title]  # 正确:检查是否存在title子元素
  2. //book[title != '']  # 正确:检查title子元素是否非空
复制代码

XPath路径和表达式是不同的概念。路径用于选择节点,而表达式用于计算值。

错误示例:
  1. //book/price + 5  # 错误:这不是有效的路径表达式
复制代码

正确示例:
  1. //book/price  # 正确:选择price元素
  2. //book/price[number(.) + 5]  # 正确:使用谓语中的表达式
复制代码

如果XML文档使用命名空间,必须在XPath表达式中考虑命名空间。忽略命名空间是常见错误。

错误示例:
  1. //book  # 错误:如果book在命名空间中,这个表达式不会选择它
复制代码

正确示例:
  1. //ns:book  # 正确:使用命名空间前缀
  2. //*[local-name() = 'book']  # 正确:使用local-name函数忽略命名空间
复制代码

9. 总结

XPath 1.0是一种强大的语言,用于在XML文档中导航和选择节点。通过掌握XPath的基础用法,包括路径表达式、谓语、轴和函数,你可以轻松解析和提取XML文档中的数据。

本文介绍了XPath的基本概念,包括节点类型、路径表达式、谓语、轴导航和常用函数。通过实际示例,我们展示了如何使用XPath查询XML文档,并提供了最佳实践和常见错误的指导。

XPath是处理XML文档的必备技能,无论是在Web开发、数据集成还是内容管理系统中都有广泛应用。掌握XPath 1.0的基础用法,将使你能够更高效地处理XML数据,为你的项目带来更大的灵活性和功能性。

随着XML技术的不断发展,XPath也在不断演进。虽然XPath 1.0仍然被广泛使用,但XPath 2.0和3.0提供了更多功能和更好的性能。不过,掌握XPath 1.0的基础用法是学习更高级版本的前提,也是处理大多数XML文档任务的 sufficient 工具。

希望这篇教程能帮助你掌握XPath 1.0的基础用法,并在实际项目中应用这些知识。随着你的经验增长,你将发现XPath的更多强大功能,并能够更高效地处理XML数据。
「七転び八起き(ななころびやおき)」
回复

使用道具 举报

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

本版积分规则