XQuery 教程
XQuery 教程
XQuery 是 W3C 制定的 XML 查询语言,被称为"XML 的 SQL",用于从 XML 文档中查询、过滤、组合数据,是 XML 数据库与传统数据库集成的重要工具。
XQuery 能做什么
- 查询 XML 文档中的数据
- 从多个 XML 文档组合数据
- 生成新的 XML/HTML/文本输出
- 支持条件、循环、函数等编程特性
- 作为 XSLT 的补充,更侧重数据查询
与 SQL / XSLT 对比
| 技术 | 数据 | 定位 |
|---|---|---|
| SQL | 关系表 | 关系数据库查询 |
| XQuery | XML 文档 | XML 数据查询 |
| XSLT | XML 文档 | XML 转换 |
简单示例
for $b in doc("books.xml")/bookstore/book
where $b/price > 30
return $b/title
查询 books.xml 中价格大于 30 的所有书名。
学习路线
- 简介与实例
- FLWOR 表达式(核心)
- FLWOR + HTML 输出
- 术语、语法
- 添加元素、选择过滤、函数
- 总结与参考
XQuery 简介
XQuery 简介
1. 什么是 XQuery
XQuery 于 2007 年成为 W3C 推荐标准,用于查询 XML 数据。它是函数式语言,主要基于 XPath 表达式,并扩展了 FLWOR 等高级特性。
2. 应用场景
- XML 数据库查询(eXist、BaseX)
- 企业数据集成(不同 XML 数据源)
- Web 服务数据处理
- 内容管理系统检索
- 电子出版(结构化文档)
3. 执行环境
# BaseX(开源,推荐入门) # https://basex.org basex books.xq # eXist-db # 基于 HTTP 的 XML 数据库 # Saxon(Java) # 命令行 saxon query # 在线测试 # https://try.zorba.io
4. 与 XPath 关系
# XPath 是 XQuery 的子集 # XPath 表达式在 XQuery 中直接可用 # XPath //book/title # XQuery for $b in //book return $b/title # XPath 适合简单定位 # XQuery 适合复杂查询与数据组合
5. 第一个查询
# books.xml
<bookstore>
<book>
<title>XML 入门</title>
<price>39.9</price>
</book>
<book>
<title>XQuery 精通</title>
<price>59.9</price>
</book>
</bookstore>
# 查询所有书名
doc("books.xml")//book/title
# 输出:
# <title>XML 入门</title>
# <title>XQuery 精通</title>
XQuery 实例
XQuery 实例
1. 准备数据
# books.xml
<?xml version="1.0"?>
<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">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>
2. 基础查询
# 选择所有书名
doc("books.xml")/bookstore/book/title
# 选择价格大于 30 的书
doc("books.xml")/bookstore/book[price > 30]
# 选择书名
doc("books.xml")//title
# 条件过滤
doc("books.xml")//book[@category="WEB"]
3. FLWOR 查询
# 查询价格大于 30 的书名(排序)
for $x in doc("books.xml")/bookstore/book
where $x/price > 30
order by $x/title
return $x/title
4. 输出 HTML
# 生成 HTML 列表
<ul>
{
for $x in doc("books.xml")//book
order by $x/title
return <li>{data($x/title)} - {data($x/price)}</li>
}
</ul>
XQuery FLWOR 表达式
XQuery FLWOR 表达式
FLWOR 是 XQuery 的核心查询表达式,名字由五个子句的首字母组成,类似 SQL 的 SELECT-FROM-WHERE。
1. FLWOR 结构
FLWOR: F - for: 迭代绑定变量(类似 foreach) L - let: 变量赋值(类似 let) W - where: 过滤条件(类似 WHERE) O - order: 排序(类似 ORDER BY) R - return: 返回结果(类似 SELECT) for $x in 数据源 let $y := 表达式 where 条件 order by 字段 return 结果
2. for 子句
# for:遍历集合,每次绑定一个值
for $b in doc("books.xml")//book
return $b/title
# 多个 for(嵌套循环)
for $a in (1, 2, 3)
for $b in ("x", "y")
return $a || $b
# 1x 1y 2x 2y 3x 3y
# at 获取索引
for $b at $i in //book
return <item>{$i}. {data($b/title)}</item>
3. let 子句
# let:绑定表达式结果(不迭代)
let $books := doc("books.xml")//book
return count($books)
# let 与 for 组合
let $books := doc("books.xml")//book
for $b in $books
where $b/price > 30
return $b/title
4. where 子句
# 过滤条件 where $b/price > 30 where $b/@category = "WEB" where $b/year > 2000 and $b/price < 40 where contains($b/title, "XML") # 比较运算 = != < <= > >= and or not()
5. order by 与 return
# 排序
order by $b/price # 升序
order by $b/price descending # 降序
order by $b/price, $b/title # 多字段
# return:最终结果
return $b/title
return <book-name>{data($b/title)}</book-name>
return concat($b/title, ": ", $b/price)
XQuery FLWOR + HTML
XQuery FLWOR + HTML
XQuery 可以直接生成 HTML,把 XML 数据渲染为网页,类似 XSLT 但语法更接近编程语言。
1. 生成 HTML 表格
xquery version "3.0";
let $books := doc("books.xml")//book
return
<html>
<body>
<h2>图书列表</h2>
<table border="1">
<tr>
<th>书名</th>
<th>作者</th>
<th>价格</th>
</tr>
{
for $b in $books
order by $b/price descending
return
<tr>
<td>{data($b/title)}</td>
<td>{data($b/author)}</td>
<td>{data($b/price)}</td>
</tr>
}
</table>
</body>
</html>
2. 条件样式
for $b in //book
return
<li style="{ if ($b/price > 35)
then 'color:red'
else 'color:green' }">
{data($b/title)} - {data($b/price)}
</li>
3. 分组统计
# 按年份分组
let $books := //book
for $year in distinct-values($books/year)
let $group := $books[year = $year]
order by $year
return
<div>
<h3>{data($year)} 年({count($group)} 本)</h3>
<ul>
{ for $b in $group
return <li>{data($b/title)}</li> }
</ul>
</div>
4. 完整页面输出
# BaseX 中输出为 HTML # 设置输出格式 declare option output:method "html"; declare option output:encoding "UTF-8"; # 或命令行 basex -o output.html books.xq
XQuery 术语
XQuery 术语
1. 节点类型
# XQuery 处理的七种节点
document-node 文档节点(根)
element 元素节点
attribute 属性节点
text 文本节点
comment 注释节点
processing-instruction 处理指令
namespace 命名空间节点
# 示例
doc("books.xml")/bookstore # 元素
doc("books.xml")/bookstore/@category # 属性
doc("books.xml")//title/text() # 文本
2. 原子值
# 原子值:单一值,无子节点 "hello" 字符串 42 整数 3.14 小数 true() / false() 布尔 2026-08-18 日期 # 类型 xs:string xs:integer xs:decimal xs:boolean xs:date xs:dateTime
3. 序列(Sequence)
# 序列:XQuery 的一切都是序列
(1, 2, 3) # 数字序列
("a", "b") # 字符串序列
(//book, //author) # 节点序列
() # 空序列
(1, 2, 3)[2] # 第二项:2
# 序列操作
count((1,2,3)) # 3
reverse((1,2,3)) # 3,2,1
distinct-values((1,1,2)) # 1,2
(1,2) | (2,3) # 并集(节点用)
first/last 用 [1] / [last()]
4. 项目(Item)
# 序列中的单个元素 # 原子值或节点都是 item (1, <a/>, "x") # 三个 item 的序列 # item 操作 (1,2,3)[. = 2] # 过滤 for $i in (1,2,3) # 迭代
5. 路径表达式
# 绝对路径
doc("books.xml")/bookstore/book
# 相对路径
//book/title
# 轴
child:: 子元素
parent:: 父节点
descendant:: 后代
ancestor:: 祖先
attribute:: 属性
self:: 自身
# 简写
/ // . .. @
XQuery 语法
XQuery 语法
1. 大小写敏感
# XQuery 区分大小写 book 和 Book 不同 # 保留字小写 for let where order return and or not div mod # 变量名 $ 开头 $x $books $price
2. 字符串与转义
# 字符串用单引号或双引号
"hello" 'hello'
# 转义
"他叫"小明"" # 双引号内转义双引号
'don''t' # 单引号内两个单引号
# 字符串操作
concat("a", "b") # ab
string-length("abc") # 3
substring("hello", 2, 3) # ell
upper-case("abc") # ABC
lower-case("ABC") # abc
contains("hello", "ll") # true
starts-with("hello", "h") # true
ends-with("hello", "o") # true
3. 注释
# 注释写法 (: 这是注释 :) (: 多行 注释 :) for $b in //book (: 行尾注释 :)
4. 条件表达式
# if-then-else(必须,无 elseif) if ($price > 30) then "贵" else "便宜" # 嵌套 if ($x > 0) then if ($x > 100) then "大" else "中" else "非正数"
5. 运算符
# 算术 + - * div mod # 注意:整数除法用 div,不是 / 10 div 3 # 3 10 mod 3 # 1 3.5 * 2 # 7 # 比较 = != < <= > >= eq ne lt le gt ge(值比较) is(节点同一性) # 逻辑 and or not() # 序列连接 (1,2) , (3,4) # 1,2,3,4 # 并集 //book | //author
XQuery 添加元素和属性
XQuery 添加元素和属性
1. 构造元素
# 直接构造
<book>内容</book>
# 带内容表达式
<book>{ $title }</book>
# 动态元素名
element { $name } { $content }
# 输出到属性值
<book id="{ $id }">{ $title }</book>
# 属性简写
<book id="b1" category="WEB">...</book>
# 动态属性
attribute { $attrName } { $attrValue }
2. 构造示例
xquery version "3.0";
let $books := doc("books.xml")//book
return
<catalog>
{
for $b in $books
return
<book category="{ data($b/@category) }"
id="{ $b/title }">
<title>{ data($b/title) }</title>
<price currency="USD">
{ data($b/price) }
</price>
</book>
}
</catalog>
3. 添加/包装数据
# 包装节点
for $b in //book
return <item>{ $b }</item>
# 添加计算属性
for $b in //book
return
<book new-flag="true">{ $b/* }</book>
# 文本节点处理
text { $b }
4. 转换(类似 XSLT)
# 创建新文档结构
declare function local:transform($b) {
<product>
<name>{ data($b/title) }</name>
<cost>{ data($b/price) }</cost>
</product>
};
for $b in //book
return local:transform($b)
XQuery 选择和过滤
XQuery 选择和过滤
1. 谓词过滤
# 方括号 = 过滤条件 //book[price > 30] //book[@category="WEB"] //book[title="Learning XML"] # 位置过滤 //book[1] # 第一个 //book[last()] # 最后一个 //book[position() <= 2] # 前两个 //book[position() = last() - 1] # 倒数第二
2. 逻辑组合
//book[price > 30 and year > 2000] //book[price > 30 or @category="WEB"] //book[not(year)] //book[not(price = 29.99)] # 比较运算 //book[price > 30] //book[price != 30] # 值比较 //book[price eq 30] //book[title eq "Harry Potter"]
3. 字符串过滤
# 模糊匹配 //book[contains(title, "XML")] //book[starts-with(title, "Learn")] //book[ends-with(title, "Potter")] # 正则匹配 //book[matches(title, "^[A-Z]")] //book[matches(title, "\bXML\b")] # 大小写 //book[lower-case(title) = "learning xml"]
4. 选择输出字段
# 选择部分子元素 for $b in //book return $b/(title, author) # 选择属性 //book/@category # 去重 distinct-values(//book/@category)
5. 聚合与统计
count(//book) # 数量
sum(//book/price) # 总和
avg(//book/price) # 平均
min(//book/price) # 最小
max(//book/price) # 最大
# 使用函数
let $prices := //book/price
return
<stat>
<total>{ sum($prices) }</total>
<avg>{ round(avg($prices), 2) }</avg>
<count>{ count($prices) }</count>
</stat>
XQuery 函数
XQuery 函数
1. 内置函数
# 字符串 concat() string-length() substring() upper-case() lower-case() contains() starts-with() ends-with() replace() # 数值 count() sum() avg() min() max() round() floor() ceiling() abs() # 序列 distinct-values() reverse() subsequence() index-of() insert-before() remove() # 日期 current-date() current-time() year-from-date() format-date() # 节点 name() local-name() data() string() root() document-uri()
2. 自定义函数
xquery version "3.0";
(: 声明命名空间 :)
declare namespace my = "http://example.com/functions";
(: 定义函数 :)
declare function my:book-price($b) {
xs:decimal($b/price)
};
declare function my:expensive($b, $threshold) as xs:boolean {
my:book-price($b) > $threshold
};
(: 使用 :)
for $b in doc("books.xml")//book
where my:expensive($b, 35)
return
<book>{ data($b/title) }: { my:book-price($b) }</book>
3. 递归函数
declare function local:count-children($node) {
if (count($node/*) = 0) then 0
else count($node/*) +
sum(for $c in $node/* return local:count-children($c))
};
# 计算所有子节点数
local:count-children(doc("books.xml"))
4. 高阶函数
# XQuery 3.0 支持函数作为参数
let $add := function($a, $b) { $a + $b }
return $add(2, 3) # 5
# map 操作
for-each((1,2,3), function($x) { $x * 2 })
# 2, 4, 6
filter((1,2,3,4), function($x) { $x mod 2 = 0 })
# 2, 4
5. 错误处理
# 抛出错误
if (not(doc("books.xml"))) then
error(xs:QName("local:notFound"), "文件不存在")
else
doc("books.xml")//book
XQuery 总结
XQuery 总结
1. 核心要点
- 定位:XML 数据的查询语言,类似 SQL 之于关系库
- FLWOR:for/let/where/order/return 核心表达式
- XPath 基础:路径表达式是 XQuery 的基石
- 函数式:一切都是表达式,函数无副作用
- 序列:一切数据都是序列,操作统一
2. 适用场景
- XML 数据库查询(eXist/BaseX)
- 企业数据集成与转换
- XML → HTML 报表生成
- SOAP/Web 服务数据处理
3. 与 XSLT 选择
# XQuery 更合适 - 数据查询与聚合 - 类似 SQL 的过滤统计 - 生成 JSON/HTML 数据 # XSLT 更合适 - XML 到 XML 的复杂转换 - 模板驱动的文档处理 - 大量样式规则 # 现代替代 - XML 数据库已较少(JSON 崛起) - JSONiq / JSONPath 处理 JSON - 数据库 JSON 函数(MySQL/PostgreSQL)
4. 学习建议
- 先掌握 XPath 表达式
- 再用 FLWOR 组合查询
- 用 BaseX 动手实验
- 阅读 W3C 规范示例
XQuery 参考手册
XQuery 参考手册
1. 表达式速查
| 表达式 | 示例 |
|---|---|
| 路径 | //book/title、/bookstore/book[1] |
| FLWOR | for $x in ... where ... return ... |
| 条件 | if (...) then ... else ... |
| 序列 | (1,2,3)、//book、() |
| 构造 | <elem>{...}</elem> |
| 量化 | some/ every $x in ... satisfies ... |
| 开关 | switch($x) case ... return ... |
| 类型 | instance of、cast as |
2. 常用函数速查
# 字符串 concat(a,b) string-length(s) substring(s,start,len) upper-case lower-case contains starts-with ends-with replace(s,pattern,repl) normalize-space tokenize(s,sep) string-join(seq,sep) # 数值 count sum avg min max round floor ceiling abs # 节点 data(n) string(n) name(n) local-name(n) root(n) position() last() # 序列 distinct-values reverse subsequence index-of insert-before remove sort # 日期时间 current-date current-time current-dateTime year-from-date month-from-date day-from-date format-date
3. 运算符速查
# 算术 + - * div mod # 值比较 eq ne lt le gt ge # 一般比较 = != < <= > >= # 节点比较 is(同一节点) # 逻辑 and or not() # 序列 , (连接) | (并集)
4. 数据类型
xs:string xs:integer xs:decimal xs:double
xs:boolean xs:date xs:time xs:dateTime
xs:QName xs:anyURI
# 转换
xs:integer("42") # 字符串转数字
xs:string(42) # 数字转字符串
xs:date("2026-08-18")
5. 执行工具
BaseX basex.org(开源,推荐) eXist-db exist-db.org(XML 数据库) Saxon saxonica.com(Java/.NET) Zorba zorba.io(在线测试) Altova XMLSpy 商业 IDE
第 1 / 12 节