If you are Google for "nokogiri xml builder namespace" , the first hit is the Nokogiri documentation page , which says:
Namespaces are added in the same way as attributes. Nokogiri::XML::Builder assumes that when an attribute begins with "xmlns", it must be a namespace:
builder = Nokogiri::XML::Builder.new { |xml| xml.root('xmlns' => 'default', 'xmlns:foo' => 'bar') do xml.tenderlove end } puts builder.to_xml
Output XML as follows:
<?xml version="1.0"?> <root xmlns:foo="bar" xmlns="default"> <tenderlove/> </root>
Applying this to your specific question, simply do:
require 'nokogiri' NS = { "xmlns:p" => "http://www.acme.com", "xmlns:p1" => "http://www.acme.com/datatypes", "xmlns:p2" => "http://www.acme.com/ACMRequestdatatypes", "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance", } builder = Nokogiri::XML::Builder.new { |xml| xml.ACMRequest(NS) do xml.GetQuote end } puts builder.to_xml
Regarding the namespace prefix on the root element itself ...
<p:ACMRequest xmlns:p="…">…</p:ACMRequest>
... I cannot figure out how to apply the namespace prefix to the first element in Nokogiri at creation time. Instead, you should apply the namespace after creating the document:
root = builder.doc.root acme = root.namespace_definitions.find{ |ns| ns.href==NS["xmlns:p"] } root.namespace = acme puts builder.to_xml
Alternatively, you can cheat:
Per " Creating an XML document with a root element with a namespace using Nokogiri builder " you can alternatively do this during creation with a little hack:
builder = Nokogiri::XML::Builder.new { |xml| xml.ACMRequest(NS) do xml.parent.namespace = …