Nokogiri使用含圆括号的XPath解析XML报无效表达式错误
Nokogiri执行XPath表达式报无效表达式错误解决方案
问题复现
使用的测试XML内容如下:
<casting> <CASTPARTICIPANT> <person> <PERSON fullname="John" name="Wick" firstname="John Wick"> <pe_functions/> </PERSON> </person> <function> <FUNCTION function="Productor"/> </function> </CASTPARTICIPANT> <CASTPARTICIPANT> <person> <PERSON fullname="John Wade" name="Wade" firstname="John"> </PERSON> </person> <function> <FUNCTION function="Actor / Principal"/> </function> </CASTPARTICIPANT> <CASTPARTICIPANT> <person> <PERSON fullname="Benjamin Franklyn" name="Franklyn" firstname="Benjamin"> </PERSON> </person> <function> <FUNCTION function="Realizer"/> </function> </CASTPARTICIPANT> </casting>
执行以下代码时抛出Invalid expression错误:
doc.xpath("//@name[../../../function/FUNCTION/starts-with(@function,'Actor')]")
测试过程中发现的现象:
- 上述报错的XPath表达式可在在线XPath测试站点正常运行
- 执行简化版表达式
doc.xpath("//@name[../../../function/FUNCTION/@function]")可正常返回结果 - 表达式
//@name[../../../function/FUNCTION/(@function)]同样可在在线XPath测试站点正常运行,但在Nokogiri中会抛出相同的无效表达式错误 - 初步判断报错与表达式中的圆括号、函数调用位置有关
根本原因
Nokogiri底层默认依赖libxml2引擎,仅支持XPath 1.0语法。报错的表达式属于XPath 2.0+支持的语法:在路径步(path step)位置直接放置函数调用、或在路径中用圆括号包裹属性选择,都不符合XPath 1.0的语法规范,因此会被判定为无效表达式。
修复方案
调整XPath写法适配XPath 1.0规范即可,推荐两种可直接运行的写法:
- 修正原表达式的谓词位置,把函数判断放到对应节点的筛选方括号内,保留原相对路径逻辑:
doc.xpath("//@name[../../../function/FUNCTION[starts-with(@function,'Actor')]]") - 优化路径写法,从顶层匹配节点开始筛选,不用多层向上回溯,可读性和稳定性更高:
doc.xpath("//CASTPARTICIPANT[function/FUNCTION[starts-with(@function, 'Actor')]]/person/PERSON/@name")
两种写法执行后都会正确返回匹配结果:name="Wade"(对应职位为Actor的参演人员John Wade的name属性)。
内容的提问来源于stack exchange,提问作者José Daniel Rodríguez Sánchez
相关产品推荐
相关产品推荐

