如何在一个跨度中包装Nokogiri节点集

时间:2014-02-22 16:43:12

标签: ruby nokogiri

所以我的目标是在一个范围内包装初始段落之后的所有段落。我试图弄清楚如何在单个范围内包装节点集,并且.wrap()将每个节点包装在自己的范围内。如想要:

<p>First</p>
<p>Second</p>
<p>Third</p>

成为:

<p>First</p>
<span>
<p>Second</p>
<p>Third</p>
</span>

任何示例代码都有帮助吗?谢谢!

2 个答案:

答案 0 :(得分:1)

我会这样做:

require 'nokogiri'

doc =  Nokogiri::HTML::DocumentFragment.parse(<<-html)
<p>First</p>
<p>Second</p>
<p>Third</p>
html

nodeset = doc.css("p")
new_node = Nokogiri::XML::Node.new('span',doc)
new_node << nodeset[1..-1]
nodeset.first.after(new_node)
puts doc.to_html
# >> <p>First</p><span><p>Second</p>
# >> <p>Third</p></span>
# >> 

答案 1 :(得分:0)

我会这样做:

require 'nokogiri'

html = '<p>First</p>
<p>Second</p>
<p>Third</p>
'

doc = Nokogiri::HTML(html)

paragraphs = doc.search('p')[1..-1].unlink 
doc.at('p').after('<span>')
doc.at('span').add_child(paragraphs)
puts doc.to_html

这导致HTML看起来像:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body>
<p>First</p>
<span><p>Second</p>
<p>Third</p></span>

</body></html>

为了让您知道发生了什么,这是一个更详细的输出,显示doc的中间变化:

paragraphs = doc.search('p')[1..-1].unlink 
paragraphs.to_html 
# => "<p>Second</p><p>Third</p>"
doc.at('p').after('<span>')
doc.to_html 
# => "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html><body>\n<p>First</p>\n<span></span>\n\n</body></html>\n"
doc.at('span').add_child(paragraphs)
doc.to_html
# => "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html><body>\n<p>First</p>\n<span><p>Second</p>\n<p>Third</p></span>\n\n</body></html>\n"

查看最初的HTML,我不确定所提出的问题是否适用于普通的日常HTML,但是,如果您完全确定它永远不会改变

<p>...</p>
<p>...</p>
<p>...</p>

布局然后你应该没问题。如果HTML确实类似于:

,那么基于初始样本HTML的任何答案都会惨不忍睹
<div>
  <p>...</p>
  <p>...</p>
  <p>...</p>
</div>
...
<div>
  <p>...</p>
  <p>...</p>
  <p>...</p>
</div>