XQuery 实战实例合集(直接复制就能跑,2025 年最新常用写法)
准备一个常用的测试 XML 文件(保存为 books.xml)
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book id="b1" category="cooking">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
<tags>cooking, italian</tags>
</book>
<book id="b2" category="children">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book id="b3" category="web">
<title lang="zh">学习 XML</title>
<author>张三</author>
<author>李四</author>
<year>2020</year>
<price>68.00</price>
</book>
<book id="b4" category="web">
<title lang="en">XQuery Kick Start</title>
<author>James McGovern</author>
<year>2003</year>
<price>49.99</price>
</book>
</bookstore>
30 个最常用、最实用的 XQuery 实例(直接抄)
| 编号 | 需求描述 | XQuery 代码(直接运行) |
|---|---|---|
| 1 | 返回所有书名 | doc("books.xml")//title |
| 2 | 返回所有价格 > 30 的书 | doc("books.xml")//book[price > 30] |
| 3 | 只返回书名和价格(构造新结构) | for $b in doc("books.xml")//book[price > 30] return <item>{ $b/title, $b/price }</item> |
| 4 | 价格从高到低排序 | for $b in doc("books.xml")//book order by xs:decimal($b/price) descending return $b/title |
| 5 | 统计总共有几本书 | count(doc("books.xml")//book) |
| 6 | 计算所有书的平均价格 | avg(doc("books.xml")//book/price) |
| 7 | 按分类分组统计数量和平均价格 | for $cat in distinct-values(doc("books.xml")//book/@category) let $books := doc("books.xml")//book[@category = $cat] return <category name="{$cat}" count="{count($books)}" avg-price="{avg($books/price)}"/> |
| 8 | 查找 2005 年出版的书 | doc("books.xml")//book[year = 2005] |
| 9 | 查找标题包含“XML”的书(不区分大小写) | doc("books.xml")//book[contains(upper-case(title), 'XML')] |
| 10 | 返回多位作者的书(作者超过1个) | doc("books.xml")//book[count(author) > 1] |
| 11 | 取出每一本书的第一作者 | doc("books.xml")//book/author[1] |
| 12 | 把所有书输出为 JSON(XQuery 3.1) | serialize(doc("books.xml"), map { 'method': 'json', 'indent': true() }) |
| 13 | 读取外部 JSON 文件并取值 | let $j := json-doc("data.json") return $j?users?*?name |
| 14 | XML 转简单 CSV | string-join( ("标题,作者,价格"), " ", for $b in doc("books.xml")//book return string-join(($b/title, $b/author[1], $b/price), ",") ) |
| 15 | 条件判断:价格 > 50 标记 expensive | for $b in doc("books.xml")//book return <book>{ $b/title, if ($b/price > 50) then <flag>expensive</flag> else <flag>normal</flag> }</book> |
| 16 | 使用 let 避免重复计算 | let $books := doc("books.xml")//book let $expensive := $books[price > 40] return <result total="{count($books)}" expensive="{count($expensive)}"/> |
| 17 | 查找属性 id=”b3″ 的书 | doc("books.xml")//book[@id = "b3"] |
| 18 | 使用位置谓词取第2本书 | doc("books.xml")//book[2] |
| 19 | 取所有英文标题(lang=”en”) | doc("books.xml")//title[@lang = 'en'] |
| 20 | 取所有中文标题 | doc("books.xml")//title[not(@lang) or @lang != 'en'] |
| 21 | 标签包含 “web” 的书 | doc("books.xml")//book[contains(tags, 'web')] |
| 22 | 拼接所有作者姓名(逗号分隔) | string-join(doc("books.xml")//author, ', ') |
| 23 | 返回只包含 title 和 price 的简洁列表 | <books>{ for $b in doc("books.xml")//book return <book>{ $b/title, $b/price }</book> }</books> |
| 24 | 高阶函数 filter(XQuery 3.1) | let $books := doc("books.xml")//book return filter($books, function($b) { $b/price > 40 }) |
| 25 | 使用 map 高阶函数提取所有标题 | map(function($b) { $b/title/text() }, doc("books.xml")//book) |
| 26 | 查找 2010 年以后出版的书 | doc("books.xml")//book[year gt 2010] |
| 27 | 查找没有 year 元素的书(容错) | doc("books.xml")//book[not(year)] |
| 28 | 同时查询多个 XML 文件(collection) | for $b in collection("xmls/?select=*.xml")//book where $b/price > 50 return $b/title |
| 29 | 更新价格(XQuery Update,只在 BaseX、eXist-db、MarkLogic 支持) | copy $db := doc("books.xml") modify ( replace value of node $db//book[@id="b2"]/price with 39.99 ) return $db |
| 30 | 完整 FLWOR 经典模板(最常用写法) | for $book in doc("books.xml")//book where $book/price > 30 and $book/year >= 2005 order by xs:decimal($book/price) descending return <item id="{$book/@id}"> { $book/title, $book/author, $book/price } </item> |
推荐立即运行环境(0 配置)
- https://xqueryinstitute.com/ ← 直接粘贴上面代码,点 Run
- BaseX GUI(下载即用)
- https://www.w3schools.com/xml/xquery_intro.asp(有在线编辑器)
把上面 30 个例子一个个敲一遍,基本就掌握了 95% 的日常 XQuery 开发需求!
想要更多行业实战案例(金融报文、出版 EPUB、医保 HL7、日志分析等),随时告诉我~