Selenium으로 인덱스별로 Xpath 노드 세트 내에서 지정된 노드를 선택하는 방법은 무엇입니까?


92

Selenium 테스트 케이스를 작성 중입니다. 다음은 데이터 테이블 내의 모든 '수정'버튼과 일치하는 데 사용하는 xpath 표현식입니다.

//img[@title='Modify']

내 질문은 인덱스별로 일치하는 노드 세트를 어떻게 방문 할 수 있습니까? 나는 시도했다

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

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

하지만 둘 다 작동하지 않습니다 .. 또한 XPath 검사기 (하나의 firefox 확장)를 사용해 보았습니다. 13 개의 일치 항목이 발견되었는데 그중 하나를 어떻게 선택해야할지 전혀 모릅니다. 아니면 XPath가 동일한 부모 노드 아래에 있지 않은 특정 노드 선택을 지원합니까?

답변:


193

이것은 FAQ입니다 :

//someName[3]

의미 : someName문서의 모든 요소, 즉 someName부모 의 세 번째 하위 요소-그러한 요소가 많을 수 있습니다.

원하는 것은 정확히 세 번째 someName요소입니다 .

(//someName)[3]

설명 :이 ( []가)보다 우선 순위 (우선 순위)가 높습니다 //. //someName선택한 노드 목록의 N 번째 노드를 지정해야 할 때 항상 유형의 표현식을 괄호로 묶어야합니다.


1
정말 고마워! 우선 순위를 잊어 버려서 미안해 .. 방금 시도했는데 작동합니다!
Kymair Wu

1
@ Kymair-Wu :이 답변이 도움이되어 기쁩니다. 여기에서 감사를 표현하는 방법은 답변을 받아들이는 것입니다 (힌트 : 답변 옆에있는 체크 표시를 클릭하십시오). :)
Dimitre Novatchev

@DimitreNovatchev 당신은 같은 질문에 대해 계속해서 포인트를 얻고 있습니다 : p, FAQ에 감사드립니다.
Eytoss 2012 년

2
@Eytoss, 천만에요. 그리고 네, 나는 비교적 간단한 답변을 가장 +1을 얻고있다 - 아니 내 가장 큰 성과 믿고 있다는 답변 - : 아마 모두가 전자를 이해하기 때문에 거의 아무도 후자를 이해하지
Dimitre Novatchev

2
@TEHEMPRAH, 사실 나는 대답에서 "부모의 세 번째 'someName'자식"이라고 말하지 않은 것을 보았습니다. 알아 주셔서 감사합니다. 지금 수정되었습니다.
Dimitre Novatchev 2015 년

14

iXPath 에는 없습니다 .

리터럴 숫자를 사용하십시오. //img[@title='Modify'][1]

또는 표현식 문자열을 동적으로 빌드합니다. '//img[@title='Modify']['+i+']'그러나 동적 XPath 표현식은 XSLT 내에서 작동하지 않습니다 .

아니면 XPath가 동일한 부모 노드 아래에 있지 않은 특정 노드 선택을 지원합니까?

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


이는 //img[@title='Modify'][i]" <img>제목이 '수정'이고 하위 요소가 인 모든 항목"을 의미합니다 <i>.


어떤 이유로 속성 표현식 앞에 색인을 포함해야했습니다. 예를 들어, 찾을 수 tda의 여섯 번째 어렸을들 tr과 빈 내용이없는 ://tr/td[6][string-length(text()) > 0]
사미르 Aguiar

1
@kopranb에 대한 설명이 응답 참조 stackoverflow.com/a/1006439/18771
Tomalak

'// img [@ title ='Modify '] ['+ i + ']'(+1)에 대해 설명해 주셔서 감사합니다
DebanjanB

3

더 없다 iXPath는에 완전히 사실이 아니다. 여전히를 사용 count()하여 색인을 찾을 수 있습니다 .

다음 페이지를 고려하십시오

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

이 페이지에는 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

참고 : 색인은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


감사합니다! 나는 그것을 사용하지만, 나는 내가 어떤 제목이 없을 때마다 td[count(../preceding-sibling::tr/th[.='Heading 4'])]/following-sibling::td속하지 td[1]않는다 :)
마니

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

의 약자

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

따라서 동일한 부모 노드 아래에서 i 번째 노드를 반환합니다.

원하는

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

1
그냥은 /descendant::img[@title='Modify'][$index]잘 작동합니다. 또한 하위 요소의 [i]존재에 대한 술어 테스트에 유의하십시오 i.

1

(// * [@ attribute = 'value']) [index]는 요소에서 여러 일치 항목을 찾는 동안 요소의 대상을 찾습니다.


1
좀 더 설명해 주 시겠어요?
abhiarora

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]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.