XQuery 教程

XQuery 教程

XQuery 是 W3C 制定的 XML 查询语言,被称为"XML 的 SQL",用于从 XML 文档中查询、过滤、组合数据,是 XML 数据库与传统数据库集成的重要工具。

XQuery 能做什么

  • 查询 XML 文档中的数据
  • 从多个 XML 文档组合数据
  • 生成新的 XML/HTML/文本输出
  • 支持条件、循环、函数等编程特性
  • 作为 XSLT 的补充,更侧重数据查询

与 SQL / XSLT 对比

技术数据定位
SQL关系表关系数据库查询
XQueryXML 文档XML 数据查询
XSLTXML 文档XML 转换

简单示例

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

查询 books.xml 中价格大于 30 的所有书名。

学习路线

  1. 简介与实例
  2. FLWOR 表达式(核心)
  3. FLWOR + HTML 输出
  4. 术语、语法
  5. 添加元素、选择过滤、函数
  6. 总结与参考

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. 学习建议

  1. 先掌握 XPath 表达式
  2. 再用 FLWOR 组合查询
  3. 用 BaseX 动手实验
  4. 阅读 W3C 规范示例

XQuery 参考手册

XQuery 参考手册

1. 表达式速查

表达式示例
路径//book/title、/bookstore/book[1]
FLWORfor $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 节