tags:

views:

39

answers:

1

I'd like to use Nokogiri to insert nodes into an XML document. Nokogiri uses the Nokogiri::XML::Builder class to insert or create new XML.

If I create XML using the new method, I'm able to create nice, formatted XML:

builder = Nokogiri::XML::Builder.new do |xml|
  xml.product {
    xml.test "hi"
  }
end

puts builder

outputs the following:

<?xml version="1.0"?>
<product>
  <test>hi</test>
</product>       

That's great, but what I want to do is add the above XML to an existing document, not create a new document. According to the Nokogiri documentation, this can be done by using the Builder's with method, like so:

builder = Nokogiri::XML::Builder.with(document.at('products')) do |xml|
  xml.product {
    xml.test "hi"
  }
end

puts builder

When I do this, however, the XML all gets put into a single line with no indentation. It looks like this:

<products><product><test>hi</test></product></products>

Am I missing something to get it to format correctly?

+1  A: 

Found the answer in the Nokogiri mailing list:

In XML, whitespace can be considered meaningful. If you parse a document that contains whitespace nodes, libxml2 will assume that whitespace nodes are meaningful and will not insert them for you.

You can tell libxml2 that whitespace is not meaningful by passing the "noblanks" flag to the parser. To demonstrate, here is an example that reproduces your error, then does what you want:

require 'nokogiri'
def build_from node
  builder = Nokogiri::XML::Builder.with(node) do|xml|
    xml.hello do
      xml.world
    end
  end
end

xml = DATA.read
doc = Nokogiri::XML(xml)
puts build_from(doc.at('bar')).to_xml
doc = Nokogiri::XML(xml) { |x| x.noblanks }
puts build_from(doc.at('bar')).to_xml

Output:

<root>
  <foo>
    <bar>
      <baz />
    </bar>
  </foo>
</root>
michaelmichael
I was looking for a flag the other day when I saw your question, but got distracted shaving a yak. +1 to you for finding the answer and posting it, and +1 to Nokogiri for rocking.
Greg
understandable. those yaks don't shave themselves (yet).
michaelmichael