Làm thế nào để chọn nút được chỉ định trong tập hợp nút Xpath theo chỉ mục với Selenium?


91

Tôi đang viết một testcase Selenium. Và đây là biểu thức xpath mà tôi sử dụng để khớp với tất cả các nút 'Sửa đổi' trong bảng dữ liệu.

//img[@title='Modify']

Câu hỏi của tôi là, làm cách nào tôi có thể truy cập các tập hợp nút phù hợp theo chỉ mục? Tôi đã thử với

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

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

Nhưng cả hai đều không hoạt động .. Tôi cũng đã thử với trình kiểm tra XPath (Một phần mở rộng firefox). Có tổng cộng 13 kết quả phù hợp được tìm thấy, sau đó tôi hoàn toàn không biết mình sẽ chọn một trong số chúng như thế nào .. Hay XPath có hỗ trợ lựa chọn cụ thể của các nút không nằm trong cùng một nút cha?

Câu trả lời:


190

Đây là câu hỏi thường gặp :

//someName[3]

có nghĩa là : tất cả các someNamephần tử trong tài liệu, là phần tử someNamecon thứ ba của cha mẹ chúng - có thể có nhiều phần tử như vậy.

Điều bạn muốn chính xác là someNameyếu tố thứ 3 :

(//someName)[3]

Giải thích : cái []có mức độ ưu tiên cao hơn (ưu tiên) hơn //. Hãy nhớ luôn đặt các biểu thức của kiểu //someNametrong dấu ngoặc khi bạn cần chỉ định nút thứ N của danh sách nút đã chọn của chúng.


1
Cám ơn rất nhiều! Xin lỗi, tôi hoàn toàn quên những thứ ưu tiên .. Tôi vừa thử và nó hoạt động!
Kymair Wu 10/09/10

1
@ Kymair-Wu: Tôi rất vui vì câu trả lời này hữu ích với bạn. Ở đây SO, cách thể hiện lòng biết ơn là chấp nhận một câu trả lời (gợi ý: nhấp vào dấu kiểm bên cạnh câu trả lời). :)
Dimitre Novatchev

@DimitreNovatchev, bạn đang nhận được điểm cho cùng một câu hỏi lặp đi lặp lại: p, cảm ơn vì Câu hỏi thường gặp.
Eytoss 29/10/12

2
@Eytoss, Bạn được chào đón. Và vâng, tôi nhận được hầu hết + 1s cho câu trả lời tương đối đơn giản - không phải cho những câu trả lời mà tôi tin là những thành tựu lớn nhất của tôi - có lẽ vì tất cả mọi người hiểu được cựu và hầu như không ai hiểu sau này :)
Dimitre Novatchev

2
@TEHEMPRAH, Trên thực tế, tôi thấy rằng trong câu trả lời, tôi không nói "đứa con thứ 3 'someName' của cha mẹ nó". Cảm ơn vì đã nhận thấy điều này. Đã sửa ngay bây giờ.
Dimitre Novatchev

14

Không có itrong XPath.

Hoặc bạn sử dụng số chữ: //img[@title='Modify'][1]

Hoặc bạn xây dựng chuỗi biểu thức động: '//img[@title='Modify']['+i+']'(nhưng hãy nhớ rằng các biểu thức XPath động không hoạt động từ bên trong XSLT).

Hoặc XPath có hỗ trợ lựa chọn cụ thể của các nút không nằm trong cùng một nút cha không?

Đúng: (//img[@title='Modify'])[13]


Điều này //img[@title='Modify'][i]có nghĩa là "bất kỳ <img>có tiêu đề 'Sửa đổi' và một phần tử con được đặt tên <i>."


Vì một số lý do, tôi cần đưa chỉ mục vào trước biểu thức thuộc tính. Ví dụ: để tìm tds là con thứ sáu của a trvà không có nội dung trống://tr/td[6][string-length(text()) > 0]
Samir Aguiar

1
@kopranb Để có lời giải thích, hãy xem câu trả lời này stackoverflow.com/a/1006439/18771
Tomalak

Cảm ơn bạn đã giải thích về '// img [@ title =' Modify '] [' + i + ']' (+1)
DebanjanB

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

là viết tắt của

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

do đó trả về nút thứ i dưới cùng một nút cha.

Bạn muốn

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

1
Chỉ cần /descendant::img[@title='Modify'][$index]sẽ hoạt động tốt. Cũng lưu ý rằng [i]kiểm tra vị từ về sự tồn tại của iphần tử con.

2

Không có itrong xpath là không hoàn toàn đúng. Bạn vẫn có thể sử dụng count()để tìm chỉ mục.

Xem xét trang sau

<html>

	<head>
		<title>HTML Sample table</title>
	</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>

	<body>
	<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>

	</body>
</html>

Trang có 2 bảng và mỗi bảng có 6 cột với tên cột duy nhất và 6 hàng với dữ liệu biến đổi. Hàng cuối cùng có Modifynút trong cả hai bảng.

Giả sử rằng người dùng phải chọn Modifynút thứ 4 từ bảng đầu tiên dựa trên tiêu đề

Sử dụng xpath //th[.='Heading 4']/ancestor::thead/following-sibling::tbody/tr/td[count(//tr/th[.='Heading 4']/preceding-sibling::th)+1]/button

Nhà count()điều hành có ích trong những tình huống như thế này.

Hợp lý:

  1. Tìm tiêu đề cho Modifynút bằng cách sử dụng//th[.='Heading 4']
  2. Tìm chỉ mục của cột tiêu đề bằng cách sử dụng count(//tr/th[.='Heading 4']/preceding-sibling::th)+1

Lưu ý: Chỉ mục bắt đầu lúc0

  1. Lấy các hàng cho tiêu đề tương ứng bằng cách sử dụng //th[.='Heading 4']/ancestor::thead/following-sibling::tbody/tr/td[count(//tr/th[.='Heading 4']/preceding-sibling::th)+1]

  2. Lấy Modifynút từ danh sách nút được trích xuất bằng cách sử dụng//th[.='Heading 4']/ancestor::thead/following-sibling::tbody/tr/td[count(//tr/th[.='Heading 4']/preceding-sibling::th)+1]/button


1

(// * [@ thuộc tính = 'value']) [index] để tìm mục tiêu của phần tử trong khi bạn tìm nhiều kết quả phù hợp trong đó


1
Bạn có thể giải thích thêm một chút không?
abhiarora

0

Đây là giải pháp cho biến chỉ mục

Giả sử, bạn đã tìm thấy 5 phần tử có cùng bộ định vị và bạn muốn thực hiện hành động trên mỗi phần tử bằng cách cung cấp số chỉ mục (ở đây, biến được sử dụng cho chỉ mục là "i")

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

Nó mất XPath:

(//div[@class='className'])[1]
(//div[@class='className'])[2]
(//div[@class='className'])[3]
(//div[@class='className'])[4]
(//div[@class='className'])[5]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.