在 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
【讨论】:
是的,这可能会起作用,但问题是如果他们在两者之间添加另一个字段,对吗?但如果以其他方式不可能,这是一个很好的候选。 见上文,稍作修改。不推荐最后一个,但即使他们添加更多tr
或 td
,最后一个也会起作用
我会推荐使用这个//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
上面将找到所有<tr>
元素:
-
在
<tr>
元素之后出现,该元素包含<td>
和文本“project2” -> [preceding-sibling::tr[td[.="project2"]]]
位于<tr>
元素之前,该元素包含带有文本“project3”的<td>
-> [not(preceding-sibling::tr[td[.="project3"]])]
带有<td>
元素,其中包含文本“name2” -> [td[.="name2"]]
然后它将深入到该行中<td>
元素内的<input>
元素。
【讨论】:
project 3
是 hardcoded
,如果他们添加 project4
或 project5
甚至将项目 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 中,我如何在两个元素之间寻找一些东西?的主要内容,如果未能解决你的问题,请参考以下文章
我们如何使用没有标签名称的 xpath 查找元素? [复制]