使用Nokogiri将元素添加到元素中

Tom*_*man 12 ruby nokogiri

显然Nokogiri的add_class方法仅适用于NodeLists,使此代码无效:

doc.search('a').each do |anchor|
  anchor.inner_text = "hello!"
  anchor.add_class("whatever") # WHOOPS!
end
Run Code Online (Sandbox Code Playgroud)

我该怎么做才能使这段代码有效?我觉得它有点像

doc.search('a').each do |anchor|
  anchor.inner_text = "hello!"
  Nokogiri::XML::NodeSet.new(anchor).add_class("whatever")
end
Run Code Online (Sandbox Code Playgroud)

但这也不起作用.请告诉我,我不必add_class为单个节点实现自己的!

Phr*_*ogz 15

CSS类只是元素的另一个属性:

doc.search('a').each do |anchor|
  anchor.inner_text = "hello!"
  anchor['class']="whatever"
end
Run Code Online (Sandbox Code Playgroud)

由于CSS类在属性中以空格分隔,如果您不确定是否已存在一个或多个类,则需要类似

anchor['class'] ||= ""
anchor['class'] = anchor['class'] << " whatever"
Run Code Online (Sandbox Code Playgroud)

您需要使用显式设置属性,=而不是仅仅改变为该属性返回的字符串.例如,这不会改变DOM:

anchor['class'] ||= ""
anchor['class'] << " whatever"
Run Code Online (Sandbox Code Playgroud)

虽然它会导致更多的工作,但我可能会这样做:

class Nokogiri::XML::Node
  def add_css_class( *classes )
    existing = (self['class'] || "").split(/\s+/)
    self['class'] = existing.concat(classes).uniq.join(" ")
  end
end
Run Code Online (Sandbox Code Playgroud)

如果你不想修补这个类,你可以选择:

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"
Run Code Online (Sandbox Code Playgroud)

编辑:您可以看到这基本上是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
Run Code Online (Sandbox Code Playgroud)