在 XPath 中,我如何在两个元素之间寻找一些东西?

Posted

技术标签:

【中文标题】在 XPath 中,我如何在两个元素之间寻找一些东西?【英文标题】:In XPath, how do i look for something between two elements? 【发布时间】:2021-11-06 04:51:21 【问题描述】:

问题: 我正在使用 Selenium 在本网站的输入字段中输入数据。 其中一个表有问题,因为它没有这些字段的唯一 ID。 我想在“name2”上的“project2”下的输入字段中输入文本。所有项目在其项目中具有相同的名称。名称可能会更改,并且将来可能会添加一些新字段。

问题: 是否可以在我在 project2 之后但同时在 project3 之前做某事的地方进行 XPATH 查询? 例如://something/preceding-sibling::tr and //something_else/following-sibling::tr

提前致谢。

示例代码:

<table border="0">
    <tr><td>project1</td><td></td></tr>
    <tr><td>name1</td><td><input type="text"></td></tr>
    <tr><td>name2</td><td><input type="text"></td></tr>
    <tr><td>name3</td><td><input type="text"></td></tr>
    <tr><td>name4</td><td><input type="text"></td></tr>

    <tr><td>project2</td><td></td></tr>
    <tr><td>name1</td><td><input type="text"></td></tr>
    <tr><td>name2</td><td><input type="text"></td></tr>
    <tr><td>name3</td><td><input type="text"></td></tr>
    <tr><td>name4</td><td><input type="text"></td></tr>

    <tr><td>project3</td><td></td></tr>
    <tr><td>name1</td><td><input type="text"></td></tr>
    <tr><td>name2</td><td><input type="text"></td></tr>
    <tr><td>name3</td><td><input type="text"></td></tr>
    <tr><td>name4</td><td><input type="text"></td></tr>
</table>

截图:

【问题讨论】:

【参考方案1】:

你可以试试下面的xpath:

//td[text()='project2']/../following-sibling::tr[2]/descendant::input

更新:

如果td[2] 是问题,那么可能使用这个:

//td[text()='project2']/../following-sibling::*/td[text()='name2']/following-sibling::td/input

甚至是下面的一个:

(//*[text()='project2']/../following-sibling::*/*[text()='name2'])[1]/following-sibling::td/input

【讨论】:

是的,这可能会起作用,但问题是如果他们在两者之间添加另一个字段,对吗?但如果以其他方式不可能,这是一个很好的候选。 见上文,稍作修改。不推荐最后一个,但即使他们添加更多 trtd,最后一个也会起作用 我会推荐使用这个//td[text()='project2']/../following-sibling::*/td[text()='name2']/following-sibling::td/input,因为即使它有多个匹配节点,Selenium find_element 总是会选择第一个【参考方案2】:

这会给你你想要的:

//tr[preceding-sibling::tr[td[.="project2"]]][not(preceding-sibling::tr[td[.="project3"]])][td[.="name2"]]/td/input

上面将找到所有&lt;tr&gt; 元素:

    &lt;tr&gt; 元素之后出现,该元素包含&lt;td&gt; 和文本“project2” -> [preceding-sibling::tr[td[.="project2"]]] 位于&lt;tr&gt; 元素之前,该元素包含带有文本“project3”的&lt;td&gt; -> [not(preceding-sibling::tr[td[.="project3"]])] 带有&lt;td&gt; 元素,其中包含文本“name2” -> [td[.="name2"]]

然后它将深入到该行中&lt;td&gt; 元素内的&lt;input&gt; 元素。

【讨论】:

project 3hardcoded,如果他们添加 project4project5 甚至将项目 3 名称更改为其他名称会怎样? 如果产品 4 出现在项目 3 之后,则不会发生任何事情。这是在名为 project 2 和 project 3 的行之间搜索一行。如果在 project 2 和 project 3 之间添加了 project 4,它将不再解析为单个元素,而是基于标记当前布局的方式是奇怪和不寻常的行为。如果(在这种情况下)您正在检查使用我提供的 XPath 返回了多少输入字段,您会得到一个快速而清晰的指示,表明这个新标记是奇怪/错误的。 另外值得指出的是,如果项目 4 位于项目 2 和项目 3 之间,如果您使用基本的 .findElement() 调用,您仍然会获得预期的元素,因为它会拾取它找到的第一个节点。如果项目 4 放在项目 2 之前,它将被忽略,因为它不在项目 2 和项目 3 之间。 如果项目 3 的名称被更改为其他名称,您将在项目 2 之后获得所有输入字段,但如果您使用基本的 .findElement() 调用,它将再次选择找到的第一个节点. 虽然所有这一切都没有实际意义,但如果标记发生重大变化,大多数复杂的 XPath 都会中断,这就是为什么人们建议向元素添加 ID 以使其易于查找并避免使用基于 XPath 的需要标记结构。

以上是关于在 XPath 中,我如何在两个元素之间寻找一些东西?的主要内容,如果未能解决你的问题,请参考以下文章

如何在WebElement中通过xpath查找子元素

更改 XPath 表达式中的元素名称

我们如何使用没有标签名称的 xpath 查找元素? [复制]

是否可以通过 Xpath 在 Robot Framework 中同时等待两个 Web 元素?

如何在两个 MongoDB 数据库之间同步一些集合?

使用 XPath 和 Selenium for Java 获取下一个兄弟元素