当前位置: 首页 > news >正文

跟着 MDN 学 HTML day_53:(深入理解 XPathResult 接口)

在前几篇文章中,我们学习了 XPathEvaluator 和 XPathExpression 接口,掌握了如何编译和执行 XPath 表达式。今天我们将聚焦于 XPath 查询的最终产物:XPathResult 接口。

XPathResult 接口代表了在给定节点上下文中对 XPath 表达式求值后生成的结果。由于 XPath 表达式可以产生多种类型的结果,例如数值、字符串、布尔值或节点集合,这个接口提供了相应的属性和方法来处理不同类型的结果。理解 XPathResult 的完整能力,对于高效使用 XPath 至关重要。

一、XPathResult 概述

XPathResult 是一个基线广泛可用的接口,它封装了 XPath 表达式求值后的所有信息。每当调用 evaluate() 方法时,都会返回一个 XPathResult 对象。

这个接口的核心设计理念是:通过 resultType 属性判断结果的具体类型,然后根据类型使用对应的属性来获取值。例如,如果结果是数值类型,就读取 numberValue 属性;如果是布尔类型,就读取 booleanValue 属性。这种设计确保了类型安全的数据访问。

示例:创建 XPathResult 对象

constxpath="//div";constresult=document.evaluate(xpath,document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);console.log(resultinstanceofXPathResult);// trueconsole.log(result.resultType);// 7,对应 ORDERED_NODE_SNAPSHOT_TYPEconsole.log(result.snapshotLength);// 文档中 div 的数量

每个 XPath 查询都会返回这样一个结果对象,接下来我们将逐一学习它的各种属性和方法。

二、XPathResult.resultType 属性

定义

resultType 是一个只读属性,返回一个整数值,表示结果的类型。这个整数值对应 XPathResult 接口中定义的类型常量。通过检查 resultType,我们可以在运行时判断结果的具体形式,并采取相应的处理逻辑。

类型常量对照表

常量名称描述
ANY_TYPE0任意类型,由表达式自然决定
NUMBER_TYPE1单个数值结果
STRING_TYPE2单个字符串结果
BOOLEAN_TYPE3单个布尔值结果
UNORDERED_NODE_ITERATOR_TYPE4无序节点迭代器
ORDERED_NODE_ITERATOR_TYPE5有序节点迭代器
ORDERED_NODE_SNAPSHOT_TYPE6无序节点快照
ORDERED_NODE_SNAPSHOT_TYPE7有序节点快照
ANY_UNORDERED_NODE_TYPE8任意单个匹配节点
FIRST_ORDERED_NODE_TYPE9第一个匹配节点
示例:判断结果是否为节点集类型
<div>XPath example</div><div>Is XPath result a node set:<output></output></div>
constxpath="//div";constresult=document.evaluate(xpath,document,null,XPathResult.ANY_TYPE,null);// 判断结果是否为节点集类型(类型 4 到 9)constisNodeSet=result.resultType>=XPathResult.UNORDERED_NODE_ITERATOR_TYPE&&result.resultType<=XPathResult.FIRST_ORDERED_NODE_TYPE;document.querySelector("output").textContent=isNodeSet;// 输出:true

通过 resultType 属性,我们可以在处理结果之前先确认其类型,从而避免访问不匹配的属性时抛出异常。

三、XPathResult.numberValue 属性

定义

numberValue 是一个只读属性,当 resultType 为 NUMBER_TYPE 时,返回结果的数值。这个属性通常与 XPath 的聚合函数(如 count()、sum()、floor() 等)一起使用。

异常说明

如果 resultType 不是 NUMBER_TYPE,访问 numberValue 会抛出 TYPE_ERR 类型的 DOMException。

示例:使用 count 函数统计节点数量

<div>XPath example</div><div>Number of<div>s:<output></output></div>
constxpath="count(//div)";constresult=document.evaluate(xpath,document,null,XPathResult.NUMBER_TYPE,null);// 获取数值结果constdivCount=result.numberValue;document.querySelector("output").textContent=divCount;// 输出:2

在这个例子中,我们使用 XPath 的 count() 函数统计文档中所有

元素的数量。由于指定了 NUMBER_TYPE,结果会以数值形式返回,可以直接通过 numberValue 属性读取。

示例:使用 sum 函数计算总和

<divdata-value="10">项目A</div><divdata-value="25">项目B</div><divdata-value="15">项目C</div><div>总和:<output></output></div>
constxpath="sum(//div/@data-value)";constresult=document.evaluate(xpath,document,null,XPathResult.NUMBER_TYPE,null);document.querySelector("output").textContent=result.numberValue;// 输出:50

XPath 的数值计算能力使得我们在处理数据属性时无需手动遍历节点,一行表达式就能完成统计工作。

四、XPathResult.stringValue 属性

定义

stringValue 是一个只读属性,当 resultType 为 STRING_TYPE 时,返回结果的字符串值。如果 resultType 不是 STRING_TYPE,访问该属性会抛出 TYPE_ERR 异常。

示例:获取节点的文本内容

<divclass="message">Hello World</div><div>文本内容:<output></output></div>
constxpath="string(//div[@class='message'])";constresult=document.evaluate(xpath,document,null,XPathResult.STRING_TYPE,null);document.querySelector("output").textContent=result.stringValue;// 输出:Hello World

stringValue 属性非常适合用于提取特定节点的文本内容,或者获取属性值的字符串表示。

五、XPathResult.booleanValue 属性

定义

booleanValue 是一个只读属性,当 resultType 为 BOOLEAN_TYPE 时,返回结果的布尔值。这个属性通常与 XPath 的逻辑函数(如 not()、true()、false())或条件表达式一起使用。

示例:判断文本是否匹配

<div>XPath example</div><p>Text is 'XPath example':<output></output></p>
constxpath="//div/text() = 'XPath example'";constresult=document.evaluate(xpath,document,null,XPathResult.BOOLEAN_TYPE,null);document.querySelector("output").textContent=result.booleanValue;// 输出:true

在这个例子中,XPath 表达式判断

元素的文本内容是否等于 ‘XPath example’。由于结果类型指定为 BOOLEAN_TYPE,可以直接通过 booleanValue 获取布尔结果。

示例:判断是否存在特定元素

<divclass="active">活跃项</div><div>存在活跃项:<output></output></div>
constxpath="boolean(//div[@class='active'])";constresult=document.evaluate(xpath,document,null,XPathResult.BOOLEAN_TYPE,null);document.querySelector("output").textContent=result.booleanValue?"是":"否";// 输出:是

布尔类型的查询在条件判断场景中非常实用,可以快速确认某个节点或状态是否存在。

六、XPathResult.singleNodeValue 属性

定义

singleNodeValue 是一个只读属性,返回结果中的单个节点。如果结果类型为 ANY_UNORDERED_NODE_TYPE 或 FIRST_ORDERED_NODE_TYPE,该属性将返回匹配的节点对象。如果没有匹配的节点,返回 null。

示例:获取第一个匹配的节点

<divclass="item">第一项</div><divclass="item">第二项</div><divclass="item">第三项</div><div>第一项内容:<output></output></div>
constxpath="//div[@class='item']";constresult=document.evaluate(xpath,document,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null);constfirstNode=result.singleNodeValue;if(firstNode){document.querySelector("output").textContent=firstNode.textContent;}// 输出:第一项

singleNodeValue 非常适合只需要获取单个节点的场景,比如获取某个特定配置元素或检查某个节点是否存在。

七、XPathResult.snapshotLength 属性

定义

snapshotLength 是一个只读属性,返回结果快照中的节点数量。当结果类型为 UNORDERED_NODE_SNAPSHOT_TYPE 或 ORDERED_NODE_SNAPSHOT_TYPE 时,这个属性表示匹配节点的总数。

示例:获取节点快照的数量

<divclass="box">A</div><divclass="box">B</div><divclass="box">C</div><div>节点总数:<output></output></div>
constxpath="//div[@class='box']";constresult=document.evaluate(xpath,document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);document.querySelector("output").textContent=result.snapshotLength;// 输出:3

快照类型的结果一次性捕获了所有匹配节点,之后即使 DOM 发生变化,快照中的数据也不会改变,这为数据的一致性提供了保障。

八、XPathResult.snapshotItem() 方法

定义

snapshotItem(index) 方法返回快照集合中指定索引位置的节点。索引从 0 开始,如果索引超出范围则返回 null。

与迭代器不同,快照不会因为 DOM 的修改而失效,但它可能不再反映当前文档的最新状态。这意味着快照适用于需要稳定数据快照的场景。

示例:遍历快照中的所有节点

<ul><liclass="task">任务1</li><liclass="task">任务2</li><liclass="task">任务3</li></ul><ulid="output-list"></ul>
constxpath="//li[@class='task']";constresult=document.evaluate(xpath,document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);constoutputList=document.getElementById("output-list");// 遍历快照中的所有节点for(leti=0;i<result.snapshotLength;i++){constnode=result.snapshotItem(i);constnewItem=document.createElement("li");newItem.textContent=`快照项${i}:${node.textContent}`;outputList.appendChild(newItem);}

通过组合使用 snapshotLength 和 snapshotItem(),我们可以方便地遍历所有匹配节点,而不用担心遍历过程中 DOM 发生变化导致的问题。

九、XPathResult.iterateNext() 方法

定义

iterateNext() 方法用于迭代节点集结果中的下一个节点。如果结果类型是 UNORDERED_NODE_ITERATOR_TYPE 或 ORDERED_NODE_ITERATOR_TYPE,每次调用该方法都会返回集合中的下一个节点,直到返回 null 表示迭代结束。

示例:使用迭代器遍历节点

<divclass="number"></div><divclass="number"></div><divclass="number"></div><ulid="iter-result"></ul>
constxpath="//div[@class='number']";constresult=document.evaluate(xpath,document,null,XPathResult.ORDERED_NODE_ITERATOR_TYPE,null);constoutputList=document.getElementById("iter-result");letnode;// 使用迭代器依次获取节点while((node=result.iterateNext())){constnewItem=document.createElement("li");newItem.textContent=`迭代项:${node.textContent}`;outputList.appendChild(newItem);}

迭代器类型的优势在于按需获取节点,不需要一次性创建所有节点的快照,在处理大量节点时可能更节省内存。

十、XPathResult.invalidIteratorState 属性

定义

invalidIteratorState 是一个只读属性,用于指示迭代器是否已失效。当 resultType 为 UNORDERED_NODE_ITERATOR_TYPE 或 ORDERED_NODE_ITERATOR_TYPE 时,如果在结果返回后文档被修改,该属性会变为 true,表示迭代器不再可靠。

示例:检测迭代器状态

<div>XPath example</div><p>Iterator state:<output></output></p>
constxpath="//div";constresult=document.evaluate(xpath,document,null,XPathResult.ANY_TYPE,null);// 在迭代之前删除一个 div,使迭代器失效document.querySelector("div").remove();// 检查迭代器状态document.querySelector("output").textContent=result.invalidIteratorState?"invalid":"valid";// 输出:invalid

这个属性的存在提醒我们,迭代器类型的 XPath 结果与 DOM 的当前状态紧密关联。如果预计在获取结果后可能会修改 DOM,使用快照类型(SNAPSHOT)会是更安全的选择。

十一、快照与迭代器的选择

在实际开发中,选择合适的 XPath 结果类型非常重要。快照类型和迭代器类型有各自的适用场景。

示例:对比快照和迭代器的行为

<divclass="test">A</div><divclass="test">B</div><divclass="test">C</div><buttonid="modify-btn">删除第一个节点</button><div><p>快照结果数量:<outputid="snapshot-output"></output></p><p>迭代器状态:<outputid="iterator-output"></output></p></div>
// 快照类型constsnapshotResult=document.evaluate("//div[@class='test']",document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);// 迭代器类型constiteratorResult=document.evaluate("//div[@class='test']",document,null,XPathResult.ORDERED_NODE_ITERATOR_TYPE,null);document.getElementById("modify-btn").addEventListener("click",()=>{constfirstDiv=document.querySelector(".test");if(firstDiv)firstDiv.remove();// 快照数量不变document.getElementById("snapshot-output").textContent=snapshotResult.snapshotLength;// 迭代器状态变为失效document.getElementById("iterator-output").textContent=iteratorResult.invalidIteratorState?"已失效":"有效";});

快照适合需要稳定数据视图的场景,迭代器适合只需一次性顺序读取且内存敏感的场合。根据具体需求选择合适的类型,可以让代码更加健壮。

十二、总结

今天的学习内容全面覆盖了 XPathResult 接口的方方面面。我们从 resultType 属性入手,了解了十种结果类型的含义和用途。随后逐一学习了 numberValue、stringValue、booleanValue、singleNodeValue、snapshotLength 等只读属性,以及 snapshotItem() 和 iterateNext() 两个实例方法。最后还探讨了 invalidIteratorState 属性以及快照与迭代器的选择策略。

XPathResult 是 XPath 查询流程的终点,也是我们获取查询结果的关键接口。掌握它的各种属性和方法,能够让我们在处理 XPath 查询结果时更加得心应手,写出更高效、更健壮的代码。

结合前面学习的 XPathEvaluator 和 XPathExpression,现在我们已经完整掌握了浏览器环境中 XPath 查询的整个流程:从创建求值器、编译表达式,到执行查询、处理结果。这套完整的知识体系将为后续的 DOM 高级操作打下坚实的基础。


想要解锁更多HTML 核心标签实战、前端零基础入门干货、开发避坑全指南吗?
持续关注,后续将更新CSS 布局实战、JavaScript 交互基础、全站导航开发等硬核内容,带你从新手快速进阶,轻松搞定前端开发!

http://www.jsqmd.com/news/824757/

相关文章:

  • 去中心化AI智能体协作网络:SwarmVault架构设计与实践
  • Python人脸识别别再自己造轮子了!用DeepFace三行代码搞定年龄、性别、情绪分析
  • 极客桌面环境配置:从dotfiles到高效工作流
  • 使用HermesAgent对接Taotoken自定义模型供应商
  • Wonder3D:单图3D重建的革命性跨域扩散技术
  • Agent监控管理工具agenttop:实现自动化任务的可观测性与可控性
  • 告别手动画框!用飞桨EISeg 0.5.0,5分钟搞定遥感影像建筑物自动标注
  • Exynos 5420 ISP架构与图像处理技术解析
  • Parabolic:200+网站支持的跨平台视频下载神器
  • ul里能放div吗_列表项嵌套规范说明【说明】
  • CAN总线避坑指南:STM32F103通信异常?先看看TJA1051收发前后的波形对比(CAN_TX vs CAN_RX vs CAN_H)
  • 全球TOP3会展服务商都在用的PlayAI翻译配置模板(含中英日三语字幕同步渲染、唇动延迟补偿参数)
  • Nornir网络自动化监控插件:集成Sentry实现异常告警与上下文追踪
  • 基于CPX与CRICKIT的创客冰淇淋车:电机控制与交互系统实践
  • 机器人多物体抓取:扩散策略与模仿学习的创新应用
  • 别再傻傻分不清了!保姆级图解GPU、CUDA、cuDNN的关系与安装避坑指南
  • 用嘉立创EDA专业版做比赛项目:一个灯光控制器的完整设计复盘与优化思路
  • 无刷电机方波驱动进阶:基于STM32和IR2101S,如何让你的电机转得更稳、停得更准?
  • Godot游戏开发:模块化系统集成与事件驱动架构实战
  • Meta-Learning新视角:为什么说Reptile是‘聪明’的预训练?(从直觉到实验的深度解读)
  • 0405开源光刻机整机控制与量检测系统(A级 中期集中攻坚)5. 开源纳米量检测国产化替代方案(全链路替代·低成本落地·性能对标进口·喂饭级实施)
  • STM32与OpenMV协同实战:多色赛道视觉循迹与串口协议解析
  • 使用Taotoken后团队月度大模型API成本下降了可观比例
  • 5分钟配置Python大麦网自动化抢票脚本:告别手速比拼的技术方案
  • 自动化代码重构工具 abra:基于AST的代码现代化与质量提升实践
  • 别再在生产环境用KEYS了!Redis模糊查询的正确姿势:SCAN命令实战与避坑指南
  • 边缘医疗智能中的自适应多模态Transformer技术解析
  • Vivado工程实战:在ZCU102上配置MIG控制器时,SLEW属性设置成SLOW还是FAST?
  • ProGuard/R8 mapping文件不止能还原堆栈?这份Android逆向分析指南请收好
  • STM32G431实战:用CubeMX+中断搞定两个555定时器PWM捕获(附完整代码)