|
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
引言
XPath是一种在XML文档中查找信息的语言,它使用路径表达式在XML文档中进行导航。XPath包含一个标准函数库,用于处理字符串、数值、日期时间比较、节点和 QName 处理、序列处理、逻辑值等多种数据类型。掌握XPath函数的使用技巧,可以大大提高XML数据处理的效率和准确性。本文将详细介绍XPath常用函数的使用技巧,并通过实例帮助读者更好地理解和应用这些函数。
XPath基础
XPath使用路径表达式来选取XML文档中的节点或节点集。这些路径表达式类似于在文件系统中使用的路径表达式。XPath是W3C标准,它是XSLT、XQuery和XPointer等XML技术的基础。
一个基本的XPath表达式由一个或多个位置步骤组成,每个步骤由一个轴、一个节点测试和零个或多个谓词组成。例如:
- /bookstore/book[price>35.00]/title
复制代码
这个表达式表示:选择bookstore元素下所有price子元素值大于35.00的book元素的title子元素。
XPath常用函数分类
XPath函数库提供了丰富的函数,可以满足各种数据处理需求。下面我们将分类介绍这些函数。
节点函数
节点函数用于处理节点和节点集。
last()函数返回当前处理节点的节点集中的节点数量。
示例:假设我们有以下XML文档:
- <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>
- <year>2003</year>
- <price>49.99</price>
- </book>
- </bookstore>
复制代码
使用last()函数:
这个表达式选择bookstore中的最后一个book元素。
position()函数返回当前节点在节点集中的位置。
示例:
- /bookstore/book[position() < 3]
复制代码
这个表达式选择bookstore中的前两个book元素。
count()函数返回节点集中的节点数量。
示例:
这个表达式返回bookstore中book元素的数量。
name()函数返回当前节点的名称。
示例:
- name(/bookstore/book[1]/*[1])
复制代码
这个表达式返回第一个book元素的第一个子元素的名称,即”title”。
local-name()函数返回当前节点的本地名称(不带命名空间前缀)。
示例:
- local-name(/bookstore/book[1]/*[1])
复制代码
这个表达式返回第一个book元素的第一个子元素的本地名称,即”title”。
namespace-uri()函数返回当前节点的命名空间URI。
示例:
- namespace-uri(/bookstore/book[1])
复制代码
这个表达式返回第一个book元素的命名空间URI。
字符串函数
字符串函数用于处理字符串值。
string()函数将参数转换为字符串。
示例:
这个表达式返回字符串”123”。
concat()函数连接两个或多个字符串。
示例:
- concat('Hello', ' ', 'World')
复制代码
这个表达式返回字符串”Hello World”。
starts-with()函数检查一个字符串是否以指定字符串开头。
示例:
- /bookstore/book[starts-with(title, 'Everyday')]
复制代码
这个表达式选择title元素以”Everyday”开头的book元素。
contains()函数检查一个字符串是否包含指定字符串。
示例:
- /bookstore/book[contains(title, 'Potter')]
复制代码
这个表达式选择title元素包含”Potter”的book元素。
substring()函数返回字符串的子串。
示例:
- substring('Hello World', 1, 5)
复制代码
这个表达式返回字符串”Hello”。
substring-before()函数返回指定子串之前的子串。
示例:
- substring-before('Hello World', ' ')
复制代码
这个表达式返回字符串”Hello”。
substring-after()函数返回指定子串之后的子串。
示例:
- substring-after('Hello World', ' ')
复制代码
这个表达式返回字符串”World”。
string-length()函数返回字符串的长度。
示例:
这个表达式返回数字5。
normalize-space()函数去除字符串前后的空白,并将内部的连续空白替换为单个空格。
示例:
- normalize-space(' Hello World ')
复制代码
这个表达式返回字符串”Hello World”。
translate()函数将字符串中的字符替换为指定的字符。
示例:
- translate('Hello', 'Hl', 'Ji')
复制代码
这个表达式返回字符串”Jeiio”。
数值函数
数值函数用于处理数值。
number()函数将参数转换为数值。
示例:
这个表达式返回数字123。
floor()函数返回不大于参数的最大整数。
示例:
这个表达式返回数字3。
ceiling()函数返回不小于参数的最小整数。
示例:
这个表达式返回数字4。
round()函数返回最接近参数的整数。
示例:
这个表达式返回数字3。
sum()函数返回节点集中所有节点的数值总和。
示例:
- sum(/bookstore/book/price)
复制代码
这个表达式返回所有book元素的price子元素的总和。
布尔函数
布尔函数用于处理布尔值。
boolean()函数将参数转换为布尔值。
示例:
这个表达式返回false。
not()函数返回参数的布尔值的相反值。
示例:
这个表达式返回false。
true()函数返回布尔值true。
示例:
这个表达式返回true。
false()函数返回布尔值false。
示例:
这个表达式返回false。
lang()函数检查当前节点的语言是否与指定的语言匹配。
示例:
- /bookstore/book/title[lang('en')]
复制代码
这个表达式选择语言为英语的title元素。
日期时间函数
XPath 2.0及以上版本提供了丰富的日期时间函数。
current-date()函数返回当前日期。
示例:
这个表达式返回当前日期。
current-time()函数返回当前时间。
示例:
这个表达式返回当前时间。
current-dateTime()函数返回当前日期和时间。
示例:
这个表达式返回当前日期和时间。
year-from-date()函数从日期中提取年份。
示例:
- year-from-date(xs:date('2023-05-15'))
复制代码
这个表达式返回2023。
month-from-date()函数从日期中提取月份。
示例:
- month-from-date(xs:date('2023-05-15'))
复制代码
这个表达式返回5。
day-from-date()函数从日期中提取日。
示例:
- day-from-date(xs:date('2023-05-15'))
复制代码
这个表达式返回15。
其他实用函数
id()函数通过元素的ID选择元素。
示例:假设我们有以下XML文档:
- <bookstore>
- <book id="bk101">
- <title>XML Developer's Guide</title>
- <author>Gambardella, Matthew</author>
- </book>
- <book id="bk102">
- <title>Midnight Rain</title>
- <author>Ralls, Kim</author>
- </book>
- </bookstore>
复制代码
使用id()函数:
这个表达式选择ID为”bk101”的元素。
doc()函数加载XML文档。
示例:
- doc('books.xml')/bookstore/book
复制代码
这个表达式加载books.xml文档并选择其中的book元素。
实用技巧与最佳实践
1. 组合使用函数
XPath函数可以组合使用,以实现更复杂的功能。
示例:
- /bookstore/book[contains(title, 'XML') and number(price) > 30]
复制代码
这个表达式选择title包含”XML”且price大于30的book元素。
2. 使用谓词过滤结果
谓词用于查找某个特定的节点或者包含某个指定的值的节点。
示例:
这个表达式选择第一个book元素。
- /bookstore/book[price > 35]
复制代码
这个表达式选择price大于35的book元素。
3. 使用轴(Axis)导航
XPath轴用于定义相对于当前节点的节点集。
示例:
- /bookstore/book/ancestor::*
复制代码
这个表达式选择所有book元素的祖先元素。
- /bookstore/book/descendant::*
复制代码
这个表达式选择所有book元素的后代元素。
4. 使用变量提高可读性
在XSLT或XQuery中,可以使用变量存储XPath表达式的结果,提高代码的可读性和重用性。
示例:
- <xsl:variable name="totalPrice" select="sum(/bookstore/book/price)" />
- <xsl:value-of select="$totalPrice" />
复制代码
5. 使用命名空间处理复杂文档
当XML文档使用命名空间时,需要在XPath表达式中声明命名空间前缀。
示例:假设我们有以下XML文档:
- <bookstore xmlns:bk="http://example.com/books">
- <bk:book>
- <bk:title>XML Developer's Guide</bk:title>
- <bk:author>Gambardella, Matthew</bk:author>
- </bk:book>
- </bookstore>
复制代码
使用命名空间:
- /*[local-name()='bookstore']/*[local-name()='book']
复制代码
或者,如果在XSLT中声明了命名空间:
- <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:bk="http://example.com/books">
- <xsl:template match="/">
- <xsl:value-of select="/bk:bookstore/bk:book/bk:title" />
- </xsl:template>
- </xsl:stylesheet>
复制代码
实例详解
实例1:提取特定条件的图书信息
假设我们有以下XML文档,存储图书信息:
- <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>
- <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的图书的标题和作者
XPath表达式:
- /bookstore/book[price > 35]/title | /bookstore/book[price > 35]/author
复制代码
或者使用更简洁的方式:
- /bookstore/book[price > 35]/(title, author)
复制代码
需求2:提取所有WEB类别图书的标题,并按价格降序排列
XPath 2.0及以上版本支持排序:
- for $book in /bookstore/book[@category='WEB']
- order by xs:decimal($book/price) descending
- return $book/title
复制代码
需求3:提取所有2005年出版的图书的标题和价格
XPath表达式:
- /bookstore/book[year=2005]/(title, price)
复制代码
实例2:处理复杂的XML结构
假设我们有以下XML文档,存储订单信息:
- <orders>
- <order id="1001">
- <customer>
- <name>John Doe</name>
- <email>john@example.com</email>
- </customer>
- <items>
- <item>
- <product>XML Guide</product>
- <quantity>2</quantity>
- <price>29.99</price>
- </item>
- <item>
- <product>XSLT Basics</product>
- <quantity>1</quantity>
- <price>39.99</price>
- </item>
- </items>
- <order-date>2023-05-10</order-date>
- </order>
- <order id="1002">
- <customer>
- <name>Jane Smith</name>
- <email>jane@example.com</email>
- </customer>
- <items>
- <item>
- <product>XPath Essentials</product>
- <quantity>3</quantity>
- <price>19.99</price>
- </item>
- </items>
- <order-date>2023-05-12</order-date>
- </order>
- </orders>
复制代码
需求1:计算每个订单的总金额
XPath 2.0及以上版本:
- for $order in /orders/order
- let $total := sum($order/items/item/(price * quantity))
- return
- <order id="{$order/@id}" total="{$total}" />
复制代码
需求2:找出购买”XML Guide”的订单
XPath表达式:
- /orders/order[items/item/product='XML Guide']
复制代码
需求3:按客户姓名排序,列出所有订单
XPath 2.0及以上版本:
- for $order in /orders/order
- order by $order/customer/name
- return $order
复制代码
实例3:使用XPath处理大型XML文件
处理大型XML文件时,需要考虑性能问题。以下是一些优化技巧:
需求:从大型XML文件中提取特定信息
假设我们有一个包含大量图书信息的大型XML文件,我们想要提取所有价格在指定范围内的图书,并且只提取标题和作者信息。
XPath表达式:
- /bookstore/book[price >= 20 and price <= 50]/(title, author)
复制代码
为了提高性能,可以考虑以下几点:
1. 使用谓词尽早过滤数据:
- /bookstore/book[price >= 20 and price <= 50]/(title, author)
复制代码
1. 避免使用//轴,因为它会搜索整个文档:
- //book // 性能较差
- /bookstore/book // 性能较好
复制代码
1. 使用特定路径而不是通配符:
- /bookstore/book/* // 性能较差
- /bookstore/book/(title, author) // 性能较好
复制代码
1. 在XSLT或XQuery中使用键(key)来提高性能:
- <xsl:key name="book-by-category" match="book" use="@category" />
复制代码
然后在表达式中使用键:
- key('book-by-category', 'WEB')
复制代码
性能优化建议
1. 避免使用//轴
//轴会搜索整个文档,性能较差。尽量使用具体的路径。
示例:
- //book // 性能较差
- /bookstore/book // 性能较好
复制代码
2. 使用谓词尽早过滤数据
在XPath表达式的早期阶段使用谓词,可以减少后续处理的数据量。
示例:
- /bookstore/book[price > 30]/title // 性能较好
- /bookstore/book/title[../price > 30] // 性能较差
复制代码
3. 避免在谓词中使用函数
在谓词中使用函数会降低性能,因为需要对每个节点调用函数。
示例:
- /bookstore/book[contains(title, 'XML')] // 性能较差
复制代码
4. 使用特定路径而不是通配符
使用具体的元素名称而不是通配符可以提高性能。
示例:
- /bookstore/book/* // 性能较差
- /bookstore/book/(title, author) // 性能较好
复制代码
5. 在XSLT或XQuery中使用键(key)
在XSLT或XQuery中,使用键可以显著提高性能,特别是对于大型文档。
示例:
- <xsl:key name="book-by-category" match="book" use="@category" />
复制代码
然后在表达式中使用键:
- key('book-by-category', 'WEB')
复制代码
6. 使用索引
如果可能,使用数据库或XML数据库的索引功能来提高查询性能。
7. 限制结果集大小
如果只需要前几个结果,使用位置谓词限制结果集大小。
示例:
- /bookstore/book[position() <= 10] // 只返回前10个book元素
复制代码
总结
XPath是一种强大的XML查询语言,通过掌握XPath函数的使用技巧,可以大大提高XML数据处理的效率和准确性。本文详细介绍了XPath的常用函数,包括节点函数、字符串函数、数值函数、布尔函数、日期时间函数和其他实用函数,并通过实例展示了这些函数的实际应用。
在使用XPath时,应该注意性能优化,避免使用//轴,尽早过滤数据,避免在谓词中使用函数,使用特定路径而不是通配符,在XSLT或XQuery中使用键,以及限制结果集大小等。
通过掌握这些技巧,您可以更高效地处理XML数据,提高工作效率。希望本文能够帮助您更好地理解和应用XPath函数,提升XML数据处理的效率。 |
|