XPath是定位XML节点的路径表达式,需嵌入其他语言使用;XQuery是图灵完备查询语言,支持变量、函数、多文档处理和FLWOR等高级特性。
XPath 本身不是独立运行的语言,而是一套用于定位 XML 文档中节点的路径表达式语法,必须嵌入在其他语言(如 XSLT、XQuery、DOM API)中使用。XQuery 则是完整的图灵完备查询语言,能声明变量、写函数、做条件判断、连接多个文档,甚至支持 FLWOR 表达式(类似 SQL 的 for/let/where/order by/return)。
你在 document.evaluate()(浏览器 DOM)、xpath()(Python lxml)、或 XSLT 的 select 属性里写的,都是 XPath 表达式;而用 zorba、BaseX 或 Saxon 的 xquery() 方法执行的,才是 XQuery 脚本。
多数 Web 抓取、配置提取、简单 XML 转 JSON 场景,只需要“从 XML 里捞出几个字段”,这时 //book/title/text() 这类 XPath 就足够了——它轻量、跨平台支持好、解析快,且几乎所有 XML/HTML 解析库都内置支持。
lxml.etree 时,root.xpath('//price') 返回元素列表,直接取 .text 或 .get('attr') 即可映射到字典字段document.evaluate('//input[@type="hidden"]', doc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null) 可批量提取表单隐藏域 就填 "unknown"),XPath 本身做不到,得靠宿主语言(Python/JS)兜底处理当映射逻辑涉及合并多个 XML 文件、按业务规则重排嵌套结构、需要强类型转换(如把字符串日期转为 xs:date)、或输出格式必须严格符合另一个 Schema 时,XQuery 才显出不可替代性。
例如,把三个不同来源的订单 XML 合并成统一格式,并过滤掉 status = "cancelled" 的记录:
for $o in doc("orders1.xml")//order,
$o2 in doc("orders2.xml")//order,
$o3 in doc("orders3.xml")//o
rder
let $all := ($o, $o2, $o3)
where $all/status != "cancelled"
return
{xs:decimal($all/total)}
{xs:date($all/date)}
这段代码依赖 XQuery 的文档加载(doc())、类型强制(xs:decimal)、以及 FLWOR 的聚合能力——XPath 完全无法完成。
同一个表达式在不同环境结果可能不同,根源常在于版本错配:
//node[1] 在 XPath 1.0 中匹配“每个父节点下的第一个 node”,在 XPath 2.0+(也是 XQuery 1.0+ 基础)中才表示“整个文档中第一个 node”——很多旧系统默认只支持 1.0replace()、tokenize()),但 Python lxml 默认只支持 XPath 1.0,调用 replace() 会直接报 Invalid expression
etree.XPathEvaluator(..., namespaces={'x': 'http://ns'})),XQuery 则用 declare namespace x = "http://ns",漏写就会查不到任何节点实际选型时,先确认目标平台支持的 XPath 版本和是否内置 XQuery 引擎;如果只是从 Spring Boot 的 @XPathParam 注解里取值,那永远只和 XPath 1.0 打交道——XQuery 再强大也用不上。