XQuery - 快速指南


XQuery - 概述

什么是 XQuery

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

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,并且针对性能进行了高度优化。无需任何 XML 数据库即可使用 Saxon XQuery 处理器。在示例中,我们将使用一个简单的 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 的书籍的标题元素。

书籍.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>

书本网

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 文档,其中包含书店各种书籍的记录。

书籍.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节点的标题元素。

书本网

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() 是用于定位 XML 源的 XQuery 函数之一。这里我们传递了“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 - 其中 - 选择条件指定的节点。

  • O - 排序依据 - 对根据条件指定的节点进行排序。

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

例子

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

书籍.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 文档上执行的查询表达式。

书本网

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 表,其中包含所有书籍的标题及其各自的价格。

书籍.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 表达式。

书本网

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。

书籍.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 元素也可以用作序列的项目。

X查询表达式

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

计数($seq 作为项目()*)

计算序列中的项目。

2

sum($seq as item()*)

返回序列中项目的总和。

3

平均值($seq 作为项目()*)

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

4

min($seq as item()*)

返回序列中最小值的项。

5

max($seq as item()*)

返回序列中的最大值。

6

不同值($seq as item()*)

返回从序列中选择的不同项目。

7

子序列($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

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

从序列中删除一个项目。

10

反向($seq as item()*)

返回相反的序列。

11

索引($seq 作为anyAtomicType()*,$target 作为anyAtomicType())

以整数形式返回索引,以指示序列中某个项目的可用性。

12

最后的()

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

13

位置()

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

XQuery - 字符串函数

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

先生编号 名称和描述
1

字符串长度($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

当前日期()

返回当前日期。

2

当前时间()

返回当前时间。

3

当前日期时间()

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

XQuery - 正则表达式

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

先生编号 名称和描述
1

匹配($输入,$正则表达式)

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

2

替换($输入,$正则表达式,$字符串)

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

3

标记化($输入,$正则表达式)

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

XQuery - 如果那么否则

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

句法

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

例子

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

书籍.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 文档。

书本网

<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 模式中定义的数据类型

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

  • 使用 XML 命名空间作为函数名称的前缀。

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

句法

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

例子

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

X查询表达式

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 程序。