掌握XQuery编程技巧从入门到精通 实战经验分享与常见问题解决方案助你高效处理XML数据

引言:XQuery在现代数据处理中的核心地位
在当今数据驱动的世界中,XML(可扩展标记语言)作为一种灵活的数据交换格式,广泛应用于企业集成、Web服务、配置文件和文档存储等领域。XQuery作为W3C标准的查询语言,专门设计用于从XML文档中提取和操作数据,其重要性不言而喻。根据最新的行业调查,超过60%的企业级应用依赖XML数据源,而XQuery是处理这些数据的首选工具。它不仅支持复杂的查询逻辑,还能无缝集成XPath表达式,提供强大的数据转换能力。
XQuery的起源可以追溯到2000年代初,由W3C XML Query工作组开发,旨在解决XPath 1.0在处理复杂查询时的局限性。如今,XQuery 3.1已成为主流标准,支持函数式编程范式、高阶函数和JSON处理,使其在大数据和NoSQL环境中也游刃有余。本文将从入门基础入手,逐步深入到高级技巧、实战案例和常见问题解决方案,帮助读者从初学者成长为XQuery专家。我们将通过详尽的代码示例和实际场景分析,确保内容实用且易于理解。
第一部分:XQuery入门基础
1.1 XQuery概述与环境搭建
XQuery是一种声明式查询语言,专为XML数据设计。它类似于SQL,但针对树状结构的XML进行了优化。XQuery的核心优势在于其表达力强、语法简洁,能处理从简单提取到复杂转换的各种任务。
要开始学习XQuery,首先需要搭建开发环境。推荐使用以下工具:
BaseX
:开源的XQuery处理器,支持XQuery 3.1,提供交互式命令行和GUI界面。下载地址:
https://basex.org/。
eXist-db
:原生XML数据库,内置XQuery引擎,适合Web应用开发。
Saxon
:商业级处理器,提供Java和.NET绑定,支持高性能查询。
安装BaseX的步骤(以Windows为例):
下载BaseX ZIP包并解压。
运行
basex.bat
启动GUI。
创建一个新数据库:在GUI中点击“New”,输入数据库名(如
mydb
),然后导入XML文件。
示例XML文件(
books.xml
):
XQuery入门指南
张三 45.00 编程


XML高级应用
李四 60.00 数据


Web服务架构
王五 55.00 架构
在BaseX中运行第一个XQuery查询:
//book/title
这个简单查询使用XPath语法(XQuery的子集)提取所有
<br /> 元素。输出:<br /> <XQuery入门指南><br /> <XML高级应用><br /> <Web服务架构><br /> 1.2 XQuery基本语法<br /> XQuery的语法基于FLWOR表达式(For-Let-Where-Order by-Return),这是其核心结构。让我们分解一个典型查询:<br /> For<br /> :迭代序列。<br /> Let<br /> :变量绑定。<br /> Where<br /> :过滤条件。<br /> Order by<br /> :排序。<br /> Return<br /> :输出结果。<br /> 示例:从<br /> books.xml<br /> 中查询价格大于50的书籍标题,并按价格降序排序。<br /> for $book in doc(“books.xml”)/library/book<br /> let $title := $book/title<br /> where $book/price > 50<br /> order by $book/price descending<br /> return $title<br /> 解释:<br /> doc(“books.xml”)<br /> :加载XML文档。<br /> for $book in …<br /> :遍历每个<br /> <book><br /> 元素。<br /> let $title := $book/title<br /> :绑定变量。<br /> where $book/price > 50<br /> :过滤。<br /> order by … descending<br /> :降序。<br /> return $title<br /> :返回标题。<br /> 输出:<br /> <Web服务架构><br /> <XML高级应用><br /> XQuery支持数据类型,如<br /> xs:integer<br /> 、<br /> xs:string<br /> 。在查询中,可以显式转换:<br /> return <result>{xs:decimal($book/price) * 1.1}</result> (: 加10%税 🙂<br /> 1.3 XPath与XQuery的关系<br /> XPath是XQuery的基础,XQuery扩展了XPath的表达能力。XPath 3.1是XQuery 3.1的子集,支持函数和更高阶的表达式。入门时,先掌握XPath轴(如<br /> ancestor<br /> 、<br /> child<br /> )和谓词(<br /> [condition]<br /> )。<br /> 示例:使用XPath在XQuery中查找特定作者的书籍。<br /> doc(“books.xml”)//book[author=”李四”]/title<br /> 输出:<br /> <XML高级应用><br /> 第二部分:XQuery编程技巧进阶<br /> 2.1 高效使用FLWOR表达式<br /> FLWOR是XQuery的灵魂,但初学者常忽略其优化潜力。技巧:使用<br /> let<br /> 代替嵌套<br /> for<br /> 以减少计算开销。<br /> 实战示例:假设我们有更复杂的XML(<br /> orders.xml<br /> ),包含订单和客户信息。<br /> <orders><br /> <order id="101"><br /> <customer>张三</customer><br /> <items><br /> <item><name>书</name><qty>2</qty><price>45</price></item><br /> <item><name>笔</name><qty>5</qty><price>10</price></item><br /> </items><br /> </order><br /> <order id="102"><br /> <customer>李四</customer><br /> <items><br /> <item><name>笔记本</name><qty>1</qty><price>20</price></item><br /> </items><br /> </order><br /> </orders><br /> 计算每个订单的总金额:<br /> for $order in doc(“orders.xml”)/orders/order<br /> let $total := sum($order/items/item/qty * $order/items/item/price)<br /> return <order id="{$order/@id}">{$total}</order><br /> 输出:<br /> <order id="101">140</order><br /> <order id="102">20</order><br /> 技巧:使用<br /> group by<br /> (XQuery 3.0+)分组数据。<br /> for $order in doc(“orders.xml”)/orders/order<br /> let $customer := $order/customer<br /> group by $customer<br /> return <customer name="{$customer}">总订单数:{count($order)}</customer><br /> 2.2 函数定义与重用<br /> XQuery支持用户定义函数(UDF),类似于编程语言的函数。函数以<br /> declare function<br /> 开头。<br /> 示例:定义一个函数计算折扣。<br /> declare function local:discount($price as xs:decimal, $rate as xs:decimal) as xs:decimal {<br /> $price * (1 – $rate)<br /> };</p> <p>for $book in doc(“books.xml”)/library/book<br /> return <discounted>{local:discount($book/price, 0.1)}</discounted><br /> 输出:<br /> <discounted>40.5</discounted><br /> <discounted>54.0</discounted><br /> <discounted>49.5</discounted><br /> 高级技巧:递归函数处理树状数据。例如,计算XML树的深度。<br /> declare function local:tree-depth($node as node()) as xs:integer {<br /> if (empty($node/*)) then 1<br /> else 1 + max(for $child in $node/* return local:tree-depth($child))<br /> };</p> <p>local:tree-depth(doc(“books.xml”)/library)<br /> 这将返回3(根、book、子元素)。<br /> 2.3 处理序列与节点测试<br /> XQuery的核心是序列(有序集合)。使用<br /> some<br /> 和<br /> every<br /> 进行存在性检查。<br /> 示例:检查所有书籍价格是否大于40。<br /> every $price in doc(“books.xml”)/library/book/price<br /> satisfies $price > 40<br /> 返回<br /> true<br /> 。<br /> 节点测试技巧:使用<br /> node()<br /> 、<br /> element()<br /> 、<br /> text()<br /> 精确匹配。<br /> for $text in doc(“books.xml”)//text()<br /> return $text<br /> 提取所有文本节点。<br /> 2.4 XQuery 3.1高级特性:Map和Array<br /> XQuery 3.1引入了Map(键值对)和Array,使其能处理JSON-like数据。<br /> 示例:将XML转换为Map。<br /> let $books := doc(“books.xml”)/library/book<br /> return map {<br /> “books”: array {<br /> for $b in $books<br /> return map {<br /> “title”: string($b/title),<br /> “price”: xs:decimal($b/price)<br /> }<br /> }<br /> }<br /> 输出(JSON格式):<br /> {<br /> “books”: [<br /> {“title”: “XQuery入门指南”, “price”: 45.0},<br /> {“title”: “XML高级应用”, “price”: 60.0},<br /> {“title”: “Web服务架构”, “price”: 55.0}<br /> ]<br /> }<br /> 技巧:使用<br /> =><br /> 操作符链式调用函数。<br /> doc(“books.xml”)/library/book/price => sum() => xs:decimal()<br /> 第三部分:实战经验分享<br /> 3.1 场景一:企业级XML数据集成<br /> 在企业环境中,XQuery常用于从多个XML源(如SOAP响应、配置文件)聚合数据。假设我们有客户XML(<br /> customers.xml<br /> )和订单XML(<br /> orders.xml<br /> ),需要生成报告。<br /> XML示例(<br /> customers.xml<br /> ):<br /> <customers><br /> <customer id="1"><name>张三</name><region>北京</region></customer><br /> <customer id="2"><name>李四</name><region>上海</region></customer><br /> </customers><br /> 实战查询:生成客户订单报告,按区域分组。<br /> for $cust in doc(“customers.xml”)/customers/customer<br /> let $orders := doc(“orders.xml”)/orders/order[customer=$cust/name]<br /> group by $region := $cust/region<br /> return <region name="{$region}">{<br /> for $o in $orders<br /> return <order id="{$o/@id}">客户:{$cust/name},总金额:{sum($o/items/item/qty * $o/items/item/price)}</order><br /> }</region><br /> 输出:<br /> <region name="北京"><br /> <order id="101">客户:张三,总金额:140</order><br /> </region><br /> <region name="上海"><br /> <order id="102">客户:李四,总金额:20</order><br /> </region><br /> 经验分享:在大型数据集上,使用索引(如BaseX的全文索引)加速查询。避免在<br /> for<br /> 循环中重复加载文档,使用变量预加载。<br /> 3.2 场景二:Web服务中的XQuery<br /> 在RESTful API中,XQuery可作为后端处理器。例如,使用eXist-db构建一个查询服务。<br /> 步骤:<br /> 将XML上传到eXist-db。<br /> 创建XQuery模块(<br /> query.xqm<br /> ):<br /> xquery version “3.1”;<br /> declare namespace rest=”http://exquery.org/ns/restxq”;<br /> declare namespace output=”http://www.w3.org/2010/xslt-xquery-serialization”;</p> <p>declare<br /> %rest:path(“/books/{$title}”)<br /> %rest:GET<br /> %output:method(“json”)<br /> function local:get-book($title as xs:string) {<br /> let $book := doc(“books.xml”)/library/book[title=$title]<br /> return map {<br /> “title”: string($book/title),<br /> “author”: string($book/author),<br /> “price”: xs:decimal($book/price)<br /> }<br /> };<br /> 调用:<br /> GET /books/XQuery入门指南<br /> 返回JSON。<br /> 经验:处理并发时,使用事务(<br /> db:transaction<br /> )确保数据一致性。在高负载下,考虑分页:使用<br /> subsequence($seq, $start, $length)<br /> 限制结果。<br /> 3.3 场景三:大数据处理与优化<br /> 对于海量XML(如TB级日志),XQuery的性能至关重要。技巧:<br /> 流式处理<br /> :使用<br /> fn:parse-xml<br /> 处理流数据。<br /> 并行化<br /> :在支持的环境中(如Saxon-EE)使用并行序列。<br /> 示例:处理日志XML,统计错误。<br /> <logs><br /> <log><timestamp>2023-01-01T10:00:00</timestamp><level>ERROR</level><msg>DB连接失败</msg></log><br /> <log><timestamp>2023-01-01T10:05:00</timestamp><level>INFO</level><msg>操作成功</msg></log><br /> </logs><br /> 查询:<br /> for $log in doc(“logs.xml”)/logs/log<br /> where $log/level=”ERROR”<br /> group by $hour := hour-from-dateTime($log/timestamp)<br /> return <hour>{$hour}: {count($log)}</hour><br /> 优化:使用<br /> db:open<br /> 在数据库中直接查询,避免文件I/O。监控查询计划(BaseX的<br /> EXPLAIN<br /> 命令)。<br /> 第四部分:常见问题解决方案<br /> 4.1 问题1:命名空间冲突<br /> 症状<br /> :查询忽略元素,因为XML有默认命名空间。<br /> 解决方案<br /> :显式声明命名空间。<br /> declare namespace lib=”http://example.com/library”;<br /> for $book in doc(“books.xml”)/lib:library/lib:book<br /> return $book/lib:title<br /> 预防<br /> :在XQuery中始终使用<br /> declare namespace<br /> 。使用<br /> in-scope-prefixes<br /> 调试。<br /> 4.2 问题2:性能瓶颈<br /> 症状<br /> :查询在大数据上超时。<br /> 解决方案<br /> :<br /> 索引:在BaseX中创建结构索引:<br /> CREATE INDEX PATH<br /> 。<br /> 避免深层嵌套:重构为多个简单查询。<br /> 示例优化前:<br /> for $b in //book[price > 50][author=”张三”] (: 慢,双重过滤 🙂<br /> return $b<br /> 优化后:<br /> let $cheap := //book[price > 50]<br /> return $cheap[author=”张三”]<br /> 工具<br /> :使用Saxon的性能分析器,或BaseX的<br /> PROFILE<br /> 命令查看执行时间。<br /> 4.3 问题3:类型错误<br /> 症状<br /> :<br /> XPTY0004<br /> 错误,类型不匹配。<br /> 解决方案<br /> :使用<br /> cast as<br /> 或<br /> instance of<br /> 。<br /> if ($price instance of xs:decimal) then $price else xs:decimal($price)<br /> 调试<br /> :在查询中添加<br /> typeswitch<br /> 表达式处理不同类型。<br /> typeswitch ($node)<br /> case element(price) return xs:decimal($node)<br /> default return $node<br /> 4.4 问题4:序列处理错误<br /> 症状<br /> :空序列导致函数失败。<br /> 解决方案<br /> :使用<br /> empty()<br /> 或<br /> exists()<br /> 检查。<br /> if (empty($result)) then “无结果” else $result<br /> 高级<br /> :使用<br /> for $item in $seq return $item<br /> 确保序列展开。<br /> 4.5 问题5:JSON与XML互转<br /> 症状<br /> :XQuery 3.1中JSON输出不正确。<br /> 解决方案<br /> :使用<br /> json:serialize<br /> 或内置序列化。<br /> xquery version “3.1”;<br /> import module namespace json=”http://basex.org/modules/json”;</p> <p>let $data := map { “key”: “value” }<br /> return json:serialize($data)<br /> 在BaseX中,设置输出方法为JSON:<br /> SET OUTPUT METHOD JSON<br /> 。<br /> 结论:从入门到精通的路径<br /> 通过本文的系统讲解,您已掌握XQuery从基础语法到高级技巧的全过程。入门时,多练习FLWOR和XPath;进阶时,探索函数和Map;实战中,注重优化和场景应用。常见问题通过调试和最佳实践可轻松解决。建议阅读W3C XQuery 3.1规范,并使用BaseX或Saxon进行实践。坚持项目驱动学习,您将高效处理任何XML数据,成为XQuery专家。如果有具体XML文件或查询需求,欢迎进一步探讨!</p> </div> <div class="wp-block-group has-global-padding is-layout-constrained wp-block-group-is-layout-constrained" style="margin-top:var(--wp--preset--spacing--40);padding-bottom:var(--wp--preset--spacing--50)"> <div class="wp-block-group has-global-padding is-layout-constrained wp-block-group-is-layout-constrained"> <div style="height:var(--wp--preset--spacing--40)" aria-hidden="true" class="wp-block-spacer"> </div> <hr class="wp-block-separator has-text-color has-contrast-3-color has-alpha-channel-opacity has-contrast-3-background-color has-background is-style-wide" style="margin-bottom:var(--wp--preset--spacing--40)"/> <nav class="wp-block-group is-content-justification-space-between is-nowrap is-layout-flex wp-container-core-group-is-layout-2b923ac6 wp-block-group-is-layout-flex" style="padding-top:var(--wp--preset--spacing--40);padding-bottom:var(--wp--preset--spacing--40)" aria-label="Posts"> <div class="post-navigation-link-previous wp-block-post-navigation-link"><span class="wp-block-post-navigation-link__arrow-previous is-arrow-arrow" aria-hidden="true">←</span><a href="https://ziliao.tiaomu.com/102436042/" rel="prev"><span class="post-navigation-link__label">Previous: </span> <span class="post-navigation-link__title">Taylor Swift 2018年身材变化:揭秘流行天后减肥与增重的秘密</span></a></div> <div class="post-navigation-link-next wp-block-post-navigation-link"><a href="https://ziliao.tiaomu.com/102436044/" rel="next"><span class="post-navigation-link__label">Next: </span> <span class="post-navigation-link__title">济南公交四门拆解视频曝光 一辆公交车的完整拆解过程与零件寿命分析</span></a><span class="wp-block-post-navigation-link__arrow-next is-arrow-arrow" aria-hidden="true">→</span></div> </nav> </div> </div> </main> <footer class="wp-block-template-part"> <div class="wp-block-group has-global-padding is-layout-constrained wp-block-group-is-layout-constrained" style="padding-top:var(--wp--preset--spacing--50);padding-bottom:var(--wp--preset--spacing--50)"> <div class="wp-block-columns alignwide is-layout-flex wp-container-core-columns-is-layout-3a88641f wp-block-columns-is-layout-flex"> <div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:30%"> <div class="wp-block-group is-vertical is-layout-flex wp-container-core-group-is-layout-831b2db5 wp-block-group-is-layout-flex"> <p class="wp-block-site-title has-medium-font-size"><a href="https://ziliao.tiaomu.com" target="_self" rel="home">资料库 – 中文知识库</a></p> </div> </div> <div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:20%"> </div> <div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:50%"> <div class="wp-block-group is-content-justification-space-between is-layout-flex wp-container-core-group-is-layout-cf54d0a6 wp-block-group-is-layout-flex"> <div class="wp-block-group is-vertical is-content-justification-stretch is-layout-flex wp-container-core-group-is-layout-d8dce8eb wp-block-group-is-layout-flex"> <h2 class="wp-block-heading has-medium-font-size has-body-font-family" style="font-style:normal;font-weight:600">About</h2> <div class="wp-block-group is-vertical is-layout-flex wp-container-core-group-is-layout-bce0c455 wp-block-group-is-layout-flex"> <nav style="font-style:normal;font-weight:400" class="has-small-font-size is-vertical wp-block-navigation is-layout-flex wp-container-core-navigation-is-layout-bce0c455 wp-block-navigation-is-layout-flex" aria-label="About"><ul style="font-style:normal;font-weight:400" class="wp-block-navigation__container has-small-font-size is-vertical wp-block-navigation" aria-label="About"><li class="wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">Team</span></a></li><li class="wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">History</span></a></li><li class="wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">Careers</span></a></li></ul></nav> </div> </div> <div class="wp-block-group is-vertical is-content-justification-stretch is-layout-flex wp-container-core-group-is-layout-d8dce8eb wp-block-group-is-layout-flex"> <h2 class="wp-block-heading has-medium-font-size has-body-font-family" style="font-style:normal;font-weight:600">Privacy</h2> <div class="wp-block-group is-vertical is-layout-flex wp-container-core-group-is-layout-bce0c455 wp-block-group-is-layout-flex"> <nav style="font-style:normal;font-weight:400" class="has-small-font-size is-vertical wp-block-navigation is-layout-flex wp-container-core-navigation-is-layout-bce0c455 wp-block-navigation-is-layout-flex" aria-label="Privacy"><ul style="font-style:normal;font-weight:400" class="wp-block-navigation__container has-small-font-size is-vertical wp-block-navigation" aria-label="Privacy"><li class="wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">Privacy Policy</span></a></li><li class="wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">Terms and Conditions</span></a></li><li class="wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">Contact Us</span></a></li></ul></nav> </div> </div> <div class="wp-block-group is-vertical is-content-justification-stretch is-layout-flex wp-container-core-group-is-layout-d8dce8eb wp-block-group-is-layout-flex"> <h2 class="wp-block-heading has-medium-font-size has-body-font-family" style="font-style:normal;font-weight:600">Social</h2> <div class="wp-block-group is-vertical is-layout-flex wp-container-core-group-is-layout-bce0c455 wp-block-group-is-layout-flex"> <nav style="font-style:normal;font-weight:400" class="has-small-font-size is-vertical wp-block-navigation is-layout-flex wp-container-core-navigation-is-layout-bce0c455 wp-block-navigation-is-layout-flex" aria-label="Social Media"><ul style="font-style:normal;font-weight:400" class="wp-block-navigation__container has-small-font-size is-vertical wp-block-navigation" aria-label="Social Media"><li class="wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">Facebook</span></a></li><li class="wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">Instagram</span></a></li><li class="wp-block-navigation-item wp-block-navigation-link"><a class="wp-block-navigation-item__content" href="#"><span class="wp-block-navigation-item__label">Twitter/X</span></a></li></ul></nav> </div> </div> </div> </div> </div> <div class="wp-block-group alignwide is-layout-flow wp-block-group-is-layout-flow" style="padding-top:var(--wp--preset--spacing--50);padding-bottom:0"> <p class="has-contrast-2-color has-text-color has-link-color has-small-font-size wp-elements-1 wp-block-paragraph"> Designed with <a href="https://wordpress.org" rel="nofollow">WordPress</a> </p> </div> </div> </footer> </div> <script type="speculationrules"> {"prefetch":[{"source":"document","where":{"and":[{"href_matches":"/*"},{"not":{"href_matches":["/wp-*.php","/wp-admin/*","/wp-content/uploads/*","/wp-content/*","/wp-content/plugins/*","/wp-content/themes/twentytwentyfour/*","/*\\?(.+)"]}},{"not":{"selector_matches":"a[rel~=\"nofollow\"]"}},{"not":{"selector_matches":".no-prefetch, .no-prefetch a"}}]},"eagerness":"conservative"}]} </script> <script data-wp-router-options="{"loadOnClientNavigation":true}" fetchpriority="low" id="@wordpress/block-library/navigation/view-js-module" src="https://ziliao.tiaomu.com/wp-includes/js/dist/script-modules/block-library/navigation/view.min.js?ver=1bf28ded04f9f188bdcb" type="module"></script> <script id="wp-emoji-settings" type="application/json"> {"baseUrl":"https://s.w.org/images/core/emoji/17.0.2/72x72/","ext":".png","svgUrl":"https://s.w.org/images/core/emoji/17.0.2/svg/","svgExt":".svg","source":{"concatemoji":"https://ziliao.tiaomu.com/wp-includes/js/wp-emoji-release.min.js?ver=7.1.3"}} </script> <script type="module"> /*! This file is auto-generated */ var e="script#wp-emoji-settings",t=document.querySelector(e);if(!(t instanceof HTMLScriptElement))throw new Error("Element missing: "+e);const r=JSON.parse(t.text),s=(window._wpemojiSettings=r,"wpEmojiSettingsSupports"),o=["flag","emoji"];function i(e){try{var t={supportTests:e,timestamp:(new Date).valueOf()};sessionStorage.setItem(s,JSON.stringify(t))}catch(e){}}function c(e,t,n){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);t=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data);e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(n,0,0);const r=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data);return t.every((e,t)=>e===r[t])}function p(e,t){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);var n=e.getImageData(16,16,1,1);for(let e=0;e<n.data.length;e++)if(0!==n.data[e])return!1;return!0}function u(e,t,n,r){switch(t){case"flag":return n(e,"\ud83c\udff3\ufe0f\u200d\u26a7\ufe0f","\ud83c\udff3\ufe0f\u200b\u26a7\ufe0f")?!1:!n(e,"\ud83c\udde8\ud83c\uddf6","\ud83c\udde8\u200b\ud83c\uddf6")&&!n(e,"\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f","\ud83c\udff4\u200b\udb40\udc67\u200b\udb40\udc62\u200b\udb40\udc65\u200b\udb40\udc6e\u200b\udb40\udc67\u200b\udb40\udc7f");case"emoji":return!r(e,"\ud83e\u1fac8")}return!1}function f(e,t,n,r){let a;const s=(a="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?new OffscreenCanvas(300,150):document.createElement("canvas")).getContext("2d",{willReadFrequently:!0}),o=(s.textBaseline="top",s.font="600 32px Arial",{});return e.forEach(e=>{o[e]=t(s,e,n,r)}),o}function a(e){var t=document.createElement("script");t.src=e,t.defer=!0,document.head.appendChild(t)}r.supports={everything:!0,everythingExceptFlag:!0},new Promise(t=>{let n=function(){try{var e=JSON.parse(sessionStorage.getItem(s));if("object"==typeof e&&"number"==typeof e.timestamp&&(new Date).valueOf()<e.timestamp+604800&&"object"==typeof e.supportTests)return e.supportTests}catch(e){}return null}();if(!n){if("undefined"!=typeof Worker&&"undefined"!=typeof OffscreenCanvas&&"undefined"!=typeof URL&&URL.createObjectURL&&"undefined"!=typeof Blob)try{var e="postMessage("+f.toString()+"("+[JSON.stringify(o),u.toString(),c.toString(),p.toString()].join(",")+"));",r=new Blob([e],{type:"text/javascript"});const a=new Worker(URL.createObjectURL(r),{name:"wpTestEmojiSupports"});return void(a.onmessage=e=>{i(n=e.data),a.terminate(),t(n)})}catch(e){}i(n=f(o,u,c,p))}t(n)}).then(e=>{for(const n in e)r.supports[n]=e[n],r.supports.everything=r.supports.everything&&r.supports[n],"flag"!==n&&(r.supports.everythingExceptFlag=r.supports.everythingExceptFlag&&r.supports[n]);var t;r.supports.everythingExceptFlag=r.supports.everythingExceptFlag&&!r.supports.flag,r.supports.everything||((t=r.source||{}).concatemoji?a(t.concatemoji):t.wpemoji&&t.twemoji&&(a(t.twemoji),a(t.wpemoji)))}); //# sourceURL=https://ziliao.tiaomu.com/wp-includes/js/wp-emoji-loader.min.js </script> <noscript><link rel="stylesheet" href="https://ziliao.tiaomu.com/wp-content/themes/abiz/assets/css/all.min.css?ver=6.5.1"></noscript> </body> </html>