我正在为下表寻找 CSS 选择器:
Peter | male | 34
Susanne | female | 12
是否有任何选择器可以匹配所有包含“男性”的 TD?
我正在为下表寻找 CSS 选择器:
Peter | male | 34
Susanne | female | 12
是否有任何选择器可以匹配所有包含“男性”的 TD?
如果我正确阅读了规范,则不会。
您可以匹配元素、元素中属性的名称以及元素中命名属性的值。不过,我没有看到任何匹配元素内的内容。
看起来他们正在为 CSS3 规范考虑它,但它没有成功。
:contains()
CSS3 选择器http://www.w3.org/TR/css3-selectors/#content-selectors
使用 jQuery:
$('td:contains("male")')
您必须向使用 or 值调用的行添加数据属性data-gender
并male
使用female
属性选择器:
HTML:
<td data-gender="male">...</td>
CSS:
td[data-gender="male"] { ... }
实际上有一个非常概念性的基础来解释为什么这还没有实现。它基本上是3个方面的组合:
这 3 个一起意味着当您拥有文本内容时,您无法返回到包含元素,并且您无法设置当前文本的样式。这可能很重要,因为降序只允许对上下文和 SAX 样式解析进行单一跟踪。涉及其他轴的升序或其他选择器引入了对更复杂的遍历或类似解决方案的需求,这将使 CSS 在 DOM 中的应用变得非常复杂。
您可以将内容设置为数据属性,然后使用属性选择器,如下所示:
/* Select every cell matching the word "male" */
td[data-content="male"] {
color: red;
}
/* Select every cell starting on "p" case insensitive */
td[data-content^="p" i] {
color: blue;
}
/* Select every cell containing "4" */
td[data-content*="4"] {
color: green;
}
<table>
<tr>
<td data-content="Peter">Peter</td>
<td data-content="male">male</td>
<td data-content="34">34</td>
</tr>
<tr>
<td data-content="Susanne">Susanne</td>
<td data-content="female">female</td>
<td data-content="14">14</td>
</tr>
</table>
您还可以使用 jQuery 轻松设置数据内容属性:
$(function(){
$("td").each(function(){
var $this = $(this);
$this.attr("data-content", $this.text());
});
});
由于 CSS 缺少此功能,您将不得不使用 JavaScript 按内容设置单元格样式。例如使用 XPath 的contains
:
var elms = document.evaluate( "//td[contains(., 'male')]", node, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null )
然后像这样使用结果:
for ( var i=0 ; i < elms.snapshotLength; i++ ){
elms.snapshotItem(i).style.background = "pink";
}
截至 2021 年 1 月,有一些事情可以做到这一点。:has() ...只有一个问题:任何浏览器尚不支持此功能
示例:以下选择器仅匹配直接包含子元素的元素:
a:has(> img)
参考:
恐怕这是不可能的,因为内容不是属性,也不能通过伪类访问。CSS3 选择器的完整列表可以在CSS3 规范中找到。
对于那些想要进行 Selenium CSS 文本选择的人来说,这个脚本可能会有一些用处。
诀窍是选择您要查找的元素的父元素,然后搜索具有文本的子元素:
public static IWebElement FindByText(this IWebDriver driver, string text)
{
var list = driver.FindElement(By.CssSelector("#RiskAddressList"));
var element = ((IJavaScriptExecutor)driver).ExecuteScript(string.Format(" var x = $(arguments[0]).find(\":contains('{0}')\"); return x;", text), list);
return ((System.Collections.ObjectModel.ReadOnlyCollection<IWebElement>)element)[0];
}
如果有多个元素,这将返回第一个元素,因为在我的情况下它始终是一个元素。
我同意data 属性(航海者的回答)应该如何处理,但是 CSS 规则如下:
td.male { color: blue; }
td.female { color: pink; }
通常可以更容易设置,尤其是像 angularjs 这样的客户端库,它可能很简单:
<td class="{{person.gender}}">
只要确保内容只有一个字!或者你甚至可以映射到不同的 CSS 类名:
<td ng-class="{'masculine': person.isMale(), 'feminine': person.isFemale()}">
为了完整起见,这里是数据属性方法:
<td data-gender="{{person.gender}}">
如果您使用的是Chimp / Webdriver.io,它们支持的 CSS 选择器比 CSS 规范要多得多。
例如,这将点击第一个包含“坏熊”字样的锚点:
browser.click("a*=Bad Bear");
如果您不自己创建 DOM(例如在用户脚本中),您可以使用纯 JS 执行以下操作:
for ( td of document.querySelectorAll('td') ) {
console.debug("text:", td, td.innerText)
td.setAttribute('text', td.innerText)
}
for ( td of document.querySelectorAll('td[text="male"]') )
console.debug("male:", td, td.innerText)
<table>
<tr>
<td>Peter</td>
<td>male</td>
<td>34</td>
</tr>
<tr>
<td>Susanne</td>
<td>female</td>
<td>12</td>
</tr>
</table>
控制台输出
text: <td> Peter
text: <td> male
text: <td> 34
text: <td> Susanne
text: <td> female
text: <td> 12
male: <td text="male"> male
@voyager 关于使用data-*
属性的回答(例如,截至 2017 年data-gender="female|male"
是最有效且符合标准的方法:
[data-gender='male'] {background-color: #000; color: #ccc;}
几乎可以实现大多数目标,因为有一些尽管有限的选择器围绕文本。::first-letter是一个伪元素,可以将有限的样式应用于元素的第一个字母。除了明显选择元素(例如段落)的第一行之外,还有一个::first-line伪元素也意味着很明显 CSS 可以用于扩展这种现有能力以设置 textNode 的特定方面的样式.
在这种倡导成功并实施之前,我可以建议的下一个最好的方法是使用空格分隔符到explode
/split
单词,输出元素内的每个单词span
,然后如果单词/样式目标是可预测的,则与:nth 选择器结合使用:
$p = explode(' ',$words);
foreach ($p as $key1 => $value1)
{
echo '<span>'.$value1.'</span>;
}
否则,如果不可预测,再次使用航海者关于使用data-*
属性的答案。使用 PHP 的示例:
$p = explode(' ',$words);
foreach ($p as $key1 => $value1)
{
echo '<span data-word="'.$value1.'">'.$value1.'</span>;
}
这里的大多数答案都试图提供如何编写 HTML 代码以包含更多数据的替代方法,因为至少在 CSS3 之前,您不能通过部分内部文本选择元素。但这可以做到,你只需要添加一点香草 JavaScript,注意因为女性也包含男性,它将被选中:
cells = document.querySelectorAll('td');
console.log(cells);
[].forEach.call(cells, function (el) {
if(el.innerText.indexOf("male") !== -1){
//el.click(); click or any other option
console.log(el)
}
});
<table>
<tr>
<td>Peter</td>
<td>male</td>
<td>34</td>
</tr>
<tr>
<td>Susanne</td>
<td>female</td>
<td>14</td>
</tr>
</table>
<table>
<tr>
<td data-content="Peter">Peter</td>
<td data-content="male">male</td>
<td data-content="34">34</td>
</tr>
<tr>
<td data-conten="Susanne">Susanne</td>
<td data-content="female">female</td>
<td data-content="14">14</td>
</tr>
</table>
如果您想将样式应用于您想要的内容。简单的把戏。
td { border: 1px solid black; }
td:empty { background: lime; }
td:empty::after { content: "male"; }
<table>
<tr>
<td>Peter</td>
<td><!--male--></td>
<td>34</td>
</tr>
<tr>
<td>Susanne</td>
<td>female</td>
<td>14</td>
</tr>
</table>
如果您不想使用 javascript 或 jquery,我发现属性选项是您最好的选择。
例如,为所有表格单元格设置单词 ready 的样式,在 HTML 中执行以下操作:
<td status*="ready">Ready</td>
然后在css中:
td[status*="ready"] {
color: red;
}
像这样做小的过滤器小部件:
var searchField = document.querySelector('HOWEVER_YOU_MAY_FIND_IT')
var faqEntries = document.querySelectorAll('WRAPPING_ELEMENT .entry')
searchField.addEventListener('keyup', function (evt) {
var testValue = evt.target.value.toLocaleLowerCase();
var regExp = RegExp(testValue);
faqEntries.forEach(function (entry) {
var text = entry.textContent.toLocaleLowerCase();
entry.classList.remove('show', 'hide');
if (regExp.test(text)) {
entry.classList.add('show')
} else {
entry.classList.add('hide')
}
})
})
这个问题的语法看起来像 Robot Framework 语法。在这种情况下,虽然没有可用于包含的 css 选择器,但可以使用 SeleniumLibrary 关键字。等待直到元素包含.
例子:
Wait Until Element Contains | ${element} | ${contains}
Wait Until Element Contains | td | male