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 |
计算序列中的项目。 |
| 2 |
返回序列中项目的总和。 |
| 3 |
返回序列中项目的平均值。 |
| 4 |
返回序列中最小值的项。 |
| 5 |
返回序列中的最大值。 |
| 6 |
返回从序列中选择的不同项目。 |
| 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 |
返回相反的序列。 |
| 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 提供的常用日期函数。
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 程序。