显然Nokogiri的add_class
方法仅适用于NodeList
s,使此代码无效:
doc.search('a').each do |anchor|
anchor.inner_text = "hello!"
anchor.add_class("whatever") # WHOOPS!
end
如何使此代码正常工作?我认为这就像是
doc.search('a').each do |anchor|
anchor.inner_text = "hello!"
Nokogiri::XML::NodeSet.new(anchor).add_class("whatever")
end
但这也不起作用。请告诉我,我不必为单个节点实现自己的add_class
!
答案 0 :(得分:15)
CSS类只是元素的另一个属性:
doc.search('a').each do |anchor|
anchor.inner_text = "hello!"
anchor['class']="whatever"
end
由于CSS类在属性中以空格分隔,如果您不确定是否已存在一个或多个类,则需要类似
的内容。anchor['class'] ||= ""
anchor['class'] = anchor['class'] << " whatever"
您需要使用=
显式设置属性,而不是仅仅更改为该属性返回的字符串。例如,这不会改变DOM:
anchor['class'] ||= ""
anchor['class'] << " whatever"
尽管它会导致更多的工作,但我可能会这样做:
class Nokogiri::XML::Node
def add_css_class( *classes )
existing = (self['class'] || "").split(/\s+/)
self['class'] = existing.concat(classes).uniq.join(" ")
end
end
如果您不想修补课程,可以选择:
module ClassMutator
def add_css_class( *classes )
existing = (self['class'] || "").split(/\s+/)
self['class'] = existing.concat(classes).uniq.join(" ")
end
end
anchor.extend ClassMutator
anchor.add_css_class "whatever"
修改:您可以看到这基本上是Nokogiri在内部为您通过点击课程查看来源找到的add_class
方法所做的事情:
# File lib/nokogiri/xml/node_set.rb, line 136
def add_class name
each do |el|
next unless el.respond_to? :get_attribute
classes = el.get_attribute('class').to_s.split(" ")
el.set_attribute('class', classes.push(name).uniq.join(" "))
end
self
end
答案 1 :(得分:1)
Nokogiri的add_class
,就像你找到的那样在NodeSet上工作。尝试在each
块中添加类不起作用,因为此时您正在处理单个节点。
相反:
require 'nokogiri'
html = '<p>one</p><p>two</p>'
doc = Nokogiri::HTML(html)
doc.search('p').tap{ |ns| ns.add_class('boo') }.each do |n|
puts n.text
end
puts doc.to_html
哪个输出:
# >> one
# >> two
# >> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
# >> <html><body>
# >> <p class="boo">one</p>
# >> <p class="boo">two</p>
# >> </body></html>
在Ruby 1.9+中实现的tap
方法允许访问节点列表本身,允许add_class
方法将“boo”类添加到<p>
标记。
答案 2 :(得分:1)
旧线程,但它是 Google 的热门话题。您现在可以使用 append_class
method 执行此操作,而不必弄乱空格分隔符:
doc.search('a').each do |anchor|
anchor.inner_text = "hello!"
anchor.append_class('whatever')
end