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

时间:2010-09-09 07:27:37

标签: xpath selenium

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

//img[@title='Modify']

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

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

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

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

6 个答案:

答案 0 :(得分:165)

这是常见问题解答

//someName[3]

表示:文档中的所有someName元素,即其父级的第三个someName子元素 - 可能有许多此类元素。

您想要的是第3个someName元素

(//someName)[3]

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

答案 1 :(得分:14)

XPath中没有i

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

或者您动态构建表达式字符串:'//img[@title='Modify']['+i+']'(但请记住,动态XPath表达式无法在 XSLT中的中运行)。

  

或者XPath支持指定的节点选择   哪些不在同一父节点下?

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


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

答案 2 :(得分:2)

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

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

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

你想要

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

答案 3 :(得分:1)

(// * [@属性=&#39;值&#39;])[指数] 找到元素的目标,同时找到多个匹配的元素

答案 4 :(得分:1)

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

请考虑以下页面

<html>
	<head>
	<style>
	table, td, th {
		border: 1px solid black;
		font-size: 15px;
		font-family: Trebuchet MS, sans-serif;
	}
	table {
		border-collapse: collapse;
		width: 100%;
	}

	th, td {
		text-align: left;
		padding: 8px;
	}

	tr:nth-child(even){background-color: #f2f2f2}

	th {
		background-color: #4CAF50;
		color: white;
	}
	</style>
	<table>
		<thead>
			<tr>
				<th>Heading 1</th>
				<th>Heading 2</th>
				<th>Heading 3</th>
				<th>Heading 4</th>
				<th>Heading 5</th>
				<th>Heading 6</th>
			</tr>
		</thead>
		<tbody>
			<tr>
				<td>Data row 1 col 1</td>
				<td>Data row 1 col 2</td>
				<td>Data row 1 col 3</td>
				<td>Data row 1 col 4</td>
				<td>Data row 1 col 5</td>
				<td>Data row 1 col 6</td>
			</tr>
			<tr>
				<td>Data row 2 col 1</td>
				<td>Data row 2 col 2</td>
				<td>Data row 2 col 3</td>
				<td>Data row 2 col 4</td>
				<td>Data row 2 col 5</td>
				<td>Data row 2 col 6</td>
			</tr>
			<tr>
				<td>Data row 3 col 1</td>
				<td>Data row 3 col 2</td>
				<td>Data row 3 col 3</td>
				<td>Data row 3 col 4</td>
				<td>Data row 3 col 5</td>
				<td>Data row 3 col 6</td>
			</tr>
			<tr>
				<td>Data row 4 col 1</td>
				<td>Data row 4 col 2</td>
				<td>Data row 4 col 3</td>
				<td>Data row 4 col 4</td>
				<td>Data row 4 col 5</td>
				<td>Data row 4 col 6</td>
			</tr>
			<tr>
				<td>Data row 5 col 1</td>
				<td>Data row 5 col 2</td>
				<td>Data row 5 col 3</td>
				<td>Data row 5 col 4</td>
				<td>Data row 5 col 5</td>
				<td>Data row 5 col 6</td>
			</tr>
			<tr>
				<td><button>Modify</button></td>
				<td><button>Modify</button></td>
				<td><button>Modify</button></td>
				<td><button>Modify</button></td>
				<td><button>Modify</button></td>
				<td><button>Modify</button></td>
			</tr>
		</tbody>
	</table>

	</br>

	<table>
		<thead>
			<tr>
				<th>Heading 7</th>
				<th>Heading 8</th>
				<th>Heading 9</th>
				<th>Heading 10</th>
				<th>Heading 11</th>
				<th>Heading 12</th>
			</tr>
		</thead>
		<tbody>
			<tr>
				<td>Data row 1 col 1</td>
				<td>Data row 1 col 2</td>
				<td>Data row 1 col 3</td>
				<td>Data row 1 col 4</td>
				<td>Data row 1 col 5</td>
				<td>Data row 1 col 6</td>
			</tr>
			<tr>
				<td>Data row 2 col 1</td>
				<td>Data row 2 col 2</td>
				<td>Data row 2 col 3</td>
				<td>Data row 2 col 4</td>
				<td>Data row 2 col 5</td>
				<td>Data row 2 col 6</td>
			</tr>
			<tr>
				<td>Data row 3 col 1</td>
				<td>Data row 3 col 2</td>
				<td>Data row 3 col 3</td>
				<td>Data row 3 col 4</td>
				<td>Data row 3 col 5</td>
				<td>Data row 3 col 6</td>
			</tr>
			<tr>
				<td>Data row 4 col 1</td>
				<td>Data row 4 col 2</td>
				<td>Data row 4 col 3</td>
				<td>Data row 4 col 4</td>
				<td>Data row 4 col 5</td>
				<td>Data row 4 col 6</td>
			</tr>
			<tr>
				<td>Data row 5 col 1</td>
				<td>Data row 5 col 2</td>
				<td>Data row 5 col 3</td>
				<td>Data row 5 col 4</td>
				<td>Data row 5 col 5</td>
				<td>Data row 5 col 6</td>
			</tr>
			<tr>
				<td><button>Modify</button></td>
				<td><button>Modify</button></td>
				<td><button>Modify</button></td>
				<td><button>Modify</button></td>
				<td><button>Modify</button></td>
				<td><button>Modify</button></td>
			</tr>
		</tbody>
	</table>

	</head>
</html>

该页面有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()运算符会派上用场。

逻辑:

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

注意:索引从0开始

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

  2. 获取相应标题的行
  3. 使用Modify

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

答案 5 :(得分:0)

这是索引变量的解决方案

比方说,您找到了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]