ChatGPT解决这个技术问题 Extra ChatGPT

如何使用 Selenium 通过索引选择 Xpath 节点集中的指定节点?

我正在写一个 Selenium 测试用例。这是我用来匹配数据表中所有“修改”按钮的 xpath 表达式。

//img[@title='Modify']

我的问题是,如何按索引访问匹配的节点集?我试过了

//img[@title='Modify'][i]

//img[@title='Modify' and position() = i]

但两者都不起作用..我也尝试过使用 XPath 检查器(一个 firefox 扩展)。总共找到 13 个匹配项,然后我完全不知道如何选择其中一个。或者 XPath 是否支持指定选择不在同一个父节点下的节点?


D
Dimitre Novatchev

这是一个常见问题解答:

//someName[3]

表示:文档中的所有 someName 元素,它们是其父级的第三个 someName 子级 - 可能有很多这样的元素。

您想要的正是第三个 someName 元素

(//someName)[3]

解释[] 的优先级(优先级)高于 //。当您需要指定所选节点列表的第 N 个节点时,请记住始终将 //someName 类型的表达式放在括号中。


非常感谢!抱歉,我完全忘记了优先事项..我只是尝试过,它有效!
@Kymair-Wu:我很高兴这个答案对你有用。在 SO 中,表达感谢的方式是接受答案(提示:单击答案旁边的复选标记)。 :)
@Eytoss,不客气。是的,对于相对简单的答案,我得到的 +1 最多——而不是我认为是我最大成就的答案——可能是因为每个人都理解前者,而几乎没有人理解后者 :)
@TEHEMPRAH,实际上我在答案中看到我没有说“其父母的第三个'someName'孩子”。感谢您注意到这一点。现已更正。
“还要注意,index values in XPath predicates (technically, 'proximity positions' of XPath node sets) start from 1,而不是像 C 和 Java 这样的语言中常见的 0。”
T
Tomalak

XPath 中没有 i

您要么使用文字数字://img[@title='Modify'][1]

或者您动态构建表达式字符串:'//img[@title='Modify']['+i+']'(但请记住,动态 XPath 表达式在 within XSLT 中不起作用)。

或者 XPath 是否支持指定选择不在同一个父节点下的节点?

是:(//img[@title='Modify'])[13]

//img[@title='Modify'][i] 表示“任何具有“修改”标题和名为 <i> 的子元素的 <img>


出于某种原因,我需要在属性表达式之前包含索引。例如,要查找 tr 的第六个子元素且没有空内容的 td//tr/td[6][string-length(text()) > 0]
@kopranb 有关解释,请参阅此答案 stackoverflow.com/a/1006439/18771
感谢您解释 '//img[@title='Modify']['+i+']' (+1)
E
Eric Stanley

xpath 中没有 i 并不完全正确。您仍然可以使用 count() 来查找索引。

考虑以下页面

HTML 示例表格

< td>数据行 5 col 5
标题 1 标题 2 标题 3 标题 4< /th> 标题 5 标题 6
数据行 1 col 1 数据行 1 col 2 数据行 1 col 3 数据行 1 col 4 数据行 1 col 5 数据行1 col 6
数据行 2 col 1 数据行 2 col 2 数据行 2 col 3 数据行 2 col 4 数据行 2 col 5 数据行 2 col 6
数据行 3 col 1 数据行 3 col 2 数据行 3 col 3 数据行 3 col 4 数据行 3 col 5< /td> 数据行 3 col 6
数据行 4 col 1 数据行 4 col 2 数据第 4 行第 3 列 数据第 4 列第 4 列 数据第 4 列第 5 列 数据第 4 列第 6 列
数据行 5 col 1 数据行 5 col 2 数据行 5 col 3 数据行 5 col 4 数据行 5 col 6< /td>

< td>数据行 3 col 5 < td>数据行 5 col 6
标题 7 标题 8 标题 9 标题 10 标题 11 标题 12
数据行 1 列1 数据行 1 col 2 数据行 1 col 3 数据行 1 col 4 数据行 1 col 5< /td> 数据行 1 col 6
数据行 2 col 1 数据行 2 col 2 数据第 2 行第 3 列 数据第 2 列第 4 列 数据第 2 列第 5 列 数据第 2 列第 6 列
数据行 3 col 1 数据行 3 col 2 数据行 3 col 3 数据行 3 col 4 数据行 3 col 6
数据行 4 col 1 数据行 4 col 2 数据行 4 col 3 数据行w 4 col 4 数据行 4 col 5 数据行 4 col 6
数据行 5 col 1 数据行 5 col 2 数据行 5 col 3 数据行 5 col 4 数据行 5 col 5

该页面有 2 个表,每列有 6 列,每列都有唯一的列名,6 行有可变数据。最后一行在两个表中都有 Modify 按钮。

假设用户必须根据标题从第一个表中选择第四个 Modify 按钮

使用 xpath //th[.='Heading 4']/ancestor::thead/following-sibling::tbody/tr/td[count(//tr/th[.='Heading 4']/preceding-sibling::th)+1]/button

count() 运算符在此类情况下会派上用场。

逻辑:

使用 //th[.='Heading 4'] 查找 Modify 按钮的标题 使用 count(//tr/th[.='Heading 4']/preceding-sibling::th) 查找标题列的索引+1

注意:索引从 0 开始

使用 //th[.='Heading 4']/ancestor::thead/following-sibling::tbody/tr/td[count(//tr/th[.='Heading 4' ]/preceding-sibling::th)+1] 使用 //th[.='Heading 4']/ancestor::thead/following-sibling::tbody/tr/td[ 从提取的节点列表中获取修改按钮count(//tr/th[.='标题 4']/preceding-sibling::th)+1]/button


多谢!我使用它,但每次我都没有标题时,我来到 td[count(../preceding-sibling::tr/th[.='Heading 4'])]/following-sibling::td 时不属于 td[1] :)
N
Nick Jones
//img[@title='Modify'][i]

简称

/descendant-or-self::node()/img[@title='Modify'][i]

因此返回同一父节点下的第 i 个节点。

你要

/descendant-or-self::img[@title='Modify'][i]

只需 /descendant::img[@title='Modify'][$index] 即可。另请注意,[i] 谓词测试是否存在 i 子元素。
m
mahesh

(//*[@attribute='value'])[index] 查找元素的目标,同时在其中找到多个匹配项


你能再解释一下吗?
M
Maelig

这是索引变量的解决方案

假设您找到了 5 个具有相同定位器的元素,并且您希望通过提供索引号对每个元素执行操作(此处,变量用于索引为“i”)

for(int i=1; i<=5; i++)
{
    string xPathWithVariable = "(//div[@class='className'])" + "[" + i + "]";
    driver.FindElement(By.XPath(xPathWithVariable)).Click();
}

它需要 XPath :

(//div[@class='className'])[1]
(//div[@class='className'])[2]
(//div[@class='className'])[3]
(//div[@class='className'])[4]
(//div[@class='className'])[5]