如何用XPath选择日历中未禁用的30号日期元素?
问题描述
有一个带启用/禁用状态的日历表格,想选择并点击未禁用的30号日期元素。原XPath在出现两个30号时失效:
//span[contains(@class,'day-number')][(text()='" + day + "')]
尝试的XPath也无效:
.//td[(@class='calendar-day') and not(@class='disabled')]/span[contains(@class,'day-number')][(text()='" + day + "')]
附对应的HTML结构:
<table class="calendar"> <tbody> <!-- ko foreach: calendarRows.weeks --> <tr class="calendar-week" data-bind="foreach: days"> <td data-bind="css: { disabled: disabled, selected: selected }, click: select, event: {keypress: select}" class="calendar-day disabled"> <span class="day-number" data-bind="text: dayNumber" tabindex="0">30</span> </td> </tr> <tr class="calendar-week" data-bind="foreach: days"> <td data-bind="css: { disabled: disabled, selected: selected }, click: select, event: {keypress: select}" class="calendar-day"> <span class="day-number" data-bind="text: dayNumber" tabindex="0">30</span> </td> </tr> <!-- /ko --> </tbody> </table>
问题分析与解决方案
你的XPath失效原因
尝试的第二个XPath核心问题在类名判断逻辑:
@class='calendar-day'是精确匹配类名,但如果td后续新增其他类名(比如selected),这个条件就会不成立,扩展性极差。not(@class='disabled')逻辑错误:禁用的td的class是calendar-day disabled,不是纯disabled,所以这个判断会错误地认为禁用的td也满足条件,导致过滤完全失效。
正确的定位写法
方案1:修正后的XPath
直接针对类名的包含关系做判断,同时准确过滤禁用状态:
//td[contains(@class, 'calendar-day') and not(contains(@class, 'disabled'))]/span[contains(@class, 'day-number') and text()='30']
代入变量day的版本:
//td[contains(@class, 'calendar-day') and not(contains(@class, 'disabled'))]/span[contains(@class, 'day-number') and text()='" + day + "']
如果要更严谨(避免匹配到类似disabled-xxx的类名),可以用空格包裹类名做判断:
//td[contains(concat(' ', @class, ' '), ' calendar-day ') and not(contains(concat(' ', @class, ' '), ' disabled '))]/span[contains(concat(' ', @class, ' '), ' day-number ') and text()='" + day + "']
方案2:用CSS选择器更简洁(如果支持)
如果你的测试框架/工具支持CSS选择器,这个写法更直观不易错:
td.calendar-day:not(.disabled) span.day-number:contains('30')
变量版:
td.calendar-day:not(.disabled) span.day-number:contains('" + day + "')
内容的提问来源于stack exchange,提问作者Robert
相关产品推荐
相关产品推荐

