views:

93

answers:

2

I have some XHTML (but really any XML will do) like this:

<h1>
  Hello<span class='punctuation'>,</span>
  <span class='noun'>World<span class='punctuation'>!</span>
</h1>

How do I get the full content of the <h1/> as a String in Ruby? As in:

assert_equal "Hello, World!", h1_node.some_method_that_aggregates_all_content

Do any of the XML frameworks (Nokogiri, libxml-ruby, &c.) have this sort of thing built-in? If not, I feel like a Y-Combinator might the right tool for the job, but I can't quite figure out what it would look like.

+3  A: 

With Nokogiri you can just ask for the text of a node. The issue I see when doing that though is that all of the whitespace and newlines that are in that node will be returned, so you might want to strip those out (likely a better way to do that than what I did for this example).

Here is a sample:

def test_nokogiri_text
  value = Nokogiri::HTML.parse(<<-HTML_END)
    "<h1>
      Hello<span class='punctuation'>,</span>
      <span class='noun'>World<span class='punctuation'>!</span>
     </h1>"
  HTML_END

  h1_node = value.search("h1").first
  assert_equal("Hello, World!", h1_node.text.split(/\s+/).join(' ').strip)
end
Aaron Hinni
If I'm going to be turning all the newlines into spaces anyway (which is totally fine, since XML treats them as equivalent), then h1_note.text.gsub(/\s+/, ' ').strip works the same and is a little faster, since it doesn't need to create as many new objects.
James A. Rosen
+1  A: 

Nokogiri's Nokogiri::XML::Node#content will do it:

irb(main):020:0> node
=> <h1>
  Hello<span class="punctuation">,</span>
  <span class="noun">World<span class="punctuation">!</span>
</span>
</h1>
irb(main):021:0> node.content
=> "\n  Hello,\n  World!\n\n"
Pesto
#text and #content are the same, so Aaron got the "Answer" b/c he also took care of the whitespace. +1, though :)
James A. Rosen
Plus, he posted his answer first.
Pesto