Rectangle 27 1

ruby Creating an XML document with a namespaced root element with Nokogiri builder?


<?xml version="1.0"?>
<foo:rootElement xmlns:foo="my-ns-url" xmlns:bar="http://example.com/bar">
  <foo:child/>
  <bar:child/>
</foo:rootElement>
<root>
<rootElement>
builder = Nokogiri::XML::Builder.new do |xml| 
  xml.rootElement do
    # create a namespace and save it for later
    ns = xml.doc.root.add_namespace_definition('foo', 'my-ns-url')
    # you can also create multiple name spaces
    xml.doc.root.add_namespace_definition('bar', 'http://example.com/bar')

    # assign the saved namespace to rootElement
    xml.doc.root.namespace = ns

    xml['foo'].child
    xml['bar'].child
  end
end
builder.to_xml

I like this better because you don't have to search for the name space, and it's easier to add multiple namespaces.

This works great. Thanks. However, I am unable to get rid of the namespace inheritance. I want to achieve something like the following. <?xml version="1.0"?> <foo:rootElement xmlns:foo="my-ns-url" xmlns:bar="example.com/bar" <child> value </child> </foo:rootElement>

Two years later, I found a cleaner way to do this by using Nokogiri::XML::Builder's document reference to retrieve the root node and add the namespace(s) to that. Like the previous solution, it requires the root node to exist before the namespaces can be added to it.

Note
Rectangle 27 1

ruby Creating an XML document with a namespaced root element with Nokogiri builder?


require 'rubygems'
require 'nokogiri'

puts Nokogiri::XML::Builder.new { |xml| 
  xml.root("xmlns:foo"=>"url") {
    xml.parent.namespace = xml.parent.namespace_definitions.find{|ns|ns.prefix=="foo"}
    xml['foo'].child
  }
}.to_xml

Note that this is fine if there's only one namespace, or maybe if you're working under Ruby 1.9 and thus can rely on the order of the hash arguments to be the same. Otherwise, I would recommend xml.parent.namespace = xml.parent.namespace_definitions.find{ |ns| ns.prefix=="foo" } (or use the ns.href if you're not sure what the prefix might have been named).

Works like a charm. Thanks!

You cannot use xml['foo'] before the namespace is defined, ie before you pass it as an argument to the root node. Thus, the code above add the namespace after-the-fact to the root node.

Note
Rectangle 27 1

ruby Creating an XML document with a namespaced root element with Nokogiri builder?


require 'rubygems'
require 'nokogiri'

puts Nokogiri::XML::Builder.new { |xml| 
  xml.root("xmlns:foo"=>"url") {
    xml.parent.namespace = xml.parent.namespace_definitions.find{|ns|ns.prefix=="foo"}
    xml['foo'].child
  }
}.to_xml

Note that this is fine if there's only one namespace, or maybe if you're working under Ruby 1.9 and thus can rely on the order of the hash arguments to be the same. Otherwise, I would recommend xml.parent.namespace = xml.parent.namespace_definitions.find{ |ns| ns.prefix=="foo" } (or use the ns.href if you're not sure what the prefix might have been named).

Works like a charm. Thanks!

You cannot use xml['foo'] before the namespace is defined, ie before you pass it as an argument to the root node. Thus, the code above add the namespace after-the-fact to the root node.

Note