如何构建 XPath 以包含来自 HTML 的特定元素?
How to construct a XPath to include specific elements from an HTML?
我有一个 table,我只想 select table 上的按钮。我们可以看到,这个table:
上只有4个按钮
我创建了以下 Xpath 来过滤掉这些 4 个按钮,页面上没有其他按钮:
//*[@id="studentListTable"]/thead/tr/th[contains(., "Actions")]//following::button | //*[@id="studentListTable_info"]//preceding::button
- @id="studentListTable_info"指的是文本"Showing 1 to 3 of 3 entries"。
但这不起作用。
这个 XPath 实际上是定位页面上的所有按钮,而不考虑按钮的位置。
这里有什么问题?
我怎样才能修复它,使这个表达式只定位四个按钮?
HTML 片段:
<div _ngcontent-c7="" appcard="" class="card">
<div _ngcontent-c7="" class="card-header">
<h5 _ngcontent-c7="">Student list <!----></h5></div>
<ul _ngcontent-c7="" class="card-actions">
<li _ngcontent-c7="">
<button _ngcontent-c7="" appcardfullscreen="" class="card-action">
<i _ngcontent-c7="" class="fa fa-arrows-alt"></i></button></li>
<li _ngcontent-c7="">
<button _ngcontent-c7="" appcardcollapse="" class="card-action icon-collapse"><i _ngcontent-c7="" class="material-icons">expand_more</i></button></li></ul>
<!---->
<div _ngcontent-c7="" class="card-body">
<div id="studentListTable_wrapper" class="dataTables_wrapper no-footer">
<div class="dataTables_length" id="studentListTable_length">
<label>Show <select name="studentListTable_length" aria-controls="studentListTable" class="">
<option value="10">10</option>
<option value="25">25</option>
<option value="50">50</option><option value="100">100</option>
</select> entries</label></div>
<div id="studentListTable_filter" class="dataTables_filter">
<label>Search:<input type="search" class="" placeholder="" aria-controls="studentListTable"></label>
</div>
<table _ngcontent-c7="" class="table table-striped dataTable no-footer" datatable="" id="studentListTable" role="grid" aria-describedby="studentListTable_info">
<thead _ngcontent-c7="">
<tr _ngcontent-c7="" role="row">
<th _ngcontent-c7="" class="sorting_asc" tabindex="0" aria-controls="studentListTable" rowspan="1" colspan="1" aria-sort="ascending" aria-label="Student ID: activate to sort column descending" style="width: 101px;">Student ID</th>
<th _ngcontent-c7="" class="sorting_disabled" rowspan="1" colspan="1" aria-label="Actions" style="width: 106px;">Actions</th></tr>
</thead><!----><tbody _ngcontent-c7=""><!---->
<tr _ngcontent-c7="" role="row" class="odd">
<td _ngcontent-c7="" class="sorting_1">123456</td>
<td _ngcontent-c7="">
<a href="unsafe:javascript:void(0)">
<i class="material-icons text-warning">info</i> Not Started</a></td>
<td _ngcontent-c7="">Null</td>
<td _ngcontent-c7="" class="text-left"><!----><div _ngcontent-c7="">
<button _ngcontent-c7="" class="btn btn-sm btn-sm-action mr-2 btn-outline-info" container="body" placement="left" popoverclass="btn-popover" triggers="mouseenter:mouseleave" type="button" tabindex="0">
<i _ngcontent-c7="" class="fa fa-arrow-right"></i></button></div><!----><!----><!----></td></tr>
<tr _ngcontent-c7="" role="row" class="even">
<td _ngcontent-c7="" class="sorting_1">153246</td>
<td _ngcontent-c7=""><a href="unsafe:javascript:void(0)"><i class="fa fa-unlock mr-2"></i>In Progress</a></td>
<td _ngcontent-c7="">Herndon MS</td>
<td _ngcontent-c7="" class="text-left"><!----><!----><div _ngcontent-c7=""><!----><div _ngcontent-c7="" class="d-flex align-items-center">
<button _ngcontent-c7="" class="btn btn-sm btn-sm-action mr-2 btn-outline-info col" container="body" placement="left" popoverclass="btn-popover" triggers="mouseenter:mouseleave" type="button" tabindex="0">
<i _ngcontent-c7="" class="fa fa-pencil"></i></button>
<button _ngcontent-c7="" class="btn btn-sm btn-sm-action mr-2 btn-outline-danger col" container="body" placement="left" popoverclass="btn-popover" triggers="mouseenter:mouseleave" type="button">
<i _ngcontent-c7="" class="fa fa-trash-o"></i></button></div><!----></div><!----><!----></td></tr>
<tr _ngcontent-c7="" role="row" class="odd">
<td _ngcontent-c7="" class="sorting_1">234135</td>
<td _ngcontent-c7="" class="text-left"><!----><!----><!---->
<div _ngcontent-c7="">
<button _ngcontent-c7="" class="btn btn-sm btn-sm-action mr-2 btn-outline-info" container="body" placement="left" popoverclass="btn-popover" triggers="mouseenter:mouseleave" type="button" tabindex="0">
<i _ngcontent-c7="" class="fa fa-eye"></i></button></div><!----></td></tr></tbody><!----><!----><!----></table>
<div class="dataTables_info" id="studentListTable_info" role="status" aria-live="polite">Showing 1 to 3 of 3 entries</div>
<div class="dataTables_paginate paging_simple_numbers" id="studentListTable_paginate">
<a class="paginate_button previous disabled" aria-controls="studentListTable" data-dt-idx="0" tabindex="0" id="studentListTable_previous">Previous</a>
<span>
<a class="paginate_button current" aria-controls="studentListTable" data-dt-idx="1" tabindex="0">1</a>
</span>
<a class="paginate_button next disabled" aria-controls="studentListTable" data-dt-idx="2" tabindex="0" id="studentListTable_next">Next</a></div></div></div></div>
很难回答你的第一个问题那里出了什么问题。
您使用了一些 |
和两个不同的 id
,也许它不完全正确。
并且您在 Xpath 中使用了 thead
元素。尽管所有按钮都位于 tbody
。
无论如何,您的定位器会从该页面获取所有 HTML 按钮。
我尝试将 Xpath 修改为以下内容:
//table//button
而且效果很好:
但是,它不是很好Xpath.
所以尝试将它绑定到最近的 id
。更新后它可以像:
//div[@id='studentListTable_wrapper']//table//button
评价结果相同
还有更多冗余版本(不推荐使用,仅出于示例原因):
//div[@id='studentListTable_wrapper']//table/tbody/tr/td/div//button
顺便说一句,我认为更好的方法是使用像这样的定位器:
//div[@id='...']
而不是:
//*[...]
很难看出是不是select错误的原因。
当然,它更 可读性 并且 更容易理解 以后支持。
您可以使用以下 XPath-1.0 表达式:
//table[@id="studentListTable" and thead/tr/th/text() = "Actions"]/tbody/tr/td[@class="sorting_1"]
至select以下三项:
<td _ngcontent-c7="" class="sorting_1">123456</td>
<td _ngcontent-c7="" class="sorting_1">153246</td>
<td _ngcontent-c7="" class="sorting_1">234135</td>
要进一步获取这三个 table
中包含的四个 button
,可以使用以下 XPath:
//table[@id="studentListTable" and thead/tr/th/text() = "Actions"]/tbody/tr/td[@class="sorting_1"]/../../tr/td//button
其结果由以下四项组成:
<button ... type="button" tabindex="0">
<i _ngcontent-c7="" class="fa fa-arrow-right"/>
</button>
<button ... type="button" tabindex="0">
<i _ngcontent-c7="" class="fa fa-pencil"/>
</button>
<button ... type="button">
<i _ngcontent-c7="" class="fa fa-trash-o"/>
</button>
<button ... type="button" tabindex="0">
<i _ngcontent-c7="" class="fa fa-eye"/>
</button>
如果我理解正确,标题意味着你想组合 2 个尝试的 XPath 表达式来获得位于 th
之后包含文本 "Actions"[=17= 的按钮] 之前 div
id "studentListTable_info" :
//*[@id="studentListTable"]/thead/tr/th[contains(., "Actions")]//following::button[
following::*[@id="studentListTable_info"]
]
几点:
- 第一行和第三行的按钮在
class="odd"
内
- 第二行的两个按钮在
class="even"
内
要过滤掉这 4 个按钮,您可以使用以下基于 XPath 的解决方案:
"//table[@class='table table-striped dataTable no-footer' and @id='studentListTable']//tbody//tr[@class= 'odd' or @class='even']//td[@class='text-left']//button"
通过xpath校验器匹配结果截图:
注意:您没有提到您正在使用的 语言绑定 ,因为元素是 Angular 元素找到您必须诱导 WebDriverWait 的元素,以便 元素可点击 .
您想要的 BUTTON
是 table 中唯一的按钮,而 table 有一个 ID,studentListTable
,所以您只需要 children BUTTON
个ID.
根据您提供的HTML,像下面这样简单的东西就可以了。
XPath
//[@id='studentListTable']//button
CSS 选择器
#studentListTable button
您可以通过 Student Id
select 按钮使用下面的 xpath 作为示例 153246
id:
//table[@id='studentListTable']//tr[@role='row' and ./td[@class='sorting_1' and .='153246']]//button
我有一个 table,我只想 select table 上的按钮。我们可以看到,这个table:
上只有4个按钮我创建了以下 Xpath 来过滤掉这些 4 个按钮,页面上没有其他按钮:
//*[@id="studentListTable"]/thead/tr/th[contains(., "Actions")]//following::button | //*[@id="studentListTable_info"]//preceding::button
- @id="studentListTable_info"指的是文本"Showing 1 to 3 of 3 entries"。
但这不起作用。
这个 XPath 实际上是定位页面上的所有按钮,而不考虑按钮的位置。
这里有什么问题?
我怎样才能修复它,使这个表达式只定位四个按钮?
HTML 片段:
<div _ngcontent-c7="" appcard="" class="card">
<div _ngcontent-c7="" class="card-header">
<h5 _ngcontent-c7="">Student list <!----></h5></div>
<ul _ngcontent-c7="" class="card-actions">
<li _ngcontent-c7="">
<button _ngcontent-c7="" appcardfullscreen="" class="card-action">
<i _ngcontent-c7="" class="fa fa-arrows-alt"></i></button></li>
<li _ngcontent-c7="">
<button _ngcontent-c7="" appcardcollapse="" class="card-action icon-collapse"><i _ngcontent-c7="" class="material-icons">expand_more</i></button></li></ul>
<!---->
<div _ngcontent-c7="" class="card-body">
<div id="studentListTable_wrapper" class="dataTables_wrapper no-footer">
<div class="dataTables_length" id="studentListTable_length">
<label>Show <select name="studentListTable_length" aria-controls="studentListTable" class="">
<option value="10">10</option>
<option value="25">25</option>
<option value="50">50</option><option value="100">100</option>
</select> entries</label></div>
<div id="studentListTable_filter" class="dataTables_filter">
<label>Search:<input type="search" class="" placeholder="" aria-controls="studentListTable"></label>
</div>
<table _ngcontent-c7="" class="table table-striped dataTable no-footer" datatable="" id="studentListTable" role="grid" aria-describedby="studentListTable_info">
<thead _ngcontent-c7="">
<tr _ngcontent-c7="" role="row">
<th _ngcontent-c7="" class="sorting_asc" tabindex="0" aria-controls="studentListTable" rowspan="1" colspan="1" aria-sort="ascending" aria-label="Student ID: activate to sort column descending" style="width: 101px;">Student ID</th>
<th _ngcontent-c7="" class="sorting_disabled" rowspan="1" colspan="1" aria-label="Actions" style="width: 106px;">Actions</th></tr>
</thead><!----><tbody _ngcontent-c7=""><!---->
<tr _ngcontent-c7="" role="row" class="odd">
<td _ngcontent-c7="" class="sorting_1">123456</td>
<td _ngcontent-c7="">
<a href="unsafe:javascript:void(0)">
<i class="material-icons text-warning">info</i> Not Started</a></td>
<td _ngcontent-c7="">Null</td>
<td _ngcontent-c7="" class="text-left"><!----><div _ngcontent-c7="">
<button _ngcontent-c7="" class="btn btn-sm btn-sm-action mr-2 btn-outline-info" container="body" placement="left" popoverclass="btn-popover" triggers="mouseenter:mouseleave" type="button" tabindex="0">
<i _ngcontent-c7="" class="fa fa-arrow-right"></i></button></div><!----><!----><!----></td></tr>
<tr _ngcontent-c7="" role="row" class="even">
<td _ngcontent-c7="" class="sorting_1">153246</td>
<td _ngcontent-c7=""><a href="unsafe:javascript:void(0)"><i class="fa fa-unlock mr-2"></i>In Progress</a></td>
<td _ngcontent-c7="">Herndon MS</td>
<td _ngcontent-c7="" class="text-left"><!----><!----><div _ngcontent-c7=""><!----><div _ngcontent-c7="" class="d-flex align-items-center">
<button _ngcontent-c7="" class="btn btn-sm btn-sm-action mr-2 btn-outline-info col" container="body" placement="left" popoverclass="btn-popover" triggers="mouseenter:mouseleave" type="button" tabindex="0">
<i _ngcontent-c7="" class="fa fa-pencil"></i></button>
<button _ngcontent-c7="" class="btn btn-sm btn-sm-action mr-2 btn-outline-danger col" container="body" placement="left" popoverclass="btn-popover" triggers="mouseenter:mouseleave" type="button">
<i _ngcontent-c7="" class="fa fa-trash-o"></i></button></div><!----></div><!----><!----></td></tr>
<tr _ngcontent-c7="" role="row" class="odd">
<td _ngcontent-c7="" class="sorting_1">234135</td>
<td _ngcontent-c7="" class="text-left"><!----><!----><!---->
<div _ngcontent-c7="">
<button _ngcontent-c7="" class="btn btn-sm btn-sm-action mr-2 btn-outline-info" container="body" placement="left" popoverclass="btn-popover" triggers="mouseenter:mouseleave" type="button" tabindex="0">
<i _ngcontent-c7="" class="fa fa-eye"></i></button></div><!----></td></tr></tbody><!----><!----><!----></table>
<div class="dataTables_info" id="studentListTable_info" role="status" aria-live="polite">Showing 1 to 3 of 3 entries</div>
<div class="dataTables_paginate paging_simple_numbers" id="studentListTable_paginate">
<a class="paginate_button previous disabled" aria-controls="studentListTable" data-dt-idx="0" tabindex="0" id="studentListTable_previous">Previous</a>
<span>
<a class="paginate_button current" aria-controls="studentListTable" data-dt-idx="1" tabindex="0">1</a>
</span>
<a class="paginate_button next disabled" aria-controls="studentListTable" data-dt-idx="2" tabindex="0" id="studentListTable_next">Next</a></div></div></div></div>
很难回答你的第一个问题那里出了什么问题。
您使用了一些|
和两个不同的id
,也许它不完全正确。
并且您在 Xpath 中使用了thead
元素。尽管所有按钮都位于tbody
。 无论如何,您的定位器会从该页面获取所有 HTML 按钮。我尝试将 Xpath 修改为以下内容:
//table//button
而且效果很好:
但是,它不是很好Xpath.
所以尝试将它绑定到最近的 id
。更新后它可以像:
//div[@id='studentListTable_wrapper']//table//button
评价结果相同
还有更多冗余版本(不推荐使用,仅出于示例原因):
//div[@id='studentListTable_wrapper']//table/tbody/tr/td/div//button
顺便说一句,我认为更好的方法是使用像这样的定位器:
//div[@id='...']
而不是:
//*[...]
很难看出是不是select错误的原因。
当然,它更 可读性 并且 更容易理解 以后支持。
您可以使用以下 XPath-1.0 表达式:
//table[@id="studentListTable" and thead/tr/th/text() = "Actions"]/tbody/tr/td[@class="sorting_1"]
至select以下三项:
<td _ngcontent-c7="" class="sorting_1">123456</td>
<td _ngcontent-c7="" class="sorting_1">153246</td>
<td _ngcontent-c7="" class="sorting_1">234135</td>
要进一步获取这三个 table
中包含的四个 button
,可以使用以下 XPath:
//table[@id="studentListTable" and thead/tr/th/text() = "Actions"]/tbody/tr/td[@class="sorting_1"]/../../tr/td//button
其结果由以下四项组成:
<button ... type="button" tabindex="0">
<i _ngcontent-c7="" class="fa fa-arrow-right"/>
</button>
<button ... type="button" tabindex="0">
<i _ngcontent-c7="" class="fa fa-pencil"/>
</button>
<button ... type="button">
<i _ngcontent-c7="" class="fa fa-trash-o"/>
</button>
<button ... type="button" tabindex="0">
<i _ngcontent-c7="" class="fa fa-eye"/>
</button>
如果我理解正确,标题意味着你想组合 2 个尝试的 XPath 表达式来获得位于 th
之后包含文本 "Actions"[=17= 的按钮] 之前 div
id "studentListTable_info" :
//*[@id="studentListTable"]/thead/tr/th[contains(., "Actions")]//following::button[
following::*[@id="studentListTable_info"]
]
几点:
- 第一行和第三行的按钮在
class="odd"
内
- 第二行的两个按钮在
class="even"
内
要过滤掉这 4 个按钮,您可以使用以下基于 XPath 的解决方案:
"//table[@class='table table-striped dataTable no-footer' and @id='studentListTable']//tbody//tr[@class= 'odd' or @class='even']//td[@class='text-left']//button"
通过xpath校验器匹配结果截图:
注意:您没有提到您正在使用的 语言绑定 ,因为元素是 Angular 元素找到您必须诱导 WebDriverWait 的元素,以便 元素可点击 .
您想要的 BUTTON
是 table 中唯一的按钮,而 table 有一个 ID,studentListTable
,所以您只需要 children BUTTON
个ID.
根据您提供的HTML,像下面这样简单的东西就可以了。
XPath
//[@id='studentListTable']//button
CSS 选择器
#studentListTable button
您可以通过 Student Id
select 按钮使用下面的 xpath 作为示例 153246
id:
//table[@id='studentListTable']//tr[@role='row' and ./td[@class='sorting_1' and .='153246']]//button