Nokogiri builder can be used for building XML and HTML documents.
builder = Nokogiri::XML::Builder.new do |xml| xml.root { xml.products { xml.widget { xml.id_ "10" xml.name "Awesome widget" } } } end puts builder.to_xml
Will output:
<?xml version="1.0"?> <root> <products> <widget> <id>10</id> <name>Awesome widget</name> </widget> </products> </root>
The builder allows two forms. When the builder is supplied with a block that has a parameter, the outside scope is maintained. This means you can access variables that are outside your builder. If you don’t need outside scope, you can use the builder without the “xml” prefix like this:
builder = Nokogiri::XML::Builder.new do root { products { widget { id_ "10" name "Awesome widget" } } } end
The builder works by taking advantage of method_missing. Unfortunately some methods are defined in ruby that are difficult or dangerous to remove. You may want to create tags with the name “type”, “class”, and “id” for example. In that case, you can use an underscore to disambiguate your tag name from the method call.
Here is an example of using the underscore to disambiguate tag names from ruby methods:
@objects = [Object.new, Object.new, Object.new] builder = Nokogiri::XML::Builder.new do |xml| xml.root { xml.objects { @objects.each do |o| xml.object { xml.type_ o.type xml.class_ o.class.name xml.id_ o.id } end } } end puts builder.to_xml
The underscore may be used with any tag name, and the last underscore will just be removed. This code will output the following XML:
<?xml version="1.0"?> <root> <objects> <object> <type>Object</type> <class>Object</class> <id>48390</id> </object> <object> <type>Object</type> <class>Object</class> <id>48380</id> </object> <object> <type>Object</type> <class>Object</class> <id>48370</id> </object> </objects> </root>
Tag attributes may be supplied as method arguments. Here is our previous example, but using attributes rather than tags:
@objects = [Object.new, Object.new, Object.new] builder = Nokogiri::XML::Builder.new do |xml| xml.root { xml.objects { @objects.each do |o| xml.object(:type => o.type, :class => o.class, :id => o.id) end } } end puts builder.to_xml
A couple attribute short cuts are available when building tags. The short cuts are available by special method calls when building a tag.
This example builds an “object” tag with the class attribute “classy” and the id of “thing”:
builder = Nokogiri::XML::Builder.new do |xml| xml.root { xml.objects { xml.object.classy.thing! } } end puts builder.to_xml
Which will output:
<?xml version="1.0"?> <root> <objects> <object class="classy" id="thing"/> </objects> </root>
All other options are still supported with this syntax, including blocks and extra tag attributes.
Namespaces are added similarly to attributes. Nokogiri::XML::Builder assumes that when an attribute starts with “xmlns”, it is meant to be a namespace:
builder = Nokogiri::XML::Builder.new { |xml| xml.root('xmlns' => 'default', 'xmlns:foo' => 'bar') do xml.tenderlove end } puts builder.to_xml
Will output XML like this:
<?xml version="1.0"?> <root xmlns:foo="bar" xmlns="default"> <tenderlove/> </root>
Tags that reference non-default namespaces (i.e. a tag “foo:bar”) can be built by using the Nokogiri::XML::Builder#[] method.
For example:
builder = Nokogiri::XML::Builder.new do |xml| xml.root('xmlns:foo' => 'bar') { xml.objects { xml['foo'].object.classy.thing! } } end puts builder.to_xml
Will output this XML:
<?xml version="1.0"?> <root xmlns:foo="bar"> <objects> <foo:object class="classy" id="thing"/> </objects> </root>
Note the “foo:object” tag.
To create a document type (DTD), access use the Builder#doc method to get the current context document. Then call Node#create_internal_subset to create the DTD node.
For example, this Ruby:
builder = Nokogiri::XML::Builder.new do |xml| xml.doc.create_internal_subset( 'html', "-//W3C//DTD HTML 4.01 Transitional//EN", "http://www.w3.org/TR/html4/loose.dtd" ) xml.root do xml.foo end end puts builder.to_xml
Will output this xml:
<?xml version="1.0"?> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <root> <foo/> </root>
Create a new Builder object. options are sent to the top level Document that is being built.
Building a document with a particular encoding for example:
Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml| ... end
# File lib/nokogiri/xml/builder.rb, line 266 266: def initialize options = {}, root = nil, &block 267: 268: if root 269: @doc = root.document 270: @parent = root 271: else 272: namespace = self.class.name.split('::') 273: namespace[1] = 'Document' 274: @doc = eval(namespace.join('::')).new 275: @parent = @doc 276: end 277: 278: @context = nil 279: @arity = nil 280: @ns = nil 281: 282: options.each do |k,v| 283: @doc.send(:"#{k}=", v) 284: end 285: 286: return unless block_given? 287: 288: @arity = block.arity 289: if @arity <= 0 290: @context = eval('self', block.binding) 291: instance_eval(&block) 292: else 293: yield self 294: end 295: 296: @parent = @doc 297: end
Create a builder with an existing root object. This is for use when you have an existing document that you would like to augment with builder methods. The builder context created will start with the given root node.
For example:
doc = Nokogiri::XML(open('somedoc.xml')) Nokogiri::XML::Builder.with(doc.at('some_tag')) do |xml| # ... Use normal builder methods here ... xml.awesome # add the "awesome" tag below "some_tag" end
# File lib/nokogiri/xml/builder.rb, line 253 253: def self.with root, &block 254: new({}, root, &block) 255: end
Append the given raw XML string to the document
# File lib/nokogiri/xml/builder.rb, line 335 335: def << string 336: @doc.fragment(string).children.each { |x| insert(x) } 337: end
Build a tag that is associated with namespace ns. Raises an ArgumentError if ns has not been defined higher in the tree.
# File lib/nokogiri/xml/builder.rb, line 314 314: def [] ns 315: @ns = @parent.namespace_definitions.find { |x| x.prefix == ns.to_s } 316: return self if @ns 317: 318: @parent.ancestors.each do |a| 319: next if a == doc 320: @ns = a.namespace_definitions.find { |x| x.prefix == ns.to_s } 321: return self if @ns 322: end 323: 324: raise ArgumentError, "Namespace #{ns} has not been defined" 325: end
Insert node as a child of the current Node
# File lib/nokogiri/xml/builder.rb, line 357 357: def insert(node, &block) 358: node.parent = @parent 359: if block_given? 360: old_parent = @parent 361: @parent = node 362: @arity ||= block.arity 363: if @arity <= 0 364: instance_eval(&block) 365: else 366: block.call(self) 367: end 368: @parent = old_parent 369: end 370: NodeBuilder.new(node, self) 371: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.