2011-01-30 13 views
10

を持つ要素にクラスを追加どうやら鋸山のadd_class方法が唯一のこのコードの無効を作り、NodeList秒で動作します:は鋸山

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

答えて

12

CSSクラスが要素上だけで、別の属性である:1つ以上のクラスがすでによ存在する可能性がある場合、あなたがわからない場合はCSSクラス以来

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

は、スペースで区切られた属性であります属性に対して返さ=を使用してだけではなく、文字列を変異

あなたが明示的に属性を設定する必要が
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" 

編集:あなたは、これは鋸山がのために内部的に何をするか、基本的であることがわかりますあなたがソースを表示するために、クラスをクリックして見つけ方法:あなたが見つけた

# 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 
+0

bigup the ClassMutator!ありがとうございました! – flunder

1

鋸山のadd_classは、ノードセット上で動作します。 eachブロック内にクラスを追加しようとしても、その時点で個々のノードで作業しているため動作しません。

代わりに:

# >> 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> 

をルビー1.9+で実装tap方法は、add_class方法は "ブーイング" を追加することができ、ノードリスト自体へのアクセスを提供します:出力

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 

クラスを<p>タグに追加しました

+2

なぜあなたは 'doc.search( 'p')をしないのですか?add_class( 'boo')。each do ...' –

+1

'doc = Nokogiri :: HTML.fragment(html)'を使うことができます。 Nokogiriにdoctypeや他のhtmlやbodyタグを追加したくない – Archonic

関連する問題