XQuery 快速指南



XQuery - 概述

什么是 XQuery

XQuery 是一种函数式语言,用于检索存储在 XML 格式中的信息。XQuery 可用于 XML 文档、包含 XML 格式数据的关联数据库或 XML 数据库。XQuery 3.0 是 W3C 于 2014 年 4 月 8 日发布的推荐标准。

官方文档对 XQuery 的定义如下:

XQuery 是一种标准化的语言,用于组合文档、数据库、网页以及几乎所有其他内容。它得到了非常广泛的应用,功能强大且易于学习。XQuery 正在取代专有的中间件语言和 Web 应用程序开发语言。XQuery 正用几行代码取代复杂的 Java 或 C++ 程序。与许多其他替代方案相比,XQuery 更易于使用和维护。

特点

  • 函数式语言 − XQuery 是一种用于检索/查询基于 XML 的数据的语言。

  • 类似于 SQL − XQuery 之于 XML,如同 SQL 之于数据库。

  • 基于 XPath − XQuery 使用 XPath 表达式来遍历 XML 文档。

  • 普遍接受 − 所有主要的数据库都支持 XQuery。

  • W3C 标准 − XQuery 是 W3C 标准。

XQuery 的优势

  • 使用 XQuery,可以检索分层数据和表格数据。

  • XQuery 可用于查询树形和图形结构。

  • XQuery 可直接用于查询网页。

  • XQuery 可直接用于构建网页。

  • XQuery 可用于转换 XML 文档。

  • XQuery 非常适合基于 XML 的数据库和基于对象的数据库。对象数据库比纯表格数据库灵活且功能强大得多。

XQuery - 环境设置

本章详细介绍如何在本地开发环境中设置 XQuery 库。

我们使用的是广泛使用的开源独立 XQuery 处理器 Saxon Home Edition (Saxon-HE)。此处理器支持 XSLT 2.0、XQuery 3.0 和 XPath 3.0,并且针对性能进行了高度优化。Saxon XQuery 处理器无需任何 XML 数据库即可使用。在我们的示例中,我们将使用一个简单的 XML 文档作为我们的数据库。

为了使用 Saxon XQuery 处理器,您的应用程序的类路径中应该包含 saxon9he.jar、saxon9-test.jar、saxon9-unpack、saxon9-xqj.jar。这些 jar 文件位于下载文件SaxonHE9-6-0-1J.zip 中。下载 SaxonHE9-6-0-1J.zip

示例

我们将使用基于 Java 的 Saxon XQuery 处理器来测试 books.xqy,这是一个包含针对我们的示例 XML 文档(即 books.xml)的 XQuery 表达式的文件。

在这个示例中,我们将了解如何编写和处理查询以获取价格高于 30 的书籍的标题元素。

books.xml

<?xml version="1.0" encoding="UTF-8"?>
<books>
   
   <book category="JAVA">
      <title lang="en">Learn Java in 24 Hours</title>
      <author>Robert</author>
      <year>2005</year>
      <price>30.00</price>
   </book>
   
   <book category="DOTNET">
      <title lang="en">Learn .Net in 24 hours</title>
      <author>Peter</author>
      <year>2011</year>
      <price>40.50</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XQuery in 24 hours</title>
      <author>Robert</author>
      <author>Peter</author> 
      <year>2013</year>
      <price>50.00</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XPath in 24 hours</title>
      <author>Jay Ban</author>
      <year>2010</year>
      <price>16.50</price>
   </book>
   
</books>

books.xqy

for $x in doc("books.xml")/books/book
where $x/price>30
return $x/title

XQueryTester.java

package com.tutorialspoint.xquery;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

import javax.xml.xquery.XQConnection;
import javax.xml.xquery.XQDataSource;
import javax.xml.xquery.XQException;
import javax.xml.xquery.XQPreparedExpression;
import javax.xml.xquery.XQResultSequence;

import com.saxonica.xqj.SaxonXQDataSource;

public class XQueryTester {
   public static void main(String[] args){
      try {
         execute();
      }
      
      catch (FileNotFoundException e) {
         e.printStackTrace();
      }
      
      catch (XQException e) {
         e.printStackTrace();
      }
   }

   private static void execute() throws FileNotFoundException, XQException{
      InputStream inputStream = new FileInputStream(new File("books.xqy"));
      XQDataSource ds = new SaxonXQDataSource();
      XQConnection conn = ds.getConnection();
      XQPreparedExpression exp = conn.prepareExpression(inputStream);
      XQResultSequence result = exp.executeQuery();
      
      while (result.next()) {
         System.out.println(result.getItemAsString(null));
      }
   }	
}

针对 XML 执行 XQuery 的步骤

  • 步骤 1 − 将 XQueryTester.java 复制到任何位置,例如,E: > java

  • 步骤 2 − 将 books.xml 复制到同一位置,E: > java

  • 步骤 3 − 将 books.xqy 复制到同一位置,E: > java

  • 步骤 4 − 使用控制台编译 XQueryTester.java。确保您的计算机上已安装 JDK 1.5 或更高版本,并且已配置类路径。有关如何使用 JAVA 的详细信息,请参阅我们的JAVA 教程

E:\java\javac XQueryTester.java
  • 步骤 5 − 执行 XQueryTester

E:\java\java XQueryTester

输出

您将获得以下结果:

<title lang="en">Learn .Net in 24 hours</title>
<title lang="en">Learn XQuery in 24 hours</title>

理解示例

  • books.xml 代表示例数据。

  • books.xqy 代表要对 books.xml 执行的 XQuery 表达式。我们将在下一章详细了解该表达式。

  • XQueryTester(一个基于 Java 的 XQuery 执行程序)读取 books.xqy,将其传递给 XQuery 表达式处理器,并执行该表达式。然后打印结果。

XQuery - 第一个应用程序

示例

以下是一个示例 XML 文档,其中包含各种书籍的书店记录。

books.xml

<?xml version="1.0" encoding="UTF-8"?>
<books>
   
   <book category="JAVA">
      <title lang="en">Learn Java in 24 Hours</title>
      <author>Robert</author>
      <year>2005</year>
      <price>30.00</price>
   </book>
   
   <book category="DOTNET">
      <title lang="en">Learn .Net in 24 hours</title>
      <author>Peter</author>
      <year>2011</year>
      <price>70.50</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XQuery in 24 hours</title>
      <author>Robert</author>
      <author>Peter</author> 
      <year>2013</year>
      <price>50.00</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XPath in 24 hours</title>
      <author>Jay Ban</author>
      <year>2010</year>
      <price>16.50</price>
   </book>
   
</books>

以下是一个示例 XQuery 文档,其中包含要对上述 XML 文档执行的查询表达式。目的是获取价格高于 30 的那些 XML 节点的标题元素。

books.xqy

for $x in doc("books.xml")/books/book
where $x/price>30
return $x/title

结果

<title lang="en">Learn .Net in 24 hours</title>
<title lang="en">Learn XQuery in 24 hours</title>

验证结果

要验证结果,请将books.xqy(在环境设置章节中给出)的内容替换为上述 XQuery 表达式,然后执行 XQueryTester java 程序。

XQuery 表达式

让我们了解上述 XQuery 表达式的每个部分。

函数的使用

doc("books.xml")

doc() 是 XQuery 函数之一,用于查找 XML 源。这里我们传递了“books.xml”。考虑到相对路径,books.xml 应该位于 books.xqy 所在的同一路径中。

XPath 表达式的使用

doc("books.xml")/books/book

XQuery 大量使用 XPath 表达式来定位要进行搜索的 XML 的所需部分。这里我们选择了 books 节点下所有可用的 book 节点。

迭代对象

for $x in doc("books.xml")/books/book

XQuery 将 xml 数据视为对象。在上面的示例中,$x 代表选定的节点,而 for 循环迭代节点集合。

应用条件

where $x/price>30

由于 $x 代表选定的节点,“/”用于获取所需元素的值;“where”子句用于对搜索结果设置条件。

返回结果

return $x/title

由于 $x 代表选定的节点,“/”用于获取所需元素(价格、标题)的值;“return”子句用于从搜索结果中返回元素。

XQuery - FLWOR

FLWOR 是“For、Let、Where、Order by、Return”的首字母缩写词。以下列表显示了它们在 FLWOR 表达式中的作用:

  • F - For - 选择所有节点的集合。

  • L - Let - 将结果放入 XQuery 变量中。

  • W - Where - 根据条件选择节点。

  • O - Order by - 根据标准对节点进行排序。

  • R - Return - 返回最终结果。

示例

以下是一个示例 XML 文档,其中包含有关书籍集合的信息。我们将使用 FLWOR 表达式来检索价格高于 30 的书籍的标题。

books.xml

<?xml version="1.0" encoding="UTF-8"?>
<books>
   
   <book category="JAVA">
      <title lang="en">Learn Java in 24 Hours</title>
      <author>Robert</author>
      <year>2005</year>
      <price>30.00</price>
   </book>
   
   <book category="DOTNET">
      <title lang="en">Learn .Net in 24 hours</title>
      <author>Peter</author>
      <year>2011</year>
      <price>70.50</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XQuery in 24 hours</title>
      <author>Robert</author>
      <author>Peter</author> 
      <year>2013</year>
      <price>50.00</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XPath in 24 hours</title>
      <author>Jay Ban</author>
      <year>2010</year>
      <price>16.50</price>
   </book>
   
</books>

以下 XQuery 文档包含要对上述 XML 文档执行的查询表达式。

books.xqy

let $books := (doc("books.xml")/books/book)
return <results>
{
   for $x in $books
   where $x/price>30
   order by $x/price
   return $x/title
}
</results>

结果

<title lang="en">Learn XQuery in 24 hours</title>
<title lang="en">Learn .Net in 24 hours</title>

验证结果

要验证结果,请将books.xqy(在环境设置章节中给出)的内容替换为上述 XQuery 表达式,然后执行 XQueryTester java 程序。

XQuery - HTML 格式

XQuery 也可轻松用于将 XML 文档转换为 HTML 页面。请查看以下示例,了解 XQuery 如何实现此功能。

示例

我们将使用相同的 books.xml 文件。以下示例使用 XQuery 从 books.xml 中提取数据,并创建一个包含所有书籍的标题及其相应价格的 HTML 表格。

books.xml

<?xml version="1.0" encoding="UTF-8"?>
<books>
   
   <book category="JAVA">
      <title lang="en">Learn Java in 24 Hours</title>
      <author>Robert</author>
      <year>2005</year>
      <price>30.00</price>
   </book>
   
   <book category="DOTNET">
      <title lang="en">Learn .Net in 24 hours</title>
      <author>Peter</author>
      <year>2011</year>
      <price>70.50</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XQuery in 24 hours</title>
      <author>Robert</author>
      <author>Peter</author> 
      <year>2013</year>
      <price>50.00</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XPath in 24 hours</title>
      <author>Jay Ban</author>
      <year>2010</year>
      <price>16.50</price>
   </book>
   
</books>

以下是将要对上述 XML 文档执行的 XQuery 表达式。

books.xqy

let $books := (doc("books.xml")/books/book)
return <table><tr><th>Title</th><th>Price</th></tr>
{
   for $x in $books   
   order by $x/price
   return <tr><td>{data($x/title)}</td><td>{data($x/price)}</td></tr>
}
</table>
</results>

结果

<table>
   <tr>
      <th>Title</th>
      <th>Price</th>
   </tr>
   <tr>
      <td>Learn XPath in 24 hours</td>
      <td>16.50</td>
   </tr>   
   <tr>
      <td>Learn Java in 24 Hours</td>
      <td>30.00</td>
   </tr>
   <tr>
      <td>Learn XQuery in 24 hours</td>
      <td>50.00</td>
   </tr>   
   <tr>
      <td>Learn .Net in 24 hours</td>
      <td>70.50</td>
   </tr>
</table>

验证结果

要验证结果,请将books.xqy(在环境设置章节中给出)的内容替换为上述 XQuery 表达式,然后执行 XQueryTester java 程序。

XQuery 表达式

这里我们使用了以下 XQuery 表达式:

  • data() 函数来评估标题元素的值,以及

  • {} 运算符告诉 XQuery 处理器将 data() 视为函数。如果不使用 {} 运算符,则 data() 将被视为普通文本。

XQuery - XPath

XQuery 兼容 XPath。它使用 XPath 表达式来限制对 XML 集合的搜索结果。有关如何使用 XPath 的更多详细信息,请参阅我们的XPath 教程

回想一下我们之前用来获取书籍列表的以下 XPath 表达式。

doc("books.xml")/books/book

XPath 示例

我们将使用 books.xml 文件并对其应用 XQuery。

books.xml

<?xml version="1.0" encoding="UTF-8"?>
<books>
   
   <book category="JAVA">
      <title lang="en">Learn Java in 24 Hours</title>
      <author>Robert</author>
      <year>2005</year>
      <price>30.00</price>
   </book>
   
   <book category="DOTNET">
      <title lang="en">Learn .Net in 24 hours</title>
      <author>Peter</author>
      <year>2011</year>
      <price>40.50</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XQuery in 24 hours</title>
      <author>Robert</author>
      <author>Peter</author> 
      <year>2013</year>
      <price>50.00</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XPath in 24 hours</title>
      <author>Jay Ban</author>
      <year>2010</year>
      <price>16.50</price>
   </book>
   
</books>

我们在这里给出了三个版本的 XQuery 语句,它们都实现了相同目标:显示价格值大于 30 的书籍标题。

XQuery – 版本 1

(: read the entire xml document :)
let $books := doc("books.xml")

for $x in $books/books/book
where $x/price > 30
return $x/title

输出

<title lang="en">Learn .Net in 24 hours</title>
<title lang="en">Learn XQuery in 24 hours</title>

XQuery – 版本 2

(: read all books :)
let $books := doc("books.xml")/books/book

for $x in $books
where $x/price > 30
return $x/title

输出

<title lang="en">Learn .Net in 24 hours</title>
<title lang="en">Learn XQuery in 24 hours</title>

XQuery – 版本 3

(: read books with price > 30 :)
let $books := doc("books.xml")/books/book[price > 30]

for $x in $books
return $x/title

输出

<title lang="en">Learn .Net in 24 hours</title>
<title lang="en">Learn XQuery in 24 hours</title>

验证结果

要验证结果,请将books.xqy(在环境设置章节中给出)的内容替换为上述 XQuery 表达式,然后执行 XQueryTester java 程序。

XQuery - 序列

序列表示项目的排序集合,其中项目可以是相同类型或不同类型的。

创建序列

序列是使用括号创建的,括号内包含带引号或双引号的字符串以及数字。XML 元素也可以用作序列的项目。

XQuery 表达式

let $items := ('orange', <apple/>, <fruit type="juicy"/>, <vehicle type="car">sentro</vehicle>, 1,2,3,'a','b',"abc")
let $count := count($items)
return
<result>
   <count>{$count}</count>
   
   <items>
      {
	     for $item in $items
         return <item>{$item}</item>
      }
   </items>
   
</result>

输出

<result>
   <count>10</count>
   <items>
      <item>orange</item>
      <item>
         <apple/>
      </item>
      <item>
         <fruit type="juicy"/>
      </item>
      <item>
         <vehicle type="car">Sentro</vehicle>
      </item>
      <item>1</item>
      <item>2</item>
      <item>3</item>
      <item>a</item>
      <item>b</item>
      <item>abc</item>
   </items>
</result>

查看序列的项目

可以使用索引或值逐一迭代序列的项目。上面的示例逐一迭代序列的项目。让我们看看另外两种方法。

XQuery 表达式(索引)

let $items := (1,2,3,4,5,6)
let $count := count($items)
return
   <result>
      <count>{$count}</count>
      
      <items>
      {
         for $item in $items[2]
         return <item>{$item}</item>
      }
      </items>
      
   </result>

输出

<result>
   <count>6</count>
   <items>
      <item>2</item>
   </items>
</result>

XQuery 表达式(值)

let $items := (1,2,3,4,5,6)
let $count := count($items)
return
   <result>
      <count>{$count}</count>
      
      <items>
      {
         for $item in $items[. = (1,2,3)]
         return <item>{$item}</item>
      }
      </items>
      
   </result>

输出

<result>
   <count>6</count>
   <items>
      <item>1</item>
      <item>2</item>
      <item>3</item>
   </items>
</result>

XQuery - 序列函数

下表列出了 XQuery 提供的常用序列函数。

序号 名称和说明
1

count($seq as item()*)

计算序列中的项目数。

2

sum($seq as item()*)

返回序列中项目的总和。

3

avg($seq as item()*)

返回序列中项目的平均值。

4

min($seq as item()*)

返回序列中最小值的项目。

5

max($seq as item()*)

返回序列中最大值的项目。

6

distinct-values($seq as item()*)

从序列中返回选定的唯一项目。

7

subsequence($seq as item()*, $startingLoc as xs:double, $length as xs:double)

返回提供的序列的子集。

8

insert-before($seq as item()*, $position as xs:integer, $inserts as item()*)

在序列中插入项目。

9

remove($seq as item()*, $position as xs:integer)

从序列中删除项目。

10

reverse($seq as item()*)

返回反转的序列。

11

index-of($seq as anyAtomicType()*, $target as anyAtomicType())

返回作为整数的索引,以指示项目在序列中的可用性。

12

last()

在谓词表达式中使用时,返回序列的最后一个元素。

13

position()

在 FLOWR 表达式中用于获取序列中项目的 位置。

XQuery - 字符串函数

下表列出了 XQuery 提供的常用字符串操作函数。

序号 名称和说明
1

string-length($string as xs:string) as xs:integer

返回字符串的长度。

2

concat($input as xs:anyAtomicType?) as xs:string

返回连接后的字符串作为输出。

3

string-join($sequence as xs:string*, $delimiter as xs:string) as xs:string

返回序列中用分隔符分隔的项目的组合。

XQuery - 日期函数

下表列出了 XQuery 提供的常用日期函数。

序号 名称和说明
1

current-date()

返回当前日期。

2

current-time()

返回当前时间。

3

current-dateTime()

返回当前日期和当前时间。

XQuery - 正则表达式

以下是 XQuery 提供的常用正则表达式函数的列表

序号 名称和说明
1

matches($input, $regex)

如果输入与提供的正则表达式匹配,则返回 true。

2

replace($input, $regex, $string)

将匹配的输入字符串替换为给定的字符串。

3

tokenize($input, $regex)

返回与正则表达式匹配的项目序列。

XQuery - if then else

XQuery 提供了一个非常有用的 if-then-else 结构来检查传递的输入值的有效性。以下是 if-then-else 结构的语法。

语法

if (condition) then
 ... 
else
 ... 

示例

我们将使用以下 books.xml 文件并对其应用包含 if-then-else 结构的 XQuery 表达式,以检索价格值大于 30 的书籍的标题。

books.xml

<?xml version="1.0" encoding="UTF-8"?>
<books>
   <book category="JAVA">
      <title lang="en">Learn Java in 24 Hours</title>
      <author>Robert</author>
      <year>2005</year>
      <price>30.00</price>
   </book>
   
   <book category="DOTNET">
      <title lang="en">Learn .Net in 24 hours</title>
      <author>Peter</author>
      <year>2011</year>
      <price>40.50</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XQuery in 24 hours</title>
      <author>Robert</author>
      <author>Peter</author>
      <year>2013</year>
      <price>50.00</price>
   </book>
   
   <book category="XML">
      <title lang="en">Learn XPath in 24 hours</title>
      <author>Jay Ban</author>
      <year>2010</year>
      <price>16.50</price>
   </book>
</books>

以下 XQuery 表达式将应用于上述 XML 文档。

books.xqy

<result>
{
   if(not(doc("books.xml"))) then (
      <error>
         <message>books.xml does not exist</message>
      </error>
   )
   else ( 
      for $x in doc("books.xml")/books/book	
      where $x/price>30
      return $x/title
   )
}
</result>

输出

<result>
   <title lang="en">Learn .Net in 24 hours</title>
   <title lang="en">Learn XQuery in 24 hours</title>
</result>

验证结果

要验证结果,请将books.xqy(在环境设置章节中给出)的内容替换为上述 XQuery 表达式,然后执行 XQueryTester java 程序。

XQuery - 自定义函数

XQuery 提供了编写自定义函数的功能。以下是创建自定义函数的指南。

  • 使用关键字declare function来定义函数。

  • 使用当前XML Schema中定义的数据类型

  • 将函数体括在花括号内。

  • 在函数名前添加XML命名空间。

创建自定义函数时使用以下语法。

语法

declare function prefix:function_name($parameter as datatype?...)
as returnDatatype?
{
   function body...
};

示例

以下示例演示如何在XQuery中创建用户自定义函数。

XQuery 表达式

declare function local:discount($price as xs:decimal?,$percentDiscount as xs:decimal?)
as xs:decimal? {
   let $discount := $price - ($price * $percentDiscount div 100) 
   return $discount
};

let $originalPrice := 100

let $discountAvailed := 10

return ( local:discount($originalPrice, $discountAvailed)) 

输出

90

验证结果

要验证结果,请将books.xqy(在环境设置章节中给出)的内容替换为上述 XQuery 表达式,然后执行 XQueryTester java 程序。

广告