Как выбрать указанный узел в наборах узлов Xpath по индексу с Selenium? - PullRequest
78 голосов
/ 09 сентября 2010

Я пишу тестовый сценарий Selenium. А вот выражение xpath, которое я использую для сопоставления всех кнопок «Изменить» в таблице данных.

//img[@title='Modify']

У меня вопрос, как я могу посетить сопоставленные наборы узлов по индексу? Я пробовал с

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

и

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

Но ни один не работает .. Я также пытался с XPath Checker (одно расширение Firefox). Всего найдено 13 совпадений, и я понятия не имею, как выбрать один из них .. Или XPath поддерживает указанный выбор узлов, которые не находятся под одним родительским узлом?

Ответы [ 6 ]

168 голосов
/ 09 сентября 2010

Это часто задаваемые вопросы :

//someName[3]

означает : все someName элементы в документе, которые являются третьим someName дочерним элементом ихparent - таких элементов может быть много.

То, что вы хотите, это точно третий someName элемент :

(//someName)[3]

Пояснение : [] имеет более высокий приоритет (приоритет), чем //.Не забывайте всегда заключать выражения типа //someName в скобки, когда вам нужно указать N-й узел их выбранного списка узлов.

14 голосов
/ 09 сентября 2010

В XPath нет i.

Либо вы используете буквенные числа: //img[@title='Modify'][1]

Или вы строите строку выражения динамически: '//img[@title='Modify']['+i+']' (но имейте в виду, что динамические выражения XPath не работают с в XSLT).

Или XPath поддерживает указанный выбор узлов которые не находятся под тем же родительским узлом?

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


Это //img[@title='Modify'][i] означает «любой <img> с заголовком« Изменить »и дочерним элементом с именем <i>

2 голосов
/ 09 сентября 2010
//img[@title='Modify'][i]

- это сокращение от

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

, поэтому он возвращает i-й узел под тем же родительским узлом.

Вы хотите

/descendant-or-self::img[@title='Modify'][i]
1 голос
/ 20 августа 2018

Там нет i в xpath не совсем верно. Вы все еще можете использовать 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 в обеих таблицах.

Предполагая, что пользователь должен выбрать 4-ю кнопку 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

Примечание: Индекс начинается с 0

  1. Получить строки для соответствующего заголовка, используя //th[.='Heading 4']/ancestor::thead/following-sibling::tbody/tr/td[count(//tr/th[.='Heading 4']/preceding-sibling::th)+1]

  2. Получить кнопку Modify из извлеченного списка узлов, используя //th[.='Heading 4']/ancestor::thead/following-sibling::tbody/tr/td[count(//tr/th[.='Heading 4']/preceding-sibling::th)+1]/button

1 голос
/ 22 апреля 2017

(// * [@ атрибут = 'значение']) [индекс] найти цель элемента, пока вы находите в нем несколько совпадений

0 голосов
/ 26 июня 2019

Вот решение для индексной переменной

Допустим, вы нашли 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]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...