I like the Nokogiri::XML::Builder
construct, but it would be easier to assemble large XML documents if I could modularize the building process further by splitting the job among several builders.
Does anybody see a way to get multiple builders to cooperate? (for instance, a parent builder calling functions that set child builders to create smaller portions of the document)
Or is there a way to modify a builder after its block terminates? (---short of outputting XML, then parsing it into a Nokogiri::XML::Document, then adding nodes, then outputting XML again)
for instance, a parent builder calling functions that set child builders to create smaller portions of the document
You can easily delegate responsibility to methods that take the builder's current state and use it. For example:
require 'nokogiri'
def add_kids_for(name,xml)
xml.send(name){ 1.upto(3){ |i| xml.kid("#{name}'s kid ##{i}") } }
end
build = Nokogiri::XML::Builder.new do |xml|
xml.root do
add_kids_for("Danny",xml)
add_kids_for("Billy",xml)
end
end
puts build.to_xml
#=> <?xml version="1.0"?>
#=> <root>
#=> <Danny>
#=> <kid>Danny's kid #1</kid>
#=> <kid>Danny's kid #2</kid>
#=> <kid>Danny's kid #3</kid>
#=> </Danny>
#=> <Billy>
#=> <kid>Billy's kid #1</kid>
#=> <kid>Billy's kid #2</kid>
#=> <kid>Billy's kid #3</kid>
#=> </Billy>
#=> </root>
Just pass the xml
(or whatever you call your builder object) to the method and let that method do what it needs to (either procedurally or manually).
Or is there a way to modify a builder after its block terminates?
Yes! :) You want to the doc
method of the Builder to get the Nokogiri::XML::Document
driving it. Carrying on the above example:
doc = build.doc
doc.css('kid').each do |kid|
kid['name'] = %w[Bobby Jenny Jill Sam Gish Gavin Lisa Imogen Lachlan].sample
end
puts doc
#=> <root>
#=> <Danny>
#=> <kid name="Lisa">Danny's kid #1</kid>
#=> <kid name="Imogen">Danny's kid #2</kid>
#=> <kid name="Lachlan">Danny's kid #3</kid>
#=> </Danny>
#=> <Billy>
#=> <kid name="Gish">Billy's kid #1</kid>
#=> <kid name="Gavin">Billy's kid #2</kid>
#=> <kid name="Sam">Billy's kid #3</kid>
#=> </Billy>
#=> </root>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With