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

站内搜索

搜索

活动公告

通知:本站资源由网友上传分享,如有违规等问题请到版务模块进行投诉,将及时处理!
10-23 09:31

掌握XQuery轻松实现XML数据高效查询与处理从基础语法到实际应用全面解析XML数据查询技巧

SunJu_FaceMall

3万

主题

417

科技点

3万

积分

大区版主

碾压王

积分
32159

立华奏

发表于 2025-10-6 00:10:22 | 显示全部楼层 |阅读模式 [标记阅至此楼]

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

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

x
引言

XQuery是一种用于查询XML数据的函数式编程语言,它被设计用来从XML文档中提取和处理信息。作为W3C推荐的标准,XQuery提供了强大的功能来搜索、检索和操作XML数据。在当今数据驱动的世界中,XML作为一种通用的数据交换格式,被广泛应用于Web服务、配置文件、文档存储等领域。掌握XQuery不仅能提高开发效率,还能更有效地处理和分析XML数据。

本文将从XQuery的基础语法开始,逐步深入到高级查询技巧和实际应用,帮助读者全面掌握XQuery,实现XML数据的高效查询与处理。

XQuery基础语法

XQuery简介

XQuery(XML Query)是一种用于从XML文档中提取数据的查询语言,类似于SQL对于关系型数据库的作用。XQuery使用XPath表达式来导航XML文档,并提供了丰富的功能来处理和转换XML数据。

基本语法结构

一个基本的XQuery查询由以下部分组成:
  1. xquery version "1.0";
  2. (: 这是一个XQuery注释 :)
  3. (: 简单的XQuery查询示例 :)
  4. for $book in doc("books.xml")/books/book
  5. where $book/price > 30
  6. return $book/title
复制代码

上面的示例中:

• xquery version "1.0";声明了XQuery的版本
• (: ... :)是XQuery的注释语法
• for子句用于迭代XML节点
• where子句用于过滤结果
• return子句指定要返回的内容

FLWOR表达式

FLWOR(For, Let, Where, Order by, Return)是XQuery中最重要的表达式,类似于SQL中的SELECT-FROM-WHERE结构。下面详细介绍FLWOR的各个部分:

for子句用于绑定变量到序列中的每个项,实现迭代功能:
  1. (: 迭代所有书籍 :)
  2. for $book in doc("books.xml")/books/book
  3. return $book/title
  4. (: 多个for子句实现嵌套循环 :)
  5. for $book in doc("books.xml")/books/book
  6. for $author in $book/authors/author
  7. return <author>{$author/text()}</author>
复制代码

let子句用于将变量绑定到一个值,该值可以是序列或单个节点:
  1. (: 使用let计算平均值 :)
  2. let $books := doc("books.xml")/books/book
  3. let $avgPrice := avg($books/price)
  4. return <average_price>{$avgPrice}</average_price>
复制代码

where子句用于过滤结果,只保留满足条件的项:
  1. (: 查找价格大于30的书籍 :)
  2. for $book in doc("books.xml")/books/book
  3. where $book/price > 30
  4. return $book/title
  5. (: 多条件过滤 :)
  6. for $book in doc("books.xml")/books/book
  7. where $book/price > 30 and $book/category = "Technology"
  8. return $book/title
复制代码

order by子句用于对结果进行排序:
  1. (: 按价格升序排序书籍 :)
  2. for $book in doc("books.xml")/books/book
  3. order by $book/price ascending
  4. return $book/title
  5. (: 多字段排序 :)
  6. for $book in doc("books.xml")/books/book
  7. order by $book/category ascending, $book/price descending
  8. return $book/title
复制代码

return子句指定要返回的内容,可以构造新的XML节点:
  1. (: 构造新的XML结构 :)
  2. for $book in doc("books.xml")/books/book
  3. where $book/price > 30
  4. return
  5.   <expensive_book>
  6.     {$book/title}
  7.     <price>{$book/price}</price>
  8.   </expensive_book>
复制代码

XPath表达式

XQuery使用XPath表达式来导航XML文档。XPath提供了一种在XML文档中查找节点的语言。以下是一些常用的XPath表达式:
  1. (: 选择所有书籍标题 :)
  2. doc("books.xml")/books/book/title
  3. (: 选择第一个书籍的标题 :)
  4. doc("books.xml")/books/book[1]/title
  5. (: 选择价格大于30的书籍 :)
  6. doc("books.xml")/books/book[price > 30]
  7. (: 选择所有类别为"Technology"的书籍的作者 :)
  8. doc("books.xml")/books/book[category = "Technology"]/authors/author
复制代码

条件表达式

XQuery支持条件表达式,类似于其他编程语言中的if-then-else结构:
  1. (: 简单的条件表达式 :)
  2. for $book in doc("books.xml")/books/book
  3. return
  4.   if ($book/price > 30) then
  5.     <expensive>{$book/title}</expensive>
  6.   else
  7.     <affordable>{$book/title}</affordable>
  8. (: 嵌套条件表达式 :)
  9. for $book in doc("books.xml")/books/book
  10. return
  11.   if ($book/price > 50) then
  12.     <very_expensive>{$book/title}</very_expensive>
  13.   else if ($book/price > 30) then
  14.     <expensive>{$book/title}</expensive>
  15.   else
  16.     <affordable>{$book/title}</affordable>
复制代码

量词表达式

量词表达式用于检查序列中的项是否满足某个条件:
  1. (: some量词 - 至少一个满足条件 :)
  2. some $book in doc("books.xml")/books/book satisfies $book/price > 50
  3. (: every量词 - 所有都满足条件 :)
  4. every $book in doc("books.xml")/books/book satisfies $book/price > 0
复制代码

序列操作

XQuery提供了丰富的序列操作功能:
  1. (: 序列构造 :)
  2. let $numbers := (1, 2, 3, 4, 5)
  3. return $numbers
  4. (: 序列过滤 :)
  5. let $numbers := (1, 2, 3, 4, 5)
  6. return $numbers[. > 3]
  7. (: 序列聚合函数 :)
  8. let $numbers := (1, 2, 3, 4, 5)
  9. return
  10.   <stats>
  11.     <count>{count($numbers)}</count>
  12.     <sum>{sum($numbers)}</sum>
  13.     <avg>{avg($numbers)}</avg>
  14.     <min>{min($numbers)}</min>
  15.     <max>{max($numbers)}</max>
  16.   </stats>
复制代码

XQuery高级查询技巧

模块化编程

XQuery支持模块化编程,可以将代码组织成模块和函数库:
  1. (: 定义一个模块 - library.xq :)
  2. module namespace bookutils = "http://example.com/bookutils";
  3. declare function bookutils:discount($price as xs:decimal, $discountRate as xs:decimal) as xs:decimal {
  4.     $price * (1 - $discountRate)
  5. };
  6. declare function bookutils:format-price($price as xs:decimal) as xs:string {
  7.     concat("$", format-number($price, "##0.00"))
  8. };
  9. (: 使用模块 - main.xq :)
  10. import module namespace bookutils = "http://example.com/bookutils" at "library.xq";
  11. for $book in doc("books.xml")/books/book
  12. let $discountedPrice := bookutils:discount($book/price, 0.1)
  13. return
  14.   <book>
  15.     {$book/title}
  16.     <original_price>{bookutils:format-price($book/price)}</original_price>
  17.     <discounted_price>{bookutils:format-price($discountedPrice)}</discounted_price>
  18.   </book>
复制代码

递归函数

XQuery支持递归函数,这对于处理层次结构数据非常有用:
  1. (: 计算目录总大小的递归函数 :)
  2. declare function local:calculate-size($dir as element(directory)) as xs:integer {
  3.     let $fileSizes := sum($dir/file/@size)
  4.     let $subDirSizes := sum(for $subdir in $dir/directory return local:calculate-size($subdir))
  5.     return $fileSizes + $subDirSizes
  6. };
  7. (: 使用递归函数 :)
  8. let $root := doc("filesystem.xml")/filesystem/directory[1]
  9. return <total_size>{local:calculate-size($root)}</total_size>
复制代码

XML构造

XQuery提供了直接构造XML的功能:
  1. (: 直接构造XML :)
  2. <html>
  3.   <head>
  4.     <title>Book List</title>
  5.   </head>
  6.   <body>
  7.     <h1>Book List</h1>
  8.     <ul>
  9.     {
  10.       for $book in doc("books.xml")/books/book
  11.       return <li>{$book/title/text()} - {$book/price/text()}</li>
  12.     }
  13.     </ul>
  14.   </body>
  15. </html>
  16. (: 计算构造XML :)
  17. element html {
  18.   element head {
  19.     element title { "Book List" }
  20.   },
  21.   element body {
  22.     element h1 { "Book List" },
  23.     element ul {
  24.       for $book in doc("books.xml")/books/book
  25.       return element li { concat($book/title/text(), " - ", $book/price/text()) }
  26.     }
  27.   }
  28. }
复制代码

节点修改

XQuery提供了修改XML节点的功能:
  1. (: 使用copy和modify更新节点 :)
  2. let $books := doc("books.xml")/books
  3. return
  4.   copy $newBooks := $books
  5.   modify (
  6.     for $book in $newBooks/book[price > 30]
  7.     return replace value of node $book/price with $book/price * 0.9
  8.   )
  9.   return $newBooks
复制代码

连接操作

XQuery支持类似SQL的连接操作:
  1. (: 内连接 - 查找有评论的书籍 :)
  2. for $book in doc("books.xml")/books/book
  3. for $review in doc("reviews.xml")/reviews/review[book-id = $book/@id]
  4. return
  5.   <book_with_review>
  6.     {$book/title}
  7.     {$review/content}
  8.   </book_with_review>
  9. (: 左外连接 - 所有书籍及其评论,如果没有评论则为空 :)
  10. for $book in doc("books.xml")/books/book
  11. let $review := doc("reviews.xml")/reviews/review[book-id = $book/@id]
  12. return
  13.   <book_with_review>
  14.     {$book/title}
  15.     {if (exists($review)) then $review/content else <review>No reviews yet</review>}
  16.   </book_with_review>
复制代码

分组操作

XQuery支持分组操作,类似于SQL的GROUP BY:
  1. (: 按类别分组并计算平均价格 :)
  2. let $books := doc("books.xml")/books/book
  3. let $categories := distinct-values($books/category)
  4. return
  5.   <categories>
  6.   {
  7.     for $category in $categories
  8.     let $booksInCategory := $books[category = $category]
  9.     let $avgPrice := avg($booksInCategory/price)
  10.     return
  11.       <category name="{$category}">
  12.         <count>{count($booksInCategory)}</count>
  13.         <average_price>{$avgPrice}</average_price>
  14.       </category>
  15.   }
  16.   </categories>
复制代码

处理命名空间

XQuery提供了处理XML命名空间的功能:
  1. (: 声明和使用命名空间 :)
  2. declare namespace ns1 = "http://example.com/ns1";
  3. declare namespace ns2 = "http://example.com/ns2";
  4. for $item in doc("items.xml")//ns1:item
  5. where $item/ns2:price > 100
  6. return $item/ns2:name
  7. (: 动态命名空间处理 :)
  8. for $item in doc("items.xml")//(*:item)
  9. let $ns := namespace-uri($item)
  10. return
  11.   <item namespace="{$ns}">
  12.     {for $child in $item/* return
  13.       element {QName(namespace-uri($child), local-name($child))} {
  14.         $child/text()
  15.       }
  16.     }
  17.   </item>
复制代码

实际应用案例

图书管理系统

假设我们有一个图书管理系统的XML数据,我们需要使用XQuery来查询和处理这些数据。
  1. <!-- books.xml -->
  2. <books>
  3.   <book id="b1">
  4.     <title>Introduction to XQuery</title>
  5.     <authors>
  6.       <author>John Doe</author>
  7.       <author>Jane Smith</author>
  8.     </authors>
  9.     <category>Technology</category>
  10.     <price>45.99</price>
  11.     <publish_date>2020-01-15</publish_date>
  12.     <isbn>978-0123456789</isbn>
  13.   </book>
  14.   <book id="b2">
  15.     <title>XML Fundamentals</title>
  16.     <authors>
  17.       <author>Mike Johnson</author>
  18.     </authors>
  19.     <category>Technology</category>
  20.     <price>39.99</price>
  21.     <publish_date>2019-05-20</publish_date>
  22.     <isbn>978-0987654321</isbn>
  23.   </book>
  24.   <book id="b3">
  25.     <title>Modern Web Development</title>
  26.     <authors>
  27.       <author>Sarah Williams</author>
  28.       <author>Robert Brown</author>
  29.     </authors>
  30.     <category>Web Development</category>
  31.     <price>55.99</price>
  32.     <publish_date>2021-03-10</publish_date>
  33.     <isbn>978-1234567890</isbn>
  34.   </book>
  35.   <book id="b4">
  36.     <title>Data Science Essentials</title>
  37.     <authors>
  38.       <author>Emily Davis</author>
  39.     </authors>
  40.     <category>Data Science</category>
  41.     <price>49.99</price>
  42.     <publish_date>2021-07-25</publish_date>
  43.     <isbn>978-1122334455</isbn>
  44.   </book>
  45. </books>
复制代码
  1. (: 查询所有书籍的标题和价格 :)
  2. for $book in doc("books.xml")/books/book
  3. return
  4.   <book_info>
  5.     <title>{$book/title/text()}</title>
  6.     <price>{$book/price/text()}</price>
  7.   </book_info>
复制代码
  1. (: 查找Technology类别的书籍 :)
  2. for $book in doc("books.xml")/books/book
  3. where $book/category = "Technology"
  4. return
  5.   <tech_book>
  6.     {$book/title}
  7.     <price>{$book/price}</price>
  8.   </tech_book>
复制代码
  1. (: 查找价格在40到50之间的书籍 :)
  2. for $book in doc("books.xml")/books/book
  3. where $book/price >= 40 and $book/price <= 50
  4. return
  5.   <book>
  6.     {$book/title}
  7.     <price>{$book/price}</price>
  8.   </book>
复制代码
  1. (: 按类别分组并计算平均价格 :)
  2. let $books := doc("books.xml")/books/book
  3. let $categories := distinct-values($books/category)
  4. return
  5.   <category_stats>
  6.   {
  7.     for $category in $categories
  8.     let $booksInCategory := $books[category = $category]
  9.     let $avgPrice := avg($booksInCategory/price)
  10.     return
  11.       <category>
  12.         <name>{$category}</name>
  13.         <book_count>{count($booksInCategory)}</book_count>
  14.         <average_price>{$avgPrice}</average_price>
  15.       </category>
  16.   }
  17.   </category_stats>
复制代码
  1. (: 查找有多位作者的书籍 :)
  2. for $book in doc("books.xml")/books/book
  3. where count($book/authors/author) > 1
  4. return
  5.   <multi_author_book>
  6.     {$book/title}
  7.     <author_count>{count($book/authors/author)}</author_count>
  8.     <authors>
  9.       {for $author in $book/authors/author return $author}
  10.     </authors>
  11.   </multi_author_book>
复制代码
  1. (: 按价格降序排序并生成HTML表格 :)
  2. let $sortedBooks :=
  3.   for $book in doc("books.xml")/books/book
  4.   order by $book/price descending
  5.   return $book
  6. return
  7.   <html>
  8.     <head>
  9.       <title>Books by Price (Descending)</title>
  10.       <style>
  11.         table { border-collapse: collapse; width: 100%; }
  12.         th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
  13.         th { background-color: #f2f2f2; }
  14.       </style>
  15.     </head>
  16.     <body>
  17.       <h1>Books by Price (Descending)</h1>
  18.       <table>
  19.         <tr>
  20.           <th>Title</th>
  21.           <th>Category</th>
  22.           <th>Price</th>
  23.           <th>Authors</th>
  24.         </tr>
  25.         {
  26.           for $book in $sortedBooks
  27.           return
  28.             <tr>
  29.               <td>{$book/title/text()}</td>
  30.               <td>{$book/category/text()}</td>
  31.               <td>${$book/price/text()}</td>
  32.               <td>{string-join($book/authors/author/text(), ", ")}</td>
  33.             </tr>
  34.         }
  35.       </table>
  36.     </body>
  37.   </html>
复制代码

电子商务产品目录

假设我们有一个电子商务网站的产品目录XML数据,我们需要使用XQuery来查询和处理这些数据。
  1. <!-- products.xml -->
  2. <products>
  3.   <product id="p1">
  4.     <name>Smartphone X1</name>
  5.     <description>Latest smartphone with advanced features</description>
  6.     <category>Electronics</category>
  7.     <subcategory>Mobile Phones</subcategory>
  8.     <price>699.99</price>
  9.     <stock>50</stock>
  10.     <specifications>
  11.       <spec name="Screen Size">6.5 inches</spec>
  12.       <spec name="Storage">128 GB</spec>
  13.       <spec name="RAM">6 GB</spec>
  14.       <spec name="Camera">12 MP</spec>
  15.     </specifications>
  16.     <reviews>
  17.       <review id="r1" rating="5">
  18.         <user>Alice</user>
  19.         <comment>Great phone, very fast!</comment>
  20.         <date>2022-01-15</date>
  21.       </review>
  22.       <review id="r2" rating="4">
  23.         <user>Bob</user>
  24.         <comment>Good phone but battery life could be better.</comment>
  25.         <date>2022-02-10</date>
  26.       </review>
  27.     </reviews>
  28.   </product>
  29.   <product id="p2">
  30.     <name>Laptop Pro</name>
  31.     <description>High-performance laptop for professionals</description>
  32.     <category>Electronics</category>
  33.     <subcategory>Computers</subcategory>
  34.     <price>1299.99</price>
  35.     <stock>25</stock>
  36.     <specifications>
  37.       <spec name="Screen Size">15.6 inches</spec>
  38.       <spec name="Storage">512 GB SSD</spec>
  39.       <spec name="RAM">16 GB</spec>
  40.       <spec name="Processor">Intel Core i7</spec>
  41.     </specifications>
  42.     <reviews>
  43.       <review id="r3" rating="5">
  44.         <user>Charlie</user>
  45.         <comment>Perfect for my work needs.</comment>
  46.         <date>2022-01-20</date>
  47.       </review>
  48.     </reviews>
  49.   </product>
  50.   <product id="p3">
  51.     <name>Wireless Headphones</name>
  52.     <description>Premium noise-cancelling headphones</description>
  53.     <category>Electronics</category>
  54.     <subcategory>Audio</subcategory>
  55.     <price>199.99</price>
  56.     <stock>100</stock>
  57.     <specifications>
  58.       <spec name="Type">Over-ear</spec>
  59.       <spec name="Battery Life">30 hours</spec>
  60.       <spec name="Connectivity">Bluetooth 5.0</spec>
  61.     </specifications>
  62.     <reviews>
  63.       <review id="r4" rating="4">
  64.         <user>David</user>
  65.         <comment>Great sound quality, comfortable to wear.</comment>
  66.         <date>2022-02-05</date>
  67.       </review>
  68.       <review id="r5" rating="5">
  69.         <user>Eve</user>
  70.         <comment>Best headphones I've ever owned!</comment>
  71.         <date>2022-02-15</date>
  72.       </review>
  73.     </reviews>
  74.   </product>
  75. </products>
复制代码
  1. (: 查找库存少于30的产品 :)
  2. for $product in doc("products.xml")/products/product
  3. where $product/stock < 30
  4. return
  5.   <low_stock_product>
  6.     {$product/name}
  7.     <current_stock>{$product/stock}</current_stock>
  8.   </low_stock_product>
复制代码
  1. (: 查找Electronics类别的产品及其平均评分 :)
  2. for $product in doc("products.xml")/products/product
  3. where $product/category = "Electronics"
  4. let $avgRating := avg($product/reviews/review/@rating)
  5. return
  6.   <product>
  7.     {$product/name}
  8.     <price>{$product/price}</price>
  9.     <average_rating>{round-half-to-even($avgRating, 1)}</average_rating>
  10.   </product>
复制代码
  1. (: 查找存储容量至少为128GB的产品 :)
  2. for $product in doc("products.xml")/products/product
  3. where some $spec in $product/specifications/spec satisfies
  4.       $spec/@name = "Storage" and
  5.       (contains($spec, "128") or contains($spec, "256") or contains($spec, "512"))
  6. return
  7.   <product>
  8.     {$product/name}
  9.     <storage>{$product/specifications/spec[@name="Storage"]/text()}</storage>
  10.     <price>{$product/price}</price>
  11.   </product>
复制代码
  1. (: 生成产品目录的RSS订阅 :)
  2. let $products := doc("products.xml")/products/product
  3. return
  4.   <rss version="2.0">
  5.     <channel>
  6.       <title>Product Catalog</title>
  7.       <link>http://example.com/products</link>
  8.       <description>Latest products in our catalog</description>
  9.       <language>en-us</language>
  10.       {
  11.         for $product in $products
  12.         order by $product/price descending
  13.         return
  14.           <item>
  15.             <title>{$product/name/text()}</title>
  16.             <description>{$product/description/text()}</description>
  17.             <link>http://example.com/products/{$product/@id}</link>
  18.             <price>{$product/price/text()}</price>
  19.             <category>{$product/category/text()}</category>
  20.           </item>
  21.       }
  22.     </channel>
  23.   </rss>
复制代码
  1. (: 查找最受欢迎的产品(基于评论数量和平均评分):)
  2. for $product in doc("products.xml")/products/product
  3. let $reviewCount := count($product/reviews/review)
  4. let $avgRating := avg($product/reviews/review/@rating)
  5. let $popularityScore := $reviewCount * $avgRating
  6. order by $popularityScore descending
  7. return
  8.   <product>
  9.     {$product/name}
  10.     <review_count>{$reviewCount}</review_count>
  11.     <average_rating>{round-half-to-even($avgRating, 1)}</average_rating>
  12.     <popularity_score>{round-half-to-even($popularityScore, 1)}</popularity_score>
  13.   </product>
复制代码

医疗记录系统

假设我们有一个医疗记录系统的XML数据,我们需要使用XQuery来查询和处理这些数据。
  1. <!-- patients.xml -->
  2. <patients>
  3.   <patient id="pat1">
  4.     <name>John Smith</name>
  5.     <dob>1975-05-15</dob>
  6.     <gender>Male</gender>
  7.     <contact>
  8.       <phone>555-1234</phone>
  9.       <email>john.smith@example.com</email>
  10.       <address>
  11.         <street>123 Main St</street>
  12.         <city>Anytown</city>
  13.         <state>CA</state>
  14.         <zip>12345</zip>
  15.       </address>
  16.     </contact>
  17.     <visits>
  18.       <visit id="v1" date="2022-01-10">
  19.         <reason>Annual checkup</reason>
  20.         <diagnosis>General health assessment</diagnosis>
  21.         <doctor>Dr. Johnson</doctor>
  22.         <prescriptions>
  23.           <prescription>
  24.             <medication>Vitamin D</medication>
  25.             <dosage>1000 IU daily</dosage>
  26.             <duration>30 days</duration>
  27.           </prescription>
  28.         </prescriptions>
  29.       </visit>
  30.       <visit id="v2" date="2022-03-15">
  31.         <reason>Fever and cough</reason>
  32.         <diagnosis>Upper respiratory infection</diagnosis>
  33.         <doctor>Dr. Williams</doctor>
  34.         <prescriptions>
  35.           <prescription>
  36.             <medication>Amoxicillin</medication>
  37.             <dosage>500mg twice daily</dosage>
  38.             <duration>10 days</duration>
  39.           </prescription>
  40.         </prescriptions>
  41.       </visit>
  42.     </visits>
  43.   </patient>
  44.   <patient id="pat2">
  45.     <name>Jane Doe</name>
  46.     <dob>1982-08-22</dob>
  47.     <gender>Female</gender>
  48.     <contact>
  49.       <phone>555-5678</phone>
  50.       <email>jane.doe@example.com</email>
  51.       <address>
  52.         <street>456 Oak Ave</street>
  53.         <city>Sometown</city>
  54.         <state>NY</state>
  55.         <zip>67890</zip>
  56.       </address>
  57.     </contact>
  58.     <visits>
  59.       <visit id="v3" date="2022-02-05">
  60.         <reason>Follow-up appointment</reason>
  61.         <diagnosis>Hypertension management</diagnosis>
  62.         <doctor>Dr. Johnson</doctor>
  63.         <prescriptions>
  64.           <prescription>
  65.             <medication>Lisinopril</medication>
  66.             <dosage>10mg daily</dosage>
  67.             <duration>90 days</duration>
  68.           </prescription>
  69.         </prescriptions>
  70.       </visit>
  71.       <visit id="v4" date="2022-04-20">
  72.         <reason>Regular checkup</reason>
  73.         <diagnosis>Blood pressure monitoring</diagnosis>
  74.         <doctor>Dr. Johnson</doctor>
  75.         <prescriptions>
  76.           <prescription>
  77.             <medication>Lisinopril</medication>
  78.             <dosage>10mg daily</dosage>
  79.             <duration>90 days</duration>
  80.           </prescription>
  81.         </prescriptions>
  82.       </visit>
  83.     </visits>
  84.   </patient>
  85.   <patient id="pat3">
  86.     <name>Robert Brown</name>
  87.     <dob>1990-12-03</dob>
  88.     <gender>Male</gender>
  89.     <contact>
  90.       <phone>555-9012</phone>
  91.       <email>robert.brown@example.com</email>
  92.       <address>
  93.         <street>789 Pine Rd</street>
  94.         <city>Othercity</city>
  95.         <state>TX</state>
  96.         <zip>13579</zip>
  97.       </address>
  98.     </contact>
  99.     <visits>
  100.       <visit id="v5" date="2022-01-25">
  101.         <reason>Allergy symptoms</reason>
  102.         <diagnosis>Seasonal allergies</diagnosis>
  103.         <doctor>Dr. Davis</doctor>
  104.         <prescriptions>
  105.           <prescription>
  106.             <medication>Loratadine</medication>
  107.             <dosage>10mg daily</dosage>
  108.             <duration>30 days</duration>
  109.           </prescription>
  110.         </prescriptions>
  111.       </visit>
  112.     </visits>
  113.   </patient>
  114. </patients>
复制代码
  1. (: 查找Dr. Johnson的所有患者 :)
  2. for $patient in doc("patients.xml")/patients/patient
  3. where some $visit in $patient/visits/visit satisfies $visit/doctor = "Dr. Johnson"
  4. return
  5.   <patient>
  6.     {$patient/name}
  7.     <dob>{$patient/dob}</dob>
  8.     <last_visit>{max($patient/visits/visit/@date)}</last_visit>
  9.   </patient>
复制代码
  1. (: 查找Lisinopril的所有处方 :)
  2. for $patient in doc("patients.xml")/patients/patient
  3. for $visit in $patient/visits/visit
  4. for $prescription in $visit/prescriptions/prescription
  5. where $prescription/medication = "Lisinopril"
  6. return
  7.   <prescription>
  8.     <patient>{$patient/name/text()}</patient>
  9.     <visit_date>{$visit/@date}</visit_date>
  10.     <doctor>{$visit/doctor}</doctor>
  11.     <medication>{$prescription/medication}</medication>
  12.     <dosage>{$prescription/dosage}</dosage>
  13.     <duration>{$prescription/duration}</duration>
  14.   </prescription>
复制代码
  1. (: 查找2022年3月1日至2022年4月30日期间的所有访问 :)
  2. for $patient in doc("patients.xml")/patients/patient
  3. for $visit in $patient/visits/visit
  4. where xs:date($visit/@date) >= xs:date("2022-03-01") and
  5.       xs:date($visit/@date) <= xs:date("2022-04-30")
  6. return
  7.   <visit>
  8.     <patient>{$patient/name/text()}</patient>
  9.     <date>{$visit/@date}</date>
  10.     <reason>{$visit/reason}</reason>
  11.     <diagnosis>{$visit/diagnosis}</diagnosis>
  12.     <doctor>{$visit/doctor}</doctor>
  13.   </visit>
复制代码
  1. (: 按诊断分组患者 :)
  2. let $patients := doc("patients.xml")/patients/patient
  3. let $diagnoses := distinct-values($patients/visits/visit/diagnosis)
  4. return
  5.   <diagnosis_groups>
  6.   {
  7.     for $diagnosis in $diagnoses
  8.     let $patientsWithDiagnosis :=
  9.       for $patient in $patients
  10.       where some $visit in $patient/visits/visit satisfies $visit/diagnosis = $diagnosis
  11.       return $patient
  12.     return
  13.       <diagnosis_group>
  14.         <diagnosis>{$diagnosis}</diagnosis>
  15.         <patient_count>{count($patientsWithDiagnosis)}</patient_count>
  16.         <patients>
  17.           {for $patient in $patientsWithDiagnosis return $patient/name}
  18.         </patients>
  19.       </diagnosis_group>
  20.   }
  21.   </diagnosis_groups>
复制代码
  1. (: 生成患者访问历史报告 :)
  2. for $patient in doc("patients.xml")/patients/patient
  3. order by $patient/name
  4. return
  5.   <patient_report>
  6.     <patient_info>
  7.       <name>{$patient/name/text()}</name>
  8.       <dob>{$patient/dob}</dob>
  9.       <gender>{$patient/gender}</gender>
  10.       <contact>
  11.         <phone>{$patient/contact/phone}</phone>
  12.         <email>{$patient/contact/email}</email>
  13.         <address>
  14.           <street>{$patient/contact/address/street}</street>
  15.           <city>{$patient/contact/address/city}</city>
  16.           <state>{$patient/contact/address/state}</state>
  17.           <zip>{$patient/contact/address/zip}</zip>
  18.         </address>
  19.       </contact>
  20.     </patient_info>
  21.     <visit_history>
  22.       {
  23.         for $visit in $patient/visits/visit
  24.         order by $visit/@date
  25.         return
  26.           <visit>
  27.             <date>{$visit/@date}</date>
  28.             <reason>{$visit/reason}</reason>
  29.             <diagnosis>{$visit/diagnosis}</diagnosis>
  30.             <doctor>{$visit/doctor}</doctor>
  31.             <prescriptions>
  32.               {for $prescription in $visit/prescriptions/prescription return
  33.                 <prescription>
  34.                   <medication>{$prescription/medication}</medication>
  35.                   <dosage>{$prescription/dosage}</dosage>
  36.                   <duration>{$prescription/duration}</duration>
  37.                 </prescription>
  38.               }
  39.             </prescriptions>
  40.           </visit>
  41.       }
  42.     </visit_history>
  43.   </patient_report>
复制代码

性能优化

索引使用

在处理大型XML文档时,使用索引可以显著提高查询性能:
  1. (: 使用索引优化查询 - 假设已经在price元素上创建了索引 :)
  2. for $book in doc("books.xml")/books/book
  3. where $book/price > 30
  4. return $book/title
  5. (: 使用索引优化连接查询 - 假设已经在book-id属性上创建了索引 :)
  6. for $book in doc("books.xml")/books/book
  7. for $review in doc("reviews.xml")/reviews/review
  8. where $review/book-id = $book/@id
  9. return
  10.   <book_review>
  11.     {$book/title}
  12.     {$review/content}
  13.   </book_review>
复制代码

查询重写

重写查询以提高性能:
  1. (: 不高效的查询 - 使用了多个XPath表达式 :)
  2. for $book in doc("books.xml")/books/book
  3. where doc("books.xml")/books/book[@id = $book/@id]/price > 30
  4. return $book/title
  5. (: 高效的查询 - 避免重复的XPath表达式 :)
  6. for $book in doc("books.xml")/books/book[price > 30]
  7. return $book/title
复制代码

避免全文档扫描

避免不必要的全文档扫描:
  1. (: 不高效的查询 - 全文档扫描后过滤 :)
  2. for $book in doc("books.xml")/books/book
  3. where $book/category = "Technology" and $book/price > 30
  4. return $book/title
  5. (: 高效的查询 - 使用更具体的路径 :)
  6. for $book in doc("books.xml")/books/book[category = "Technology"][price > 30]
  7. return $book/title
复制代码

使用变量缓存结果

使用变量缓存中间结果:
  1. (: 不高效的查询 - 重复计算相同的表达式 :)
  2. for $book in doc("books.xml")/books/book
  3. return
  4.   <book>
  5.     <title>{$book/title}</title>
  6.     <price_with_tax>{$book/price * 1.08}</price_with_tax>
  7.     <discounted_price>{$book/price * 0.9}</discounted_price>
  8.     <final_price>{$book/price * 0.9 * 1.08}</final_price>
  9.   </book>
  10. (: 高效的查询 - 使用变量缓存中间结果 :)
  11. for $book in doc("books.xml")/books/book
  12. let $price := $book/price
  13. let $discountedPrice := $price * 0.9
  14. return
  15.   <book>
  16.     <title>{$book/title}</title>
  17.     <price_with_tax>{$price * 1.08}</price_with_tax>
  18.     <discounted_price>{$discountedPrice}</discounted_price>
  19.     <final_price>{$discountedPrice * 1.08}</final_price>
  20.   </book>
复制代码

使用特定函数代替通用函数

使用更具体的函数代替通用函数:
  1. (: 不高效的查询 - 使用通用函数 :)
  2. for $book in doc("books.xml")/books/book
  3. where count($book/authors/author) > 1
  4. return $book/title
  5. (: 高效的查询 - 使用特定函数 :)
  6. for $book in doc("books.xml")/books/book
  7. where exists($book/authors/author[2])
  8. return $book/title
复制代码

限制结果集大小

限制结果集大小以提高性能:
  1. (: 不高效的查询 - 处理所有结果 :)
  2. for $book in doc("books.xml")/books/book
  3. order by $book/price descending
  4. return $book/title
  5. (: 高效的查询 - 只处理前10个结果 :)
  6. for $book in doc("books.xml")/books/book
  7. order by $book/price descending
  8. return $book/title[position() <= 10]
复制代码

使用子查询优化

使用子查询优化复杂查询:
  1. (: 不高效的查询 - 嵌套FLWOR表达式 :)
  2. for $category in distinct-values(doc("books.xml")/books/book/category)
  3. let $books :=
  4.   for $book in doc("books.xml")/books/book
  5.   where $book/category = $category
  6.   return $book
  7. return
  8.   <category>
  9.     <name>{$category}</name>
  10.     <book_count>{count($books)}</book_count>
  11.     <average_price>{avg($books/price)}</average_price>
  12.   </category>
  13. (: 高效的查询 - 使用子查询 :)
  14. let $books := doc("books.xml")/books/book
  15. for $category in distinct-values($books/category)
  16. let $booksInCategory := $books[category = $category]
  17. return
  18.   <category>
  19.     <name>{$category}</name>
  20.     <book_count>{count($booksInCategory)}</book_count>
  21.     <average_price>{avg($booksInCategory/price)}</average_price>
  22.   </category>
复制代码

总结

XQuery是一种强大的XML查询语言,它提供了丰富的功能来查询、处理和转换XML数据。通过本文的学习,我们了解了XQuery的基础语法、高级查询技巧以及在实际应用中的使用方法。

关键要点

1. 基础语法:XQuery使用FLWOR表达式(For, Let, Where, Order by, Return)来构建查询,类似于SQL的SELECT-FROM-WHERE结构。
2. XPath表达式:XQuery使用XPath表达式来导航XML文档,选择特定的节点和属性。
3. 条件表达式:XQuery支持if-then-else条件表达式,可以根据条件返回不同的结果。
4. 序列操作:XQuery提供了丰富的序列操作功能,包括过滤、排序和聚合。
5. 模块化编程:XQuery支持模块化编程,可以将代码组织成模块和函数库,提高代码的可重用性。
6. 递归函数:XQuery支持递归函数,这对于处理层次结构数据非常有用。
7. XML构造:XQuery提供了直接构造XML的功能,可以方便地创建新的XML文档。
8. 节点修改:XQuery提供了修改XML节点的功能,可以更新、插入或删除节点。
9. 连接操作:XQuery支持类似SQL的连接操作,可以关联多个XML文档中的数据。
10. 分组操作:XQuery支持分组操作,类似于SQL的GROUP BY,可以对数据进行分组和聚合。

基础语法:XQuery使用FLWOR表达式(For, Let, Where, Order by, Return)来构建查询,类似于SQL的SELECT-FROM-WHERE结构。

XPath表达式:XQuery使用XPath表达式来导航XML文档,选择特定的节点和属性。

条件表达式:XQuery支持if-then-else条件表达式,可以根据条件返回不同的结果。

序列操作:XQuery提供了丰富的序列操作功能,包括过滤、排序和聚合。

模块化编程:XQuery支持模块化编程,可以将代码组织成模块和函数库,提高代码的可重用性。

递归函数:XQuery支持递归函数,这对于处理层次结构数据非常有用。

XML构造:XQuery提供了直接构造XML的功能,可以方便地创建新的XML文档。

节点修改:XQuery提供了修改XML节点的功能,可以更新、插入或删除节点。

连接操作:XQuery支持类似SQL的连接操作,可以关联多个XML文档中的数据。

分组操作:XQuery支持分组操作,类似于SQL的GROUP BY,可以对数据进行分组和聚合。

实际应用

XQuery在实际应用中有广泛的用途,包括:

1. 图书管理系统:查询和处理图书信息,如查找特定类别的书籍、计算平均价格等。
2. 电子商务产品目录:查询和处理产品信息,如查找库存不足的产品、生成产品目录的RSS订阅等。
3. 医疗记录系统:查询和处理患者信息,如查找特定医生的所有患者、生成患者访问历史报告等。

图书管理系统:查询和处理图书信息,如查找特定类别的书籍、计算平均价格等。

电子商务产品目录:查询和处理产品信息,如查找库存不足的产品、生成产品目录的RSS订阅等。

医疗记录系统:查询和处理患者信息,如查找特定医生的所有患者、生成患者访问历史报告等。

性能优化

在处理大型XML文档时,性能优化非常重要。以下是一些优化技巧:

1. 索引使用:使用索引可以显著提高查询性能。
2. 查询重写:重写查询以提高性能,避免重复的XPath表达式。
3. 避免全文档扫描:使用更具体的路径,避免不必要的全文档扫描。
4. 使用变量缓存结果:使用变量缓存中间结果,避免重复计算。
5. 使用特定函数代替通用函数:使用更具体的函数代替通用函数,提高查询效率。
6. 限制结果集大小:限制结果集大小,只处理必要的数据。
7. 使用子查询优化:使用子查询优化复杂查询,提高查询效率。

索引使用:使用索引可以显著提高查询性能。

查询重写:重写查询以提高性能,避免重复的XPath表达式。

避免全文档扫描:使用更具体的路径,避免不必要的全文档扫描。

使用变量缓存结果:使用变量缓存中间结果,避免重复计算。

使用特定函数代替通用函数:使用更具体的函数代替通用函数,提高查询效率。

限制结果集大小:限制结果集大小,只处理必要的数据。

使用子查询优化:使用子查询优化复杂查询,提高查询效率。

通过掌握XQuery的基础语法和高级技巧,并结合实际应用场景,我们可以更高效地查询和处理XML数据,充分发挥XML作为数据交换格式的优势。希望本文能够帮助读者全面掌握XQuery,实现XML数据的高效查询与处理。
「七転び八起き(ななころびやおき)」
回复

使用道具 举报

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

本版积分规则

联系我们|小黑屋|TG频道|RSS |网站地图

Powered by Pixtech

© 2025-2026 Pixtech Team.

>