了解给定数据:
获取所有行:
driver.findElements(By.xpath("//table[@id='dt']/tbody/tr"))
获取给定行的列(单元格):
row.findElements(By.tagName("td"))
获取给定列(单元格)的文本:
getTextFromElement(cell)
如果行索引单元格上的文本匹配给定的字符串(stringFirst),则预期结果:
driver.findElement(By.xpath(String.format("//table[@id='dt']/tbody/tr[%s]/td[%s]", index, integerFirst)))
从需求来看,似乎逻辑应该围绕索引。
方法细分:
首先,我们需要一个行列表。这和以前完全一样:
List<WebElement> tableRows = driver.findElements(By.xpath("//table[@id='dt']/tbody/tr"));
现在我们将创建一个包含所有索引的 IntStream。
rangeClosed 意味着结束是包容的
boxed() 用于将原始整数转换为整数
IntStream.rangeClosed(1,tableRows.size()).boxed()
1,
2,
3,
...
为每个索引idx创建一个map,idx为key,row idx对应的column为value:
.map(idx -> Map.of(idx, list.get(idx-1).findElements(By.tagName("td"))))
{1=[cell11, cell12, cell13]},
{2=[cell21, cell22, cell23]},
...
合并所有地图:
.flatMap(m -> m.entrySet().stream())
1=[cell11, cell12, cell13],
2=[cell21, cell22, cell23],
...
过滤掉不包含以文本为给定字符串的单元格的值:
如果找到任何值,findAny() 返回 Optional(不确定这是否是要求)
.filter(containsCellWithText).findAny()
上述谓词的实现:
Predicate<Map.Entry> containsCellWithText = (Map.Entry me) -> me.getValue()
.stream()
.anyMatch(cell -> getTextFromElement(cell).equals(stringFirst));
现在,只剩下所需的条目。获取对应索引的结果:
.map(me -> driver.findElement(By.xpath(String.format("//table[@id='dt']/tbody/tr[%s]/td[%s]", me.getKey(), integerFirst))))
我们应该在 Optional(如果存在)中得到答案。获取它,否则得到一个空字符串:
.orElse("")
完整答案汇总:
List<WebElement> tableRows = driver.findElements(By.xpath("//table[@id='dt']/tbody/tr"));
Predicate<Map.Entry> containsCellWithText = (Map.Entry me) -> me.getValue()
.stream()
.anyMatch(cell -> getTextFromElement(cell).equals(stringFirst));
IntStream.rangeClosed(1,tableRows.size())
.boxed()
.map(idx -> Map.of(idx, list.get(idx-1).findElements(By.tagName("td"))))
.flatMap(m -> m.entrySet().stream())
.filter(containsCellValue)
.findAny()
.map(me -> driver.findElement(By.xpath(String.format("//table[@id='dt']/tbody/tr[%s]/td[%s]", me.getKey(), integerFirst))))
.orElse("")
资源: