使用Nokogiri添加节点

时间:2014-09-02 11:45:48

标签: ruby-on-rails ruby nokogiri

我有一个HTML字符串(例如<div class="input">hello</div>),我只想在字符串中的HTML标记是label(例如<label>Hi</label>)时才添加节点。 / p>

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

2 个答案:

答案 0 :(得分: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>的现有子节点,这意味着在包含文本节点之后附加了 &#34;你好&#34;

如果您想覆盖孩子,可以使用children =轻松完成:

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

结果是:

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

children =可以使用单个节点,该节点可以包含多个其他节点,或者插入的节点的HTML文本。这是node_or_tagsthe 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')是查找特定节点的一种方法。它基本上意味着&#34;在第一个div中找到第一个标签标签&#34;。 at表示找到第一个内容,与使用search(...).first类似。如果您需要,Nokogiri::XML::Node documentation中的atsearch都有CSS和XPath等效项。

答案 1 :(得分: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)行。