2017-03-29 22 views
0

我有:如何更改类具有匹配内容元素

<div class="bar">baz</div> 
<div class="foo">qux</div> 
<div class="foo">qux</div> 
<div class="foo">baz</div> 
<div class="foo">qux</div> 
<div class="foo">baz</div> 
<div class="foo">qux</div> 

而且我想所有包含内容相同的一个一类“栏”也有一个元素这样的“酒吧”类:

<div class="bar">baz</div> 
<div class="foo">qux</div> 
<div class="foo">qux</div> 
<div class="bar">baz</div> 
<div class="foo">qux</div> 
<div class="bar">baz</div> 
<div class="foo">qux</div> 

但我不能只搜索“巴兹”,因为该内容可能会发生变化。相反,我必须搞清楚什么是在孤独的“酒吧”的div然后找到与之相匹配的是别人而改变自己的类“栏”了。

我已经成功地得到了第一个“棒”元素的内容到一个变量:

var = body.css(".bar").first.inner_text 

但没有什么我已经从那里试图尽可能找到匹配的内容和更换类有工作。

回答

0

小心使用body.css("div:contains('#{text_to_match}')")

input = '<div class="bar">baz</div> 
<div class="foo">qux</div> 
<div class="foo">qux</div> 
<div class="foo">baza</div> 
<div class="foo">qux</div> 
<div class="foo">bazfdsfsdf</div> 
<div class="foo">qux</div>' 

输出将是:

<div class="bar">baz</div> 
<div class="foo">qux</div> 
<div class="foo">qux</div> 
<div class="bar">baza</div> 
<div class="foo">qux</div> 
<div class="bar">bazfdsfsdf</div> 
<div class="foo">qux</div> 

如果你想匹配在两个元素中完全相同的文字,你应该使用: body.css("div[text() = '#{text_to_match}']")

input = '<div class="bar">baz</div> 
<div class="foo">qux</div> 
<div class="foo">qux</div> 
<div class="foo">baza</div> 
<div class="foo">qux</div> 
<div class="foo">bazfdsfsdf</div> 
<div class="foo">baz</div>' 

输出将是:

<div class="bar">baz</div> 
<div class="foo">qux</div> 
<div class="foo">qux</div> 
<div class="foo">baza</div> 
<div class="foo">qux</div> 
<div class="foo">bazfdsfsdf</div> 
<div class="bar">baz</div> 
0

您可以使用body.css('div:contains("<text-to-match>")')匹配包含您想要的文本内容的节点。

你可以达到你想要做什么像什么:

require 'nokogiri' 

input = '<div class="bar">baz</div> 
<div class="foo">qux</div> 
<div class="foo">qux</div> 
<div class="foo">baz</div> 
<div class="foo">qux</div> 
<div class="foo">baz</div> 
<div class="foo">qux</div>' 

body = Nokogiri::HTML.fragment(input) 

text_to_match = body.at_css('.bar').text 

matching_nodes = body.css("div:contains('#{text_to_match}')") 
matching_nodes.each do |node| 
    node['class'] = 'bar' 
end 

puts body.to_html 
+0

酷感谢这个作品!现在唯一的问题是它也针对包含包含baz的div的div。必须弄清楚如何针对直接包含baz而不是父母的div。 – j1mmy

+0

“必须弄清楚如何针对直接包含baz而不是父母的div”所以你的例子和问题不是他们应该做的?不要提出蠕变的问题;找出真正的问题是什么,然后问。如果不这样做会浪费每个人的时间。 –

0

我会做这样的事情:

require 'nokogiri' 

doc = Nokogiri::HTML(<<EOT) 
<div class="bar">baz</div> 
<div class="foo">qux</div> 
<div class="foo">baz</div> 
EOT 

target_text = doc.at('.bar').text # => "baz" 
doc.search("//div[text()='#{target_text}']").each do |div| 
    div['class'] = 'bar' 
end 

导致:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> 
<html><body> 
<div class="bar">baz</div> 
<div class="foo">qux</div> 
<div class="bar">baz</div> 
</body></html> 

没有什么,说我们不能混用的CSS和XPath选择。 XPath具有更多功能,但它在视觉上很嘈杂,所以我可以在需要时使用CSS,而在必要时使用XPath。

XPath可以很容易地搜索所有节点的文本,所以它是该任务的不错选择。

相关问题