简体中文 繁體中文 English 日本語 Deutsch 한국 사람 بالعربية TÜRKÇE português คนไทย Français

站内搜索

搜索

活动公告

11-02 12:46
10-23 09:32
通知:本站资源由网友上传分享,如有违规等问题请到版务模块进行投诉,将及时处理!
10-23 09:31
10-23 09:28
通知:签到时间调整为每日4:00(东八区)
10-23 09:26

XQuery高级功能学习指南掌握复杂查询与数据转换的专业技巧让您的XML数据处理能力更上一层楼成为团队中的技术专家

3万

主题

317

科技点

3万

积分

大区版主

木柜子打湿

积分
31893

财Doro三倍冰淇淋无人之境【一阶】立华奏小樱(小丑装)⑨的冰沙以外的星空【二阶】

发表于 2025-8-24 22:40:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
1. XQuery基础回顾

XQuery是一种用于查询XML数据的函数式编程语言,它允许我们从XML文档中提取和操作数据。在深入探讨高级功能之前,让我们简要回顾一些基础概念。

1.1 XQuery基本语法

XQuery使用FLWOR表达式(For, Let, Where, Order by, Return)作为其核心构造块。下面是一个简单的例子:
  1. for $book in collection("books")/books/book
  2. where $book/price > 30
  3. order by $book/title
  4. return $book/title
复制代码

这个查询从书籍集合中选择价格超过30的书籍,并按标题排序返回。

1.2 XPath与XQuery的关系

XQuery建立在XPath之上,XPath用于在XML文档中导航。XQuery扩展了XPath,添加了迭代、排序、构造等功能。
  1. (: 使用XPath选择节点 :)
  2. let $authors := doc("books.xml")/books/book/author
  3. return count($authors)
复制代码

2. XQuery高级查询技术

2.1 条件逻辑与分支处理

XQuery提供了丰富的条件表达式,包括if-then-else语句和typeswitch表达式。
  1. for $book in collection("books")/books/book
  2. return
  3.   if ($book/price > 50) then
  4.     <expensive>{$book/title/text()}</expensive>
  5.   else if ($book/price > 30) then
  6.     <moderate>{$book/title/text()}</moderate>
  7.   else
  8.     <affordable>{$book/title/text()}</affordable>
复制代码

typeswitch允许根据表达式的类型执行不同的代码块:
  1. let $item := (42, "hello", <element/>, attribute attr {"value"})[3]
  2. return
  3.   typeswitch($item)
  4.     case xs:integer return "Integer: " || string($item)
  5.     case xs:string return "String: " || $item
  6.     case element() return "Element: " || name($item)
  7.     case attribute() return "Attribute: " || name($item)
  8.     default return "Other type"
复制代码

2.2 量化表达式

XQuery提供了一些和量词相关的表达式,包括some和every。

some表达式检查序列中是否至少有一个项满足条件:
  1. (: 检查是否有书籍价格超过100 :)
  2. some $book in collection("books")/books/book satisfies $book/price > 100
复制代码

every表达式检查序列中是否所有项都满足条件:
  1. (: 检查是否所有书籍都有作者 :)
  2. every $book in collection("books")/books/book satisfies exists($book/author)
复制代码

2.3 序列操作与高级函数

XQuery提供了强大的序列操作功能,包括序列构造、过滤、映射等。
  1. (: 构造序列 :)
  2. let $sequence := (1 to 10, "a", "b", "c", <item>1</item>, <item>2</item>)
  3. (: 序列过滤 :)
  4. let $filtered := $sequence[self::item]
  5. (: 序列映射 :)
  6. let $mapped := for $item in $sequence return string($item)
  7. (: 序列聚合 :)
  8. let $count := count($sequence)
  9. let $sum := sum($sequence[. castable as xs:integer])
  10. let $concat := string-join($sequence[. instance of xs:string], "-")
  11. return (
  12.   <filtered>{$filtered}</filtered>,
  13.   <mapped>{$mapped}</mapped>,
  14.   <stats count="{$count}" sum="{$sum}" concat="{$concat}"/>
  15. )
复制代码

XQuery 3.0引入了函数项和高阶函数,使函数式编程更加灵活:
  1. (: 定义函数 :)
  2. declare function local:double($x as xs:integer) as xs:integer {
  3.   $x * 2
  4. };
  5. (: 函数作为参数 :)
  6. declare function local:apply($f as function(xs:integer) as xs:integer, $x as xs:integer) as xs:integer {
  7.   $f($x)
  8. };
  9. (: 使用函数项 :)
  10. let $double-fn := local:double#1
  11. let $numbers := (1 to 5)
  12. return (
  13.   <direct>{local:apply($double-fn, 10)}</direct>,
  14.   <mapped>{for $n in $numbers return $double-fn($n)}</mapped>
  15. )
复制代码

2.4 模块化与代码重用

XQuery支持模块化编程,允许将代码组织到可重用的模块中。
  1. (: 文件: library.xqm :)
  2. module namespace lib = "http://example.com/library";
  3. declare function lib:format-price($price as xs:decimal) as xs:string {
  4.   concat("$", format-number($price, "#,##0.00"))
  5. };
  6. declare function lib:book-summary($book as element(book)) as element(summary) {
  7.   <summary>
  8.     <title>{$book/title/text()}</title>
  9.     <author>{$book/author/text()}</author>
  10.     <price>{lib:format-price($book/price)}</price>
  11.   </summary>
  12. };
复制代码
  1. (: 导入模块 :)
  2. import module namespace lib = "http://example.com/library" at "library.xqm";
  3. (: 使用模块中的函数 :)
  4. for $book in collection("books")/books/book
  5. return lib:book-summary($book)
复制代码

3. XQuery数据转换功能

3.1 XML构造与转换

XQuery提供了强大的XML构造功能,可以创建新的XML结构或转换现有XML。
  1. (: 直接构造XML元素 :)
  2. let $book :=
  3.   <book category="fiction">
  4.     <title>Example Book</title>
  5.     <author>John Doe</author>
  6.     <price>29.99</price>
  7.   </book>
  8. return $book
复制代码
  1. (: 使用计算构造动态创建元素和属性 :)
  2. let $category := "fiction"
  3. let $title := "Dynamic Book"
  4. let $author := "Jane Smith"
  5. let $price := 34.99
  6. return
  7.   element book {
  8.     attribute category { $category },
  9.     element title { $title },
  10.     element author { $author },
  11.     element price { $price }
  12.   }
复制代码
  1. (: 将书籍列表转换为HTML表格 :)
  2. let $books := collection("books")/books/book
  3. return
  4.   <html>
  5.     <head>
  6.       <title>Book List</title>
  7.       <style>
  8.         table {{ border-collapse: collapse; width: 100%; }}
  9.         th, td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
  10.         th {{ background-color: #f2f2f2; }}
  11.       </style>
  12.     </head>
  13.     <body>
  14.       <h1>Book List</h1>
  15.       <table>
  16.         <tr>
  17.           <th>Title</th>
  18.           <th>Author</th>
  19.           <th>Price</th>
  20.         </tr>
  21.         {
  22.           for $book in $books
  23.           order by $book/title
  24.           return
  25.             <tr>
  26.               <td>{$book/title/text()}</td>
  27.               <td>{$book/author/text()}</td>
  28.               <td>{$book/price/text()}</td>
  29.             </tr>
  30.         }
  31.       </table>
  32.     </body>
  33.   </html>
复制代码

3.2 节点修改与更新

XQuery Update Facility提供了修改XML文档的功能。
  1. (: 在书籍中插入新的评论节点 :)
  2. let $book := doc("books.xml")/books/book[title = "Example Book"]
  3. return
  4.   insert node
  5.     <review>
  6.       <user>Alice</user>
  7.       <rating>4</rating>
  8.       <comment>Great book!</comment>
  9.     </review>
  10.   into $book
复制代码
  1. (: 更新书籍价格 :)
  2. let $book := doc("books.xml")/books/book[title = "Example Book"]
  3. return
  4.   replace node $book/price with <price currency="USD">24.99</price>
复制代码
  1. (: 删除书籍的评论节点 :)
  2. let $book := doc("books.xml")/books/book[title = "Example Book"]
  3. return
  4.   delete node $book/review
复制代码

3.3 JSON处理

现代XQuery实现(如BaseX、eXist-db)支持JSON处理,允许在XQuery中查询和转换JSON数据。
  1. (: 解析JSON字符串 :)
  2. let $json-string := '{"books": [{"title": "Book 1", "author": "Author 1"}, {"title": "Book 2", "author": "Author 2"}]}'
  3. let $json := parse-json($json-string)
  4. return $json
复制代码
  1. (: 将JSON转换为XML :)
  2. let $json-string := '{"title": "Example", "author": "John", "price": 29.99}'
  3. let $json := parse-json($json-string)
  4. return
  5.   <book>
  6.     <title>{$json("title")}</title>
  7.     <author>{$json("author")}</author>
  8.     <price>{$json("price")}</price>
  9.   </book>
复制代码
  1. (: 将XML转换为JSON :)
  2. let $xml :=
  3.   <book>
  4.     <title>Example</title>
  5.     <author>John</author>
  6.     <price>29.99</price>
  7.   </book>
  8. return
  9.   serialize(
  10.     {
  11.       "title": $xml/title/string(),
  12.       "author": $xml/author/string(),
  13.       "price": xs:decimal($xml/price)
  14.     },
  15.     {"method": "json"}
  16.   )
复制代码

4. 实际应用案例

4.1 复杂报表生成

假设我们有一个包含销售数据的XML文件,需要生成一个复杂的报表:
  1. <!-- sales.xml -->
  2. <sales>
  3.   <region id="north">
  4.     <product id="p1" name="Widget" category="gadgets">
  5.       <sale date="2023-01-01" quantity="10" price="19.99"/>
  6.       <sale date="2023-01-15" quantity="5" price="19.99"/>
  7.       <sale date="2023-02-01" quantity="8" price="18.99"/>
  8.     </product>
  9.     <product id="p2" name="Gadget" category="gadgets">
  10.       <sale date="2023-01-05" quantity="3" price="29.99"/>
  11.       <sale date="2023-01-20" quantity="7" price="29.99"/>
  12.     </product>
  13.   </region>
  14.   <region id="south">
  15.     <product id="p1" name="Widget" category="gadgets">
  16.       <sale date="2023-01-10" quantity="15" price="19.99"/>
  17.       <sale date="2023-02-05" quantity="12" price="18.99"/>
  18.     </product>
  19.     <product id="p3" name="Thingy" category="accessories">
  20.       <sale date="2023-01-12" quantity="20" price="9.99"/>
  21.       <sale date="2023-01-25" quantity="15" price="9.99"/>
  22.     </product>
  23.   </region>
  24. </sales>
复制代码

我们可以使用XQuery生成一个详细的销售报表:
  1. (: 生成销售报表 :)
  2. declare function local:format-date($date as xs:date) as xs:string {
  3.   format-date($date, "[MNn] [D], [Y]")
  4. };
  5. declare function local:region-report($region as element(region)) as element(region-report) {
  6.   let $region-id := $region/@id
  7.   let $products := $region/product
  8.   let $total-sales := sum($products/sale/(xs:decimal(@quantity) * xs:decimal(@price)))
  9.   let $total-quantity := sum($products/sale/xs:decimal(@quantity))
  10.   
  11.   return
  12.     <region-report id="{$region-id}">
  13.       <summary>
  14.         <total-sales>{$total-sales}</total-sales>
  15.         <total-quantity>{$total-quantity}</total-quantity>
  16.         <product-count>{count($products)}</product-count>
  17.       </summary>
  18.       <products>
  19.         {
  20.           for $product in $products
  21.           let $product-sales := sum($product/sale/(xs:decimal(@quantity) * xs:decimal(@price)))
  22.           let $product-quantity := sum($product/sale/xs:decimal(@quantity))
  23.           order by $product-sales descending
  24.           return
  25.             <product id="{$product/@id}" name="{$product/@name}" category="{$product/@category}">
  26.               <total-sales>{$product-sales}</total-sales>
  27.               <total-quantity>{$product-quantity}</total-quantity>
  28.               <sales>
  29.                 {
  30.                   for $sale in $product/sale
  31.                   order by $sale/@date
  32.                   return
  33.                     <sale date="{local:format-date(xs:date($sale/@date))}"
  34.                           quantity="{$sale/@quantity}"
  35.                           price="{$sale/@price}"
  36.                           total="{xs:decimal($sale/@quantity) * xs:decimal($sale/@price)}"/>
  37.                 }
  38.               </sales>
  39.             </product>
  40.         }
  41.       </products>
  42.     </region-report>
  43. };
  44. let $sales := doc("sales.xml")/sales
  45. let $regions := $sales/region
  46. let $grand-total := sum($regions/product/sale/(xs:decimal(@quantity) * xs:decimal(@price)))
  47. let $grand-quantity := sum($regions/product/sale/xs:decimal(@quantity))
  48. return
  49.   <sales-report>
  50.     <summary>
  51.       <grand-total>{$grand-total}</grand-total>
  52.       <grand-quantity>{$grand-quantity}</grand-quantity>
  53.       <region-count>{count($regions)}</region-count>
  54.     </summary>
  55.     <regions>
  56.       {
  57.         for $region in $regions
  58.         return local:region-report($region)
  59.       }
  60.     </regions>
  61.   </sales-report>
复制代码

4.2 数据集成与转换

假设我们有两个XML文件,包含客户信息和订单信息,需要将它们合并为一个统一的视图:
  1. <!-- customers.xml -->
  2. <customers>
  3.   <customer id="c1">
  4.     <name>John Smith</name>
  5.     <email>john@example.com</email>
  6.     <phone>555-1234</phone>
  7.   </customer>
  8.   <customer id="c2">
  9.     <name>Jane Doe</name>
  10.     <email>jane@example.com</email>
  11.     <phone>555-5678</phone>
  12.   </customer>
  13. </customers>
复制代码
  1. <!-- orders.xml -->
  2. <orders>
  3.   <order id="o1" customer-id="c1" date="2023-01-15">
  4.     <item product-id="p1" quantity="2" price="19.99"/>
  5.     <item product-id="p3" quantity="1" price="9.99"/>
  6.   </order>
  7.   <order id="o2" customer-id="c2" date="2023-01-20">
  8.     <item product-id="p2" quantity="1" price="29.99"/>
  9.   </order>
  10.   <order id="o3" customer-id="c1" date="2023-02-05">
  11.     <item product-id="p1" quantity="3" price="18.99"/>
  12.   </order>
  13. </orders>
复制代码

我们可以使用XQuery将这些数据合并:
  1. (: 合并客户和订单数据 :)
  2. let $customers := doc("customers.xml")/customers/customer
  3. let $orders := doc("orders.xml")/orders/order
  4. return
  5.   <customer-orders>
  6.     {
  7.       for $customer in $customers
  8.       let $customer-id := $customer/@id
  9.       let $customer-orders := $orders[@customer-id = $customer-id]
  10.       let $total-spent := sum($customer-orders/item/(xs:decimal(@quantity) * xs:decimal(@price)))
  11.       let $order-count := count($customer-orders)
  12.       
  13.       return
  14.         <customer id="{$customer-id}">
  15.           <name>{$customer/name/text()}</name>
  16.           <email>{$customer/email/text()}</email>
  17.           <phone>{$customer/phone/text()}</phone>
  18.           <order-summary>
  19.             <total-orders>{$order-count}</total-orders>
  20.             <total-spent>{$total-spent}</total-spent>
  21.           </order-summary>
  22.           <orders>
  23.             {
  24.               for $order in $customer-orders
  25.               let $order-total := sum($order/item/(xs:decimal(@quantity) * xs:decimal(@price)))
  26.               order by $order/@date
  27.               return
  28.                 <order id="{$order/@id}" date="{$order/@date}">
  29.                   <total>{$order-total}</total>
  30.                   <items>
  31.                     {
  32.                       for $item in $order/item
  33.                       return
  34.                         <item product-id="{$item/@product-id}"
  35.                               quantity="{$item/@quantity}"
  36.                               price="{$item/@price}"
  37.                               total="{xs:decimal($item/@quantity) * xs:decimal($item/@price)}"/>
  38.                     }
  39.                   </items>
  40.                 </order>
  41.             }
  42.           </orders>
  43.         </customer>
  44.     }
  45.   </customer-orders>
复制代码

4.3 高级文本处理

XQuery提供了强大的文本处理功能,可以用于复杂的文本分析任务:
  1. (: 分析文档中的词频 :)
  2. declare function local:tokenize-text($text as xs:string) as xs:string* {
  3.   let $normalized := lower-case(replace($text, "[^\p{L}\p{N}]+", " "))
  4.   return tokenize($normalized, "\s+")[. != ""]
  5. };
  6. declare function local:word-frequency($text as xs:string) as element(word)* {
  7.   let $tokens := local:tokenize-text($text)
  8.   let $distinct-words := distinct-values($tokens)
  9.   
  10.   return
  11.     for $word in $distinct-words
  12.     let $count := count($tokens[. = $word])
  13.     order by $count descending
  14.     return
  15.       <word count="{$count}">{$word}</word>
  16. };
  17. (: 假设我们有一个包含文章内容的XML文档 :)
  18. let $article := doc("article.xml")/article
  19. let $title := $article/title/string()
  20. let $content := $article/content/string()
  21. let $full-text := concat($title, " ", $content)
  22. return
  23.   <analysis>
  24.     <document>
  25.       <title>{$title}</title>
  26.       <word-count>{count(local:tokenize-text($full-text))}</word-count>
  27.     </document>
  28.     <top-words>
  29.       {subsequence(local:word-frequency($full-text), 1, 20)}
  30.     </top-words>
  31.   </analysis>
复制代码

5. 性能优化技巧

5.1 索引利用

在处理大型XML数据集时,合理利用索引可以显著提高查询性能。
  1. (: 在BaseX中创建索引 :)
  2. try {
  3.   db:create-index("books", "path")
  4. } catch * {
  5.   (: 索引可能已存在 :)
  6. }
  7. (: 使用索引优化的查询 :)
  8. for $book in collection("books")/books/book[author = "John Doe"]
  9. return $book/title
复制代码

5.2 查询优化技术
  1. (: 不优化的版本 - 在循环中重复计算 :)
  2. for $book in collection("books")/books/book
  3. let $price := xs:decimal($book/price)
  4. let $discounted-price := $price * 0.9
  5. where $price > 20
  6. return
  7.   <book>
  8.     <title>{$book/title/text()}</title>
  9.     <original-price>{$price}</original-price>
  10.     <discounted-price>{$discounted-price}</discounted-price>
  11.   </book>
  12. (: 优化版本 - 先过滤再计算 :)
  13. for $book in collection("books")/books/book[xs:decimal(price) > 20]
  14. let $price := xs:decimal($book/price)
  15. let $discounted-price := $price * 0.9
  16. return
  17.   <book>
  18.     <title>{$book/title/text()}</title>
  19.     <original-price>{$price}</original-price>
  20.     <discounted-price>{$discounted-price}</discounted-price>
  21.   </book>
复制代码
  1. (: 嵌套循环连接 - 可能效率较低 :)
  2. for $customer in doc("customers.xml")/customers/customer
  3. for $order in doc("orders.xml")/orders/order[@customer-id = $customer/@id]
  4. return
  5.   <customer-order>
  6.     <customer-name>{$customer/name/text()}</customer-name>
  7.     <order-id>{$order/@id}</order-id>
  8.   </customer-order>
  9. (: 使用键和索引的连接 - 通常更高效 :)
  10. let $orders := doc("orders.xml")/orders/order
  11. let $order-index :=
  12.   map:merge(
  13.     for $order in $orders
  14.     return map:entry($order/@customer-id, $order)
  15.   )
  16.   
  17. for $customer in doc("customers.xml")/customers/customer
  18. let $customer-id := $customer/@id
  19. let $customer-orders := $order-index($customer-id)
  20. where exists($customer-orders)
  21. return
  22.   <customer-order>
  23.     <customer-name>{$customer/name/text()}</customer-name>
  24.     <order-id>{$customer-orders/@id}</order-id>
  25.   </customer-order>
复制代码

5.3 内存管理
  1. (: 使用流式处理处理大型文档 - 避免将整个文档加载到内存 :)
  2. declare function local:process-large-document() {
  3.   for $record in collection("large-data")/records/record
  4.   let $processed := local:process-record($record)
  5.   where local:matches-criteria($processed)
  6.   return local:output-result($processed)
  7. };
  8. declare function local:process-record($record as element(record)) as element(processed-record) {
  9.   (: 处理记录的逻辑 :)
  10.   <processed-record id="{$record/@id}">
  11.     <data>{$record/data/text()}</data>
  12.     <timestamp>{current-dateTime()}</timestamp>
  13.   </processed-record>
  14. };
  15. declare function local:matches-criteria($record as element(processed-record)) as xs:boolean {
  16.   (: 匹配条件的逻辑 :)
  17.   xs:decimal($record/data) > 100
  18. };
  19. declare function local:output-result($record as element(processed-record)) as element(result) {
  20.   (: 输出结果的逻辑 :)
  21.   <result>{$record/@id, $record/timestamp}</result>
  22. };
  23. local:process-large-document()
复制代码

6. 最佳实践和注意事项

6.1 代码组织与可维护性

将复杂的XQuery代码分解为可重用的模块和函数:
  1. (: 文件: config.xqm :)
  2. module namespace config = "http://example.com/config";
  3. declare variable $config:db-path as xs:string := "/data/db";
  4. declare variable $config:default-language as xs:string := "en";
复制代码
  1. (: 文件: utils.xqm :)
  2. module namespace utils = "http://example.com/utils";
  3. declare function utils:format-date($date as xs:date, $lang as xs:string) as xs:string {
  4.   if ($lang = "fr") then
  5.     format-date($date, "[D]/[M]/[Y]", "fr", ())
  6.   else
  7.     format-date($date, "[M]/[D]/[Y]", "en", ())
  8. };
  9. declare function utils:validate-email($email as xs:string) as xs:boolean {
  10.   matches($email, "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$")
  11. };
复制代码
  1. (: 文件: main.xqm :)
  2. module namespace main = "http://example.com/main";
  3. import module namespace config = "http://example.com/config" at "config.xqm";
  4. import module namespace utils = "http://example.com/utils" at "utils.xqm";
  5. declare function main:process-users() {
  6.   for $user in collection(concat($config:db-path, "/users"))/users/user
  7.   let $email := $user/email/text()
  8.   where utils:validate-email($email)
  9.   return
  10.     <user id="{$user/@id}">
  11.       <name>{$user/name/text()}</name>
  12.       <email>{$email}</email>
  13.       <registration-date>{utils:format-date(xs:date($user/registration-date), $config:default-language)}</registration-date>
  14.     </user>
  15. };
复制代码

6.2 错误处理与调试
  1. (: 使用try-catch处理错误 :)
  2. declare function local:safe-divide($a as xs:double, $b as xs:double) as xs:double {
  3.   try {
  4.     $a div $b
  5.   } catch err:FOAR0001 {
  6.     (: 处理除以零的错误 :)
  7.     0
  8.   } catch * {
  9.     (: 处理其他错误 :)
  10.     fn:error(xs:QName("local:CALCULATION_ERROR"), "Calculation failed", $a, $b)
  11.   }
  12. };
  13. (: 使用错误处理进行安全查询 :)
  14. for $item in collection("items")/items/item
  15. let $price := xs:decimal($item/price)
  16. let $quantity := xs:decimal($item/quantity)
  17. let $total-value := local:safe-divide($price, $quantity)
  18. return
  19.   <item id="{$item/@id}">
  20.     <price>{$price}</price>
  21.     <quantity>{$quantity}</quantity>
  22.     <unit-value>{$total-value}</unit-value>
  23.   </item>
复制代码
  1. (: 使用trace函数调试 :)
  2. for $book in collection("books")/books/book
  3. let $price := trace(xs:decimal($book/price), "Price: ")
  4. let $discounted := $price * 0.9
  5. where trace($price > 20, "Expensive book: ")
  6. return
  7.   <book>
  8.     <title>{$book/title/text()}</title>
  9.     <price>{$price}</price>
  10.     <discounted-price>{$discounted}</discounted-price>
  11.   </book>
  12. (: 使用注释和日志记录 :)
  13. declare function local:process-data($data as element(data)) as element(result) {
  14.   (: 开始处理数据 :)
  15.   let $processed := local:transform-data($data)
  16.   (: 数据转换完成 :)
  17.   let $validated := local:validate-data($processed)
  18.   (: 数据验证完成 :)
  19.   return
  20.     if ($validated) then (
  21.       (: 数据有效,返回结果 :)
  22.       <result status="success">{$processed}</result>
  23.     ) else (
  24.       (: 数据无效,返回错误 :)
  25.       <result status="error">Invalid data</result>
  26.     )
  27. };
复制代码

6.3 安全考虑
  1. (: 不安全的方式 - 直接使用用户输入 :)
  2. let $user-input := request:parameter("category")
  3. let $query := concat("for $book in /books/book[category='", $user-input, "'] return $book")
  4. (: 这样容易受到注入攻击 :)
  5. (: 安全的方式 - 使用参数化查询 :)
  6. let $user-input := request:parameter("category")
  7. let $books :=
  8.   if (matches($user-input, "^[a-zA-Z0-9_-]+$")) then
  9.     collection("books")/books/book[category = $user-input]
  10.   else
  11.     error(xs:QName("local:INVALID_INPUT"), "Invalid category parameter")
  12. return $books
复制代码
  1. (: 实现基于角色的访问控制 :)
  2. declare function local:check-permission($resource as xs:string, $action as xs:string) as xs:boolean {
  3.   let $user := local:get-current-user()
  4.   let $role := local:get-user-role($user)
  5.   
  6.   return
  7.     if ($role = "admin") then
  8.       true()
  9.     else if ($role = "editor" and $action = ("read", "write")) then
  10.       true()
  11.     else if ($role = "reader" and $action = "read") then
  12.       true()
  13.     else
  14.       false()
  15. };
  16. declare function local:get-document($doc-path as xs:string) as document-node()? {
  17.   if (local:check-permission($doc-path, "read")) then
  18.     doc($doc-path)
  19.   else
  20.     error(xs:QName("local:ACCESS_DENIED"), "Access denied to document: " || $doc-path)
  21. };
  22. (: 使用访问控制函数 :)
  23. let $document := local:get-document("/private/reports.xml")
  24. return $document/reports
复制代码

结论

XQuery是一种功能强大的查询和转换语言,特别适合处理XML数据。通过掌握本文介绍的高级功能,包括复杂查询技术、数据转换功能、实际应用案例、性能优化技巧以及最佳实践,您可以显著提高XML数据处理能力,成为团队中的技术专家。

要真正掌握XQuery,需要不断实践和探索。尝试将这些技术应用到实际项目中,解决复杂的数据处理问题,并持续关注XQuery生态系统的发展和新的功能特性。

随着XML数据在企业应用中的广泛使用,以及XQuery在处理JSON和其他数据格式方面的能力不断增强,精通XQuery将成为您职业生涯中的宝贵技能。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

频道订阅

频道订阅

加入社群

加入社群

联系我们|TG频道|RSS

Powered by Pixtech

© 2025 Pixtech Team.