XPath中|运算符未按预期生效的技术问题求助
XPath优先级提取前序兄弟/祖先节点@id的正确写法
需求说明
作为XPath新手,需要提取目标节点的前序兄弟节点的@id属性;若不存在该兄弟节点,则提取其祖先节点的@id。
目标XML
<?xml version="1.0" encoding="utf-8"?> <root> <parent class="InfoType01" id="1"> <p>11</p> <node class="InfoType01" id="2"> <p>22</p> </node> <node class="InfoType01" id="3"> <p>33</p> </node> </parent> </root>
原表达式问题
原使用的XPath表达式:
//node[contains(p, '33')]/preceding-sibling::node[@class='InfoType01'][1]/@id | //node[contains(p, '33')]/ancestor::*[@class='InfoType01']/@id
两个表达式单独执行均正常,但合并后无论第一个表达式是否有结果,都会返回第二个表达式的结果。这是因为误解了|运算符的作用:XPath中的|是节点集合并运算符,会将两个表达式的结果合并去重,而非短路判断(仅第一个无结果时执行第二个)。
正确解决方案
方案1:XPath 2.0+ 支持的if-else逻辑
利用XPath 2.0及以上版本的条件判断语法,实现短路逻辑:
if (//node[contains(p, '33')]/preceding-sibling::node[@class='InfoType01'][1]) then //node[contains(p, '33')]/preceding-sibling::node[@class='InfoType01'][1]/@id else //node[contains(p, '33')]/ancestor::*[@class='InfoType01']/@id
方案2:兼容XPath 1.0的写法
通过给第二个表达式添加条件,仅当目标节点没有符合要求的前序兄弟时才执行:
//node[contains(p, '33')]/preceding-sibling::node[@class='InfoType01'][1]/@id | //node[contains(p, '33')][not(preceding-sibling::node[@class='InfoType01'])]/ancestor::*[@class='InfoType01']/@id
这样合并后,只会返回前序兄弟的@id(存在时),或祖先节点的@id(无前序兄弟时)。
内容的提问来源于stack exchange,提问作者I0sens
相关产品推荐
相关产品推荐

