查找带有文本的元素,然后在其上方的许多级别中选择元素

Posted

技术标签:

【中文标题】查找带有文本的元素,然后在其上方的许多级别中选择元素【英文标题】:Find Element with Text, then Select Element Many Levels Above it 【发布时间】:2021-10-05 00:14:54 【问题描述】:

我正在制作一个删除网站部分的 chrome 扩展程序。为此,我需要找到一个包含一些文本的<span>,然后选择包含<div> 的标签。通常这个标签会在 DOM 中的 span 之上很多层,并且它没有一致的属性可供选择。

html

<body>
  <div> <!-- I want to select this DIV -->
    <div>
        <div>
            <div>
                <span>some text</span>
             </div>
         </div>
    </div>
  </div>
</body>

我使用//span[text() = 'some text' 找到了正确的&lt;span&gt;,但现在我需要回到示例HTML 中的第一个&lt;div&gt;

试过//*[ancestor::span[text() = 'some text']]//span[ancestor::*[text() = 'some text']]。是的,这些只会上升到第一个父级,但这甚至对我不起作用,即使当我在 XPath Tester 上测试时它们作为有效的 XPath 表达式出现。

编写可以做到这一点的 XPath 表达式的最简单方法是什么?

【问题讨论】:

【参考方案1】:

您可以尝试使用 ../ 语法上一级(即:到直接父级)并像这样链接它们:

const getnodes=function( expr, parent )
        let results=[];
        let contextNode=parent || document;
        let query=document.evaluate( expr, contextNode, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );
        for ( let i=0, length=query.snapshotLength; i < length; ++i ) 
            results.push( query.snapshotItem( i ) );
        
        return results;
    ;
  
  let col=getnodes( '//span[ text()="some text" ]/../../../../../div', document.body );
  col.forEach( n=>console.info( n.textContent ) )
<!--This is the div I want to select -->
  <div>top
    <div>a
        <div>b
            <div>c
                <span>some text</span>
             </div>
         </div>
    </div>
  </div>

【讨论】:

【参考方案2】:

我发现一个更好的解决方案是在 XPath 查询中使用 ancestor,因为我经常想要向上遍历多个级别。

例子

//span[text() = 'some text']/ancestor::*[4]

从所选跨度中选择第四个元素,无论这些元素可能是什么类型。

//span[text() = 'some text']/ancestor::a[2]

将从所选跨度向上查找第二个锚标记,前提是它是该跨度的直接升序。

【讨论】:

以上是关于查找带有文本的元素,然后在其上方的许多级别中选择元素的主要内容,如果未能解决你的问题,请参考以下文章

Word VBA查找某种颜色的文本并在其前面插入一个空格

Twitter Bootstrap 按钮单击以切换按钮上方的展开/折叠文本部分

jquery 选中文本框 jquery 文本框样式 jquery 改变样式

在找到的文本上方查找指定的文本

在辅助功能模式下未检测到手势

无法在具有相同元素的 viewController 上方的模式上断言元素