掌握 XPath:高效查找 XML 信息(一)

XPath 是一种强大的语言,用于在 XML 文档中查找和定位信息。它不仅在 XSLT 中扮演着重要角色,还被广泛应用于 XQuery 和 XPointer 等其他 XML 处理技术中。本文将详细介绍 XPath 的基本概念、语法、路径表达式、标准函数、运算符以及在实际开发中的应用。通过本文的学习,你将能够熟练掌握 XPath 的使用方法,提升在 XML 数据处理方面的技能。

在学习之前应该具备的知识

在深入学习 XPath 之前,建议你对以下技术有一定的了解:

  • HTML / XHTML:熟悉基本的网页结构和语法。
  • XML / XML Namespaces:了解 XML 的基本概念和命名空间的使用。

如果你需要补充这些基础知识,可以在 菜鸟教程 找到相关的教程。

什么是 XPath?

XPath 是一门用于在 XML 文档中查找信息的语言。它的主要特点包括:

  • 路径表达式:使用类似于文件系统的路径表达式来定位 XML 文档中的节点。
  • 标准函数库:提供超过 100 个内置函数,用于处理字符串、数值、日期和时间等数据。
  • XSLT 的核心:XPath 是 XSLT 的主要组成部分,没有 XPath,XSLT 将无法正常工作。
  • W3C 标准:XPath 于 1999 年 11 月 16 日成为 W3C 标准,被设计为供 XSLT、XPointer 以及其他 XML 解析软件使用。

XPath 的基本概念

节点

在 XPath 中,XML 文档被视为一个节点树。每个节点都有特定的类型,常见的节点类型包括:

  • 元素节点:表示 XML 文档中的元素,如 <book>。
  • 属性节点:表示元素的属性,如 lang="en"。
  • 文本节点:表示元素中的文本内容,如 Harry Potter。
  • 命名空间节点:表示 XML 命名空间。
  • 处理指令节点:表示处理指令,如 <?xml-stylesheet type="text/xsl" href="style.xsl"?>。
  • 注释节点:表示注释,如 <!-- 这是一个注释 -->。
  • 文档节点(根节点):表示整个 XML 文档的根。

基本值(或称原子值,Atomic value)

基本值是没有父节点或子节点的节点。例如,J K. Rowling 和 "en" 都是基本值。

项目(Item)

项目可以是基本值或节点。在 XPath 中,项目是处理的基本单位。

节点关系

父(Parent)

每个元素和属性节点都有一个父节点。例如,在以下 XML 片段中,book 元素是 title、author、year 和 price 元素的父节点:


<book>

<title>Harry Potter</title>

<author>J K. Rowling</author>

<year>2005</year>

<price>29.99</price>
</book>

子(Children)

元素节点可以有零个、一个或多个子节点。例如,在上述片段中,title、author、year 和 price 元素都是 book 元素的子节点。

同胞(Sibling)

拥有相同父节点的节点称为同胞。例如,在上述片段中,title、author、year 和 price 元素都是同胞节点。

先辈(Ancestor)

先辈节点包括父节点、父的父节点等。例如,在以下 XML 片段中,title 元素的先辈节点是 book 和 bookstore:


<bookstore>

<book>

<title>Harry Potter</title>

<author>J K. Rowling</author>

<year>2005</year>

<price>29.99</price>
    </book>
</bookstore>

后代(Descendant)

后代节点包括子节点、子的子节点等。例如,在上述片段中,bookstore 的后代节点包括 book、title、author、year 和 price。

XPath 的语法

路径表达式

XPath 使用路径表达式来选取 XML 文档中的节点。路径表达式由一系列的步(step)组成,每一步可以包含节点测试、谓语和轴。

常见的路径表达式

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

示例

假设我们有以下 XML 文档:

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>

<book>
        <title lang="en">Harry Potter</title>

<price>29.99</price>
    </book>

<book>
        <title lang="en">Learning XML</title>

<price>39.95</price>
    </book>
</bookstore>

以下是一些常用的路径表达式及其结果:

  • /bookstore:选取所有名为 bookstore 的节点。
  • /bookstore/book:选取属于 bookstore 的子元素的所有 book 元素。
  • //book:选取所有 book 子元素,而不管它们在文档中的位置。
  • /bookstore//book:选取属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。
  • //@lang:选取名为 lang 的所有属性。

谓语(Predicates)

谓语用于在路径表达式中进一步筛选节点。谓语被嵌在方括号中。

示例

  • /bookstore/book[1]:选取属于 bookstore 子元素的第一个 book 元素。

  • /bookstore/book[last()]:选取属于 bookstore 子元素的最后一个 book 元素。

  • /bookstore/book[last()-1]:选取属于 bookstore 子元素的倒数第二个 book 元素。

  • /bookstore/book[position()<3]:选取最前面的两个属于 bookstore 元素的子元素的 book 元素。

  • //title[@lang]:选取所有带有名为 lang 的属性的 title 元素。

  • //title[@lang='en']:选取所有 title 元素,且这些元素拥有值为 en 的 lang 属性。

  • /bookstore/book[price>35.00]:选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。

  • /bookstore/book[price>35.00]//title:选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。

通配符

XPath 通配符用于选取未知的 XML 元素。

常见的通配符

  • *:匹配任何元素节点。
  • @*:匹配任何属性节点。
  • node():匹配任何类型的节点。

示例

  • /bookstore/*:选取 bookstore 元素的所有子元素。
  • //*:选取文档中的所有元素。
  • //title[@*]:选取所有带有属性的 title 元素。

选取多个路径

通过在路径表达式中使用 | 运算符,可以同时选取多个路径。

示例

  • //book/title | //book/price:选取 book 元素的所有 title 和 price 元素。
  • //title | //price:选取文档中的所有 title 和 price 元素。
  • /bookstore/book/title | //price:选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。

XPath 轴(Axes)

轴用于定义相对于当前节点的节点集。

常见的轴

  • ancestor:选取当前节点的所有先辈(父、祖父等)。
  • ancestor-or-self:选取当前节点的所有先辈(父、祖父等)以及当前节点本身。
  • attribute:选取当前节点的所有属性。
  • child:选取当前节点的所有子元素。
  • descendant:选取当前节点的所有后代元素(子、孙等)。
  • descendant-or-self:选取当前节点的所有后代元素(子、孙等)以及当前节点本身。
  • following:选取文档中当前节点的结束标签之后的所有节点。
  • following-sibling:选取当前节点之后的所有兄弟节点。
  • namespace:选取当前节点的所有命名空间节点。
  • parent:选取当前节点的父节点。
  • preceding:选取文档中当前节点的开始标签之前的所有节点。
  • preceding-sibling:选取当前节点之前的所有同级节点。
  • self:选取当前节点。

示例

  • ancestor::book:选取当前节点的所有 book 先辈。
  • descendant::title:选取当前节点的所有 title 后代。

XPath 运算符

XPath 提供了多种运算符,用于在路径表达式中进行计算和比较。

常见的运算符

  • |:计算两个节点集。
  • +:加法。
  • -:减法。
  • *:乘法。
  • div:除法。
  • =:等于。
  • !=:不等于。
  • <:小于。
  • <=:小于或等于。
  • >:大于。
  • >=:大于或等于。
  • or:或。
  • and:与。
  • mod:计算除法的余数。

示例

  • 6 + 4:返回 10。
  • 8 div 4:返回 2。
  • price=9.80:如果 price 是 9.80,则返回 true;如果 price 是 9.90,则返回 false。
  • price>9.80:如果 price 是 9.90,则返回 true;如果 price 是 9.80,则返回 false。
  • price=9.80 or price=9.70:如果 price 是 9.80,则返回 true;如果 price 是 9.50,则返回 false。
  • 5 mod 2:返回 1。

实际应用示例

假设我们有以下 XML 文档:

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
    <book category="COOKING">
        <title lang="en">Everyday Italian</title>

<author>Giada De Laurentiis</author>

<year>2005</year>

<price>30.00</price>
    </book>
    <book category="CHILDREN">
        <title lang="en">Harry Potter</title>

<author>J K. Rowling</author>

<year>2005</year>

<price>29.99</price>
    </book>
    <book category="WEB">
        <title lang="en">XQuery Kick Start</title>

<author>James McGovern</author>

<author>Per Bothner</author>

<author>Kurt Cagle</author>

<author>James Linn</author>

<author>Vaidyanathan Nagarajan</author>

<year>2003</year>

<price>49.99</price>
    </book>
    <book category="WEB">
        <title lang="en">Learning XML</title>

<author>Erik T. Ray</author>

<year>2003</year>

<price>39.95</price>
    </book>
</bookstore>

示例 1:选取所有价格大于 35.00 的书籍

/bookstore/book[price>35.00]

示例 2:选取所有类别为 WEB 的书籍

/bookstore/book[@category='WEB']

示例 3:选取所有带有 lang 属性的 title 元素

//title[@lang]

示例 4:选取所有 book 元素的 author 子元素

/bookstore/book/author

总结

通过本文的学习,你已经掌握了 XPath 的基本概念、语法、路径表达式、标准函数、运算符以及在实际开发中的应用。XPath 是一个强大且灵活的工具,能够帮助你在 XML 文档中高效地查找和处理信息。希望本文能为你在 XML 数据处理方面提供有价值的指导。如果你有任何问题或需要进一步的帮助,欢迎在评论区留言。