2014-09-02 89 views
1

我有一個HTML字符串(例如<div class="input">hello</div>),我想僅在字符串中的HTML標記爲label(例如<label>Hi</label>)時添加節點。使用Nokogiri添加節點

doc = Nokogiri::XML(html) 

doc.children.each do |node| 
    if node.name == 'label' 
    # this code gets called 
    span = Nokogiri::XML::Node.new "span", node 
    span.content = "hello" 

    puts span.parent 
    # nil 

    span.parent = node 
    # throws error "node can only have one parent" 
    end 
end 

doc.to_html # Does not contain the span. 

我不能爲我的生活了解我做錯了,任何幫助將大大讚賞

編輯:這解決了我的問題,感謝您的答案!

# notice DocumentFragment rather than XML 
doc = Nokogiri::HTML::DocumentFragment.parse(html_tag) 
doc.children.each do |node| 
    if node.name == 'label' 
    span = Nokogiri::XML::Node.new "span", doc 
    node.add_child(span) 
    end 
end 
+0

你想在哪裏顯示新的跨度? – 2014-09-02 12:02:49

+0

你需要展示你的輸出/結果HTML應該是什麼樣子的例子。 – 2014-09-02 18:07:03

回答

2

可以很容易地添加/修改/刪除HTML:

require 'nokogiri' 

doc = Nokogiri::HTML::DocumentFragment.parse('<div class="input">hello</div>') 
div = doc.at('div') 
div << '<span>Hello</span>' 
puts doc.to_html 

導致:

# >> <div class="input">hello<span>Hello</span> 
# >> </div> 

注意,上面的代碼中附加一個新節點<div>現有的孩子,因爲的<<,這意味着它們在之後附加包含「hello」的文本節點。

如果你想覆蓋的孩子,你可以很容易地使用children =做到這一點:

div.children = '<span>Hello</span>' 
puts doc.to_html 

導致:

# >> <div class="input"><span>Hello</span></div> 

children =可以採取哪些可以有多個其它節點的單個節點依靠它或者插入的節點的HTML文本。這就是node_or_tags意味着當你在the documentation看到它。

這就是說,要改變只是一個嵌入式<label>,我會做一些事情,如:

doc = Nokogiri::HTML::DocumentFragment.parse('<div class="input"><label>hello</label></div>') 
label = doc.at('div label') 
label.name = 'span' if label 
puts doc.to_html 
# >> <div class="input"><span>hello</span></div> 

或者:

doc = Nokogiri::HTML::DocumentFragment.parse('<div class="input"><label>hello</label></div>') 
label = doc.at('div label') 
label.replace("<span>#{ label.text }</span>") if label 
puts doc.to_html 
# >> <div class="input"><span>hello</span></div> 

引入nokogiri使得一旦你很容易改變標籤的名稱指着它。您可以輕鬆地更改<span>中的文字,您可以用任何想要的替換#{ label.text }

at('div label')是找到特定節點的一種方式。它基本上意味着「找到第一個div內的第一個標籤標籤」。 at意味着找到第一個東西,並且類似於使用search(...).first。如果您需要這些,則可在atsearchNokogiri::XML::Node documentation之間使用CSS和XPath等效項。

+0

這解決了它,當我應該使用'Nokogiri :: HTML :: DocumentFragment ::'時,我使用了'Nokogiri :: XML ::'。 :-) – nicohvi 2014-09-03 07:35:59

+1

使用'DocumentFragment.parse'和正常解析之間的區別在於,在後面的Nokogiri創建一個DOM與周圍的''標籤,基本上做了修復,試圖創建一個語法正確文件。 – 2014-09-03 18:04:54

+0

是否有將父項添加到片段的方法?我需要在div中包裝和iframe,並給這個div一個特定的類。 – 2016-06-22 18:39:26

1

幾個問題 - 你span = ..線正在創建節點,但實際上並沒有將它添加到文檔。另外,您不能在創建它的塊之外訪問span

我覺得這是你追求的:

html = '<label>Hi</label>' 

doc = Nokogiri::XML(html) 

doc.children.each do |node| 
    if node.name == 'label' 
    # this code gets called 
    span = Nokogiri::XML::Node.new "span", doc 
    span.content = "hello" 
    node.add_child(span) 
    end 
end 

# NOTE: `node` nor `span` are accessible outside of the each block 

doc.to_s # => "<?xml version=\"1.0\"?>\n<label>Hi<span>hello</span></label>\n" 

注意node.add_child(span)線。

+0

是的,我很抱歉顯示混亂的代碼。放置(對於跨度)的調用實際上是在塊內。 – nicohvi 2014-09-03 07:37:49