You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用XPath匹配前后元素均满足条件的XML元素

XPath筛选相邻元素问题排查与修正

原始XML文档

<root>
  <tok lemma="per" xpos="SPS00">per</tok>
  <tok lemma="els" xpos="L3CP0">los</tok>
  <tok lemma="qual" xpos="PR0CP000">quals</tok>
  <tok lemma="ser" xpos="VSIP3P0">són</tok>
  <tok lemma="digne" xpos="AQ0CP00">dignes</tok>
  <tok lemma="de" xpos="SPC00">de</tok>
  <tok lemma="gloriós" xpos="AQ0FS00">gloriosa</tok>
  <tok lemma="memòria" xpos="NCFS000">memòria</tok>
  <tok xpos="CC" lemma="i">e</tok>
  <tok lemma="li" xpos="L3CSD" >li</tok>
  <tok lemma="plàcia" xpos="VMSP3S0">plàcia</tok>
  <tok lemma="molt" xpos="RG">molt</tok>
  <tok lemma="per" xpos="SPS00">per</tok>
</root>

尝试的XPath表达式

//tok[starts-with(@xpos, "L")]/preceding-sibling::tok[1][not(starts-with(@xpos, "V"))]/following-sibling::tok[1][not(starts-with(@xpos, "V"))]

预期与实际结果

  • 预期结果:仅匹配<tok lemma="els" xpos="L3CP0">los</tok>(即前后相邻元素的xpos都不以V开头、自身xpos以L开头的tok)
  • 实际结果:匹配到两个元素:
    <tok lemma="els" xpos="L3CP0">los</tok>
    <tok lemma="li" xpos="L3CSD">li</tok>
    

原XPath错误原因

原表达式的筛选逻辑链条完全偏离了需求:它先找xpos以L开头的节点,取其前一个符合条件的兄弟节点,再从这个前兄弟节点取后一个符合条件的节点。这里的后节点判断是基于前兄弟的视角,完全没检查原L开头节点的后兄弟属性。

比如对<tok lemma="li" xpos="L3CSD">li</tok>来说,它的前兄弟xpos不以V开头,从该前兄弟取后一个节点就是li本身,此时判断的是li自己的xpos而非它的后兄弟,所以错误被选中。

修正后的XPath

直接对目标节点同时校验前后相邻兄弟的属性,表达式如下:

//tok[
  starts-with(@xpos, "L") 
  and not(starts-with(preceding-sibling::tok[1]/@xpos, "V")) 
  and not(starts-with(following-sibling::tok[1]/@xpos, "V"))
]

逻辑说明

这个表达式对每个tok做三重校验:

  1. 当前节点xpos以L开头;
  2. 前一个相邻兄弟节点的xpos不以V开头;
  3. 后一个相邻兄弟节点的xpos不以V开头。

执行后只会匹配到<tok lemma="els" xpos="L3CP0">los</tok>,完全符合预期。


内容的提问来源于stack exchange,提问作者jfontana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 13:01:25