首页 文章

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

提问于
浏览
69

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

//img[@title='Modify']

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

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

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

但两者都不起作用..我也试过XPath checker(一个firefox扩展) . 已经找到了13场比赛,然后我完全不知道我将如何选择其中一场比赛.. Or does XPath support specified selection of nodes which are not under same parent node?

5 回答

  • 14

    This is a FAQ

    //someName[3]
    

    means :文档中的所有 someName 元素,即父元素的第三个 someName 子元素 - 可能有许多这样的元素 .

    What you want is exactly the 3rd someName element

    (//someName)[3]
    

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

  • 1

    XPath中没有 i .

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

    或者动态构建表达式字符串: '//img[@title='Modify']['+i+']' (但请记住,动态XPath表达式在XSLT中不起作用) .

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

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


    这个 //img[@title='Modify'][i] 表示“任何 <img> , Headers 为'Modify',子元素名为 <i> . ”

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

    是的缩写

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

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

    你要

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

    (// * [@ attribute ='value'])[index]查找元素的目标,同时在其中找到多个匹配项

  • 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 按钮 .

    假设用户必须根据 Headers 从第一个表中选择第4个 Modify 按钮

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

    count() 运算符在这样的情况下派上用场 .

    Logic:

    • 使用 //th[.='Heading 4'] 查找 Modify 按钮的 Headers

    • 使用 count(//tr/th[.='Heading 4']/preceding-sibling::th)+1 查找 Headers 列的索引

    注意:索引从0开始

    • 使用 //th[.='Heading 4']/ancestor::thead/following-sibling::tbody/tr/td[count(//tr/th[.='Heading 4']/preceding-sibling::th)+1] 获取相应标头的行

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

相关问题