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 |
計算序列中的專案數。 |
| 2 |
返回序列中專案的總和。 |
| 3 |
返回序列中專案的平均值。 |
| 4 |
返回序列中最小值的專案。 |
| 5 |
返回序列中最大值的專案。 |
| 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 |
返回反轉的序列。 |
| 11 | index-of($seq as anyAtomicType()*, $target as anyAtomicType()) 返回作為整數的索引,以指示專案在序列中的可用性。 |
| 12 |
在謂詞表達式中使用時,返回序列的最後一個元素。 |
| 13 |
在 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 |
返回當前日期。 |
| 2 |
返回當前時間。 |
| 3 |
返回當前日期和當前時間。 |
XQuery - 正則表示式
以下是 XQuery 提供的常用正則表示式函式的列表
| 序號 | 名稱和說明 |
|---|---|
| 1 |
如果輸入與提供的正則表示式匹配,則返回 true。 |
| 2 | replace($input, $regex, $string) 將匹配的輸入字串替換為給定的字串。 |
| 3 |
返回與正則表示式匹配的專案序列。 |
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 程式。