วิธีการเลือกโหนดที่ระบุภายในโหนด Xpath กำหนดโดยดัชนีด้วยซีลีเนียม


92

ฉันกำลังเขียนแบบทดสอบซีลีเนียม นี่คือนิพจน์ xpath ที่ฉันใช้เพื่อจับคู่ปุ่ม 'แก้ไข' ทั้งหมดภายในตารางข้อมูล

//img[@title='Modify']

คำถามของฉันคือฉันจะไปที่โหนดที่ตรงกันที่กำหนดโดยดัชนีได้อย่างไร ฉันได้ลองกับ

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

และ

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

แต่ก็ไม่ได้ผล .. ฉันลองใช้ XPath checker ด้วย (ส่วนขยาย Firefox ตัวเดียว) พบการแข่งขันทั้งหมด 13 รายการแล้วฉันไม่รู้เลยว่าฉันจะเลือกหนึ่งในนั้นได้อย่างไร .. หรือ XPath รองรับการเลือกโหนดที่ระบุซึ่งไม่อยู่ภายใต้โหนดหลักเดียวกัน?

คำตอบ:


194

นี่คือคำถามที่พบบ่อย :

//someName[3]

หมายถึง : someNameองค์ประกอบทั้งหมดในเอกสารซึ่งเป็นsomeNameลูกคนที่สาม ของผู้ปกครอง - อาจมีองค์ประกอบดังกล่าวมากมาย

สิ่งที่คุณต้องการคือsomeNameองค์ประกอบที่ 3 :

(//someName)[3]

คำอธิบายที่: []มีความสำคัญสูงกว่า (ความสำคัญ) //มากกว่า อย่าลืมใส่นิพจน์ของประเภท//someNameในวงเล็บเสมอเมื่อคุณต้องการระบุโหนด Nth ของรายการโหนดที่เลือก


1
ขอบคุณมาก! ขออภัยฉันลืมสิ่งสำคัญไปโดยสิ้นเชิง .. ฉันแค่ลองและมันได้ผล!
Kymair Wu

1
@ Kymair-Wu: ฉันดีใจที่คำตอบนี้มีประโยชน์กับคุณ ที่ SO วิธีแสดงความขอบคุณคือการยอมรับคำตอบ (คำใบ้: คลิกที่เครื่องหมายถูกข้างคำตอบ) :)
Dimitre Novatchev

@DimitreNovatchev คุณได้รับคะแนนสำหรับคำถามเดียวกันซ้ำแล้วซ้ำเล่า: p ขอบคุณสำหรับคำถามที่พบบ่อย
Eytoss

2
@Eytoss ยินดีต้อนรับครับ และใช่ฉันได้รับ +1 ส่วนใหญ่สำหรับคำตอบที่ค่อนข้างง่ายไม่ใช่สำหรับคำตอบที่ฉันเชื่อว่าเป็นความสำเร็จที่ยิ่งใหญ่ที่สุดของฉัน - อาจเป็นเพราะทุกคนเข้าใจอดีตและแทบไม่มีใครเข้าใจสิ่งหลัง :)
Dimitre Novatchev

2
@TEHEMPRAH ที่จริงฉันเห็นว่าในคำตอบฉันไม่ได้พูดว่า "ลูก" someName "ที่ 3 ของพ่อแม่" ขอบคุณที่สังเกตเห็นสิ่งนี้ แก้ไขแล้ว.
Dimitre Novatchev

14

ไม่มีiใน XPath

คุณใช้ตัวเลขตามตัวอักษร: //img[@title='Modify'][1]

หรือคุณสร้างสตริงนิพจน์แบบไดนามิก: '//img[@title='Modify']['+i+']'(แต่โปรดทราบว่านิพจน์ XPath แบบไดนามิกไม่ทำงานจากภายใน XSLT)

หรือ XPath สนับสนุนการเลือกโหนดที่ระบุซึ่งไม่อยู่ภายใต้โหนดแม่เดียวกันหรือไม่

ใช่: (//img[@title='Modify'])[13]


ซึ่ง//img[@title='Modify'][i]หมายความว่า "รายการใด ๆ ที่<img>มีชื่อ" Modify "และองค์ประกอบลูกชื่อ<i>"


ด้วยเหตุผลบางอย่างฉันต้องรวมดัชนีไว้ก่อนนิพจน์แอตทริบิวต์ ตัวอย่างเช่นหากต้องการค้นหาtds ที่เป็นลูกคนที่หกของ a trและไม่มีเนื้อหาว่างเปล่า://tr/td[6][string-length(text()) > 0]
Samir Aguiar

1
@kopranb สำหรับคำอธิบายโปรดดูคำตอบนี้stackoverflow.com/a/1006439/18771
Tomalak

ขอขอบคุณที่อธิบายเกี่ยวกับ '// img [@ title =' Modify '] [' + i + ']' (+1)
DebanjanB

3

ไม่มีiใน xpath ไม่เป็นความจริงทั้งหมด คุณยังสามารถใช้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ปุ่มที่4 จากตารางแรกตามหัวข้อ

ใช้ 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'th ภายใต้โหนดแม่เดียวกัน

คุณต้องการ

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

1
เพียงแค่/descendant::img[@title='Modify'][$index]จะทำงานได้ดี โปรดทราบว่า[i]การทดสอบเพรดิเคตสำหรับการมีอยู่ของiองค์ประกอบลูก

1

(// * [@ attribute = 'value']) [ดัชนี] เพื่อค้นหาเป้าหมายขององค์ประกอบในขณะที่คุณพบรายการที่ตรงกันหลายรายการ


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.