How to move a node using Hpricot

32 views Asked by At

I am using Hpricot to select a <div> element from a web page:

doc = open("overview.html") { |f| Hpricot(f) }
puts doc.search("div[@class=leftnav-btn]")

I want to copy that element and paste it to under other <div> element with class="secondDiv".

How can I do this?

1

There are 1 answers

0
the Tin Man On

I'd do it like this:

require 'nokogiri'

div1 = doc.at('div.leftnav-btn').remove
doc.at('div.secondDiv').add_next_sibling(div1)
puts doc.to_html

# >> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
# >> <html>
# >>   <body>
# >>     
# >>     <div class="secondDiv"></div>
# >> <div class="leftnav-btn">foo</div>
# >>   </body>
# >> </html>

The empty line after <body> is the result of the trailing TextNode that follows the <div> tag. It doesn't affect how XML works, nor does it affect the data, it's only cosmetic.

doc.at('.leftnav-btn').next.class # => Nokogiri::XML::Text
doc.at('.leftnav-btn').next.to_html # => "\n    "

Notice that in the above selector I'm only using the class .leftnav-btn since it wasn't necessary to use the full div.leftnav-btn. Nokogiri, like Hpricot, uses CSS selectors, and also allows XPath, making for more flexibility. Nokogiri also supports % and / though we don't use them:

(doc % '.leftnav-btn').next.class # => Nokogiri::XML::Text
(doc % '.leftnav-btn').next.to_html # => "\n    "

Hpricot was deprecated a long time ago, and shouldn't be used. Nokogiri is the standard for HTML/XML parsing for Ruby.

The Nokogiri tutorials cover the basics so spend some time with them. See the documentation for Nokogiri::XML::Node and Nokogiri::XML::NodeSet for more information.