2009-10-05 69 views
301

我要寻找一个CSS选择如下表:是否有包含某些文本的元素的CSS选择器?

Peter | male | 34 
Susanne | female | 12 

是否有任何选择,以匹配包含“男性”的所有TD?

+1

问题是,这将很难以高性能的方式实现。 – Ms2ger 2009-10-06 13:11:58

+2

我现在在使用jQuery。它完美的作品。 – jantimon 2009-10-06 13:27:49

+5

XPath选择器可以使用.text()方法执行它(如果您不想使用JavaScript执行程序)。 – djangofan 2013-02-03 20:46:53

回答

233

如果我正确地读了the specification,没有。

您可以匹配元素,元素中的属性名称和元素中命名属性的值。尽管如此,我没有看到任何匹配内容的内容。

+153

有一个边缘情况:':空白'。 – 2014-07-06 10:55:49

+2

以上评论必须是选择的答案! – 2016-08-03 16:01:55

+9

这个答案今天(2016年)依然如此吗? – 2016-09-22 12:13:44

3

恐怕这是不可能的,因为内容没有属性,也不能通过伪类访问。可以在the CSS3 specification找到CSS3选择器的完整列表。

86

你必须添加一个数据属性,称为data-gendermalefemale值的行和使用属性选择:

HTML:

<td data-gender="male">...</td> 

CSS:

td[data-gender="male"] { ... } 
+3

聪明的解决方案。谢谢 – 2015-01-30 16:46:15

+1

数据属性不能用作JS钩子或CSS选择器 - 这就是类的用途。 从规范:“自定义数据属性是为了将自定义数据私人存储到页面或应用程序,为此没有更适当的属性或元素。”#: Link to spec:[link](http:// www .w3.org/html/wg/drafts/html/master/dom.html#embedding-custom-non-visible-data-with-the-data - * - attributes) – 2015-06-12 23:19:02

+10

@Ivan Durst,我衷心不赞同JS钩子或CSS选择符符合页面或应用程序私有数据的定义,而且目前还没有比较适合用于性别的html语义。我们把更多的责任放到class属性上,我们最终从语义html中获得更多的功能,所以我开始使用html5中可用的增加的元数据。 – DannyMeister 2015-07-06 18:46:39

98

看起来他们正在考虑CSS3规范但它并没有削减

:contains() CSS3选择器http://www.w3.org/TR/css3-selectors/#content-selectors

+19

':contains()'的最后一个可用定义可以在这里找到(http://www.w3.org/TR/2001/CR-css3-selectors-20011113/#content-selectors)。 – BoltClock 2012-02-07 05:06:34

+2

'看起来他们正在为CSS3规范思考它,但它并没有削减。“并且出于充分的理由,这违反了分离样式,内容,结构和行为的整个前提。 – Synetech 2015-07-06 22:01:34

+26

@Synetech它实际上可以帮助将样式与内容分离,因为它意味着内容不需要知道其客户端将被视为重要的基础样式。现在我们的html内容通常包含我们知道样式器关心的类,并与css紧密配合。他们已经开始转向在内容中使用CSS,正如CSS3中的属性值选择器所证明的那样。 – DannyMeister 2015-07-16 23:23:42

128

使用jQuery:

$('td:contains("male")') 
+5

需要与此相反,它是:jQuery(element).not(“:contains('string')”) – Jazzy 2013-11-06 22:58:09

+130

除了不是CSS,那就是JavaScript。 – Synetech 2015-07-06 22:00:31

+5

同意 - 这就是为什么我的回答说我使用jQuery,而不是CSS。但我的答案的那部分被编辑了出来。 =) – moettinger 2015-07-07 01:22:43

54

其实是有为什么这并没有得到落实非常概念基础。它的主要三个方面的结合:

  1. 元素的文本内容实际上是该元素
  2. 的孩子你不能针对文本内容直接
  3. CSS不允许有选择
  4. 提升

这3个表示当你有文本内容时,你不能上升回到包含的元素,并且你不能设置当前文本的样式。这可能很重要,因为降序只允许对上下文和SAX样式解析进行单独跟踪。包含其他轴的升序或其他选择器引入了更复杂的遍历或类似解决方案的需求,这将使CSS在DOM上的应用大大复杂化。

+3

这是真的。这是XPath的用途。如果你可以在JS/jQuery或解析库中执行选择器(而不是CSS),那么可以使用XPath的'text()'函数。 – 2013-06-07 13:25:18

+0

对我来说这些都是借口。 css是我见过的最糟糕的语言之一。因为基本逻辑的关键词可以追溯到20世纪80年代,所以使用?+ @#>和空格(大声喊叫!)。他们所能做的至少是使用现有的可怕的反直觉选择器语言,如正则表达式或xpath,它们均匀不好,但至少你不必学习另一种语言。 他们可以做的最好的事情是使用js的端口,无论是选择器,属性还是值。例如,至少在这种情况下,您可以将某个元素放置在其容器中,而关于一个侧元素。 – oriadam 2017-07-18 14:16:30

3

对于那些想要做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]; 
} 

这将返回的第一个元素,如果有不止一个因为它总是一个元素,就我而言。

4

由于CSS缺乏此功能,您将不得不使用javascript来按内容对单元格进行样式设置。例如使用XPath 包含

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"; 
} 

https://jsfiddle.net/gaby_de_wilde/o7bka7Ls/9/

+0

这是javascript,这与这个问题有什么关系? – rubo77 2016-08-11 01:27:19

+0

由于你无法通过CSS选择内容,你将不得不使用js来做到这一点。虽然你指出这不是css,但数据属性的使用不是按内容选择的。我们只能猜测为什么读者想按内容选择单元格,她对html有什么样的访问权限,有多少匹配,表格有多大等等。 – user40521 2016-09-07 16:00:26

9

的数据属性您可以设置内容,然后用attribute selectors

/* Select every cell containing 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-conten="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()); 
    }); 
}); 
+1

这是一个非常方便的技巧,用于生成标记 – Whelkaholism 2017-02-24 13:42:44

+2

请注意'。 text()'和'.textContent'非常重,尽可能避免在长列表或大文本中使用它们。 '.html()'和'.innerHTML'很快。 – oriadam 2017-07-18 14:09:16

1

@航海者的回答有关使用data-*属性(例如data-gender="female|male"是最有效和符合标准方法2017年:

[data-gender='male'] {background-color: #000; color: #ccc;} 

差不多进球最多可以来实现,因为有一些虽然周围的面向文本的有限选择。 ::first-letter是一个pseudo-element,可以将有限的样式应用于元素的第一个字母。还有一个::first-line伪元素,除了明显选择元素的第一行(例如段落)之外,还意味着可以使用CSS来扩展此现有功能以设置textNode的特定方面。

在此之前的宣传成功实现应用时是使用空间deliminator explode/split的话,输出span元素中,然后如果字/造型的目标每一个人的话,我可以建议退而求其次是组合预测的使用与:nth selectors

$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>; 
} 
1

我同意the data attribute(航海的答案)是应该如何来处理,但是,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}}"> 
1

这里的大多数答案尝试提供替代方案怎么写HTML代码包含更多的数据,因为至少达到CSS3你不能通过部分内部文本选择一个元素。不过,这是可以做到,你只需要添加一点香草的JavaScript,通知自女性还含有男性会选择:

 cells = document.querySelectorAll('td'); 
 
    \t console.log(cells); 
 
     [].forEach.call(cells, function (el) { 
 
    \t if(el.innerText.indexOf("male") !== -1){ 
 
    \t //el.click(); click or any other option 
 
    \t console.log(el) 
 
    \t } 
 
    });
<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> 
-1

我有一些不好的HTML同样的问题。所有数据保存在<td>标签中,没有附加标识信息。

注意:这只适用于因为随后的<td>文本始终包含前面的<td>文本的“值”。

我正在寻找芝加哥所有CTA电台的地址。我有一个带站号的数据库,所以我可以用下面的代码创建一个将站号连接到地址的散列。

td_hash = {} 
filename = Rails.root + "cta_geojson.geojson" 
page = open(filename) 
parsed_json = JSON.parse(page.read) 
q = parsed_json['features'].map {|e| e['properties']['description'] } #description was a string of badly formed HTML 
q.each do |station| 
    doc = Nokogiri::HTML(station) 
    td = doc.css("td") #collect the td's 
    s_address = 0 #address selector. This goes to 1 when the <td> text is "ADDRESS" becase we know the address is in the next <td> 
    s_gtfs = 0 #gtfs selector. This goes to 1 when the <td> text is "GTFS" because we know the cta number is in the next <td> 
    key = '' 
    value = '' 
    td.each do |td| 
    if s_address == 1 
     value = td.text 
     s_address = 0 
    end 
    if s_gtfs == 1 
     key = td.text 
     td_hash.store(key,value) 
     s_gtfs = 0 
    end 
    if td.text == "ADDRESS" 
     s_address = s_address + 1 
    end 
    if td.text == "GTFS" 
     s_gtfs = s_gtfs + 1 
    end 
    end 
end 
相关问题