我想构建一个XPath查询,该查询将返回“ DIV”或“表”元素,只要它具有包含文本“ ABC”的后代。一个警告是它不能有任何Div或桌子后代。

<div>
  <table>
    <form>
      <div>
        <span>
          <p>abcdefg</p>
        </span>
      </div>
      <table>
        <span>
          <p>123456</p>
        </span>
      </table>
    </form>
  </table>
</div>

因此,此查询的唯一正确结果是:

/div/table/form/div 

我最好的尝试看起来像这样:

//div[contains(//text(), "abc") and not(descendant::div or descendant::table)] | //table[contains(//text(), "abc") and not(descendant::div or descendant::table)]

但不返回正确的结果。

谢谢你的帮助。

有帮助吗?

解决方案

有些不同: :)

//text()[contains(.,'abc')]/ancestor::*[self::div or self::table][1]

似乎比其他解决方案短得多,不是吗? :)

翻译成简单的英语: :对于文档中包含字符串的任何文本节点 "abc" 选择其第一个祖先 div 或a table.

这更有效, ,因为只需要对文档树的全面扫描(而不是其他),并且 ancestor::* 与一个相比,遍历非常便宜 descendent:: (树)扫描。

验证该解决方案“确实有效”:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/">
  <xsl:copy-of select=
  "//text()[contains(.,'abc')]/ancestor::*[self::div or self::table][1] "/>
 </xsl:template>
</xsl:stylesheet>

当在提供的XML文档上执行此转换时:

<div>
  <table>
    <form>
      <div>
        <span>
          <p>abcdefg</p>
        </span>
      </div>
      <table>
        <span>
          <p>123456</p>
        </span>
      </table>
    </form>
  </table>
</div>

想要的,正确的结果被产生:

<div>
   <span>
      <p>abcdefg</p>
   </span>
</div>

笔记: :不必使用XSLT - 任何XPATH 1.0主机 - 例如DOM,必须获得相同的结果。

其他提示

//*[self::div|self::table] 
   [descendant::text()[contains(.,"abc")]]  
   [not(descendant::div|descendant::table)]

问题 contains(//text(), "abc") 是施放第一个节点的函数铸造节点集。

您可以尝试:

//div[
  descendant::text()[contains(., "abc")] 
  and not(descendant::div or descendant::table)
] | 
//table[
  descendant::text()[contains(., "abc")] 
  and not(descendant::div or descendant::table)
]

这有帮助吗?

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top