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

僤鯓⒐⒋嵵緔 提交于 2019-11-30 07:00:13
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

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.

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.

I've changed the <root> element to <rootElement> so this is more clear:

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

Now, builder.to_xml will return:

<?xml version="1.0"?>
<foo:rootElement xmlns:foo="my-ns-url" xmlns:bar="http://example.com/bar">
  <foo:child/>
  <bar:child/>
</foo:rootElement>

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

Three years after Luke's answer, it's gotten yet simpler. You can now use the namespace "before" it's defined. This code:

require 'nokogiri'

NAMESPACES = { 'xmlns:foo' => 'bar', 'xmlns:baz' => 'bat' }

builder = Nokogiri::XML::Builder.new { |xml|
  xml['foo'].RootElement(NAMESPACES) {
    xml['baz'].FirstChild
  }
}

puts builder.to_xml

Outputs this XML:

<?xml version="1.0"?>
<foo:RootElement xmlns:foo="bar" xmlns:baz="bat">
  <baz:FirstChild/>
</foo:RootElement>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!