我有一个HTML字符串(例如<div class="input">hello</div>
),并且只有当字符串中的HTML标记是label
(例如<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", 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
添加/更改/删除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
时,它就是这个意思。
也就是说,要更改嵌入的<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可以让你在指向标签后很容易地更改标签的名称。你可以通过用你想要的任何内容替换#{ label.text }
来轻松地更改<span>
中的文本。
CCD_ 12是查找特定节点的一种方式。它的基本意思是"在第一个div中找到第一个标签标签"。at
的意思是找到某物的第一个,类似于使用search(...).first
。如果需要的话,Nokogiri::XML::Node文档中有与at
和search
等效的CSS和XPath。
几个问题-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)
行。