Skip to content

Instantly share code, notes, and snippets.

@julik
Created April 17, 2010 13:35
Show Gist options
  • Save julik/369543 to your computer and use it in GitHub Desktop.
Save julik/369543 to your computer and use it in GitHub Desktop.
# An XML writer for Ruby's XML RPC module
require 'rubygems'
require 'builder'
# The default XML serializer in Ruby's XML RPC module is VERY sloppy.
# We use Jim Weirich's excellent Builder to generate clean XML, even though it costs us some extra
# performance
class RPCBuilder
# This is what is going to be lugged around as XML RPC results. It's actually
# a node element
class Command
attr_accessor :text, :name, :children
def initialize
@text, @name, @children = nil, nil, []
yield(self) if block_given?
end
def inspect
'<#Command @name=%s @text=%s @children=%s' % [ name, text, children.length]
end
end
# Should return a prebaked element. It saves us that native Builder uses tag!
def tag(name, txt)
Command.new { | c | c.name = name; c.text = txt }
end
def document_to_str(command_tree)
@builder = Builder::XmlMarkup.new
@builder.instruct!
# Play the command tree to builder inside, do not run twice
command_to_builder_call(command_tree)
@builder.target!
end
# Make a document and stuff things into it. Document is actually a nothing thing.
def document(*stuff)
stuff
end
# noop, a processing instruction
def pi(name, *params); end
def ele(name, *children)
# Make an element with name and attributes
Command.new { |c| c.name = name; c.children = children }
end
# Should return the text escaped as XML cdata
def text(txt)
Command.new { |c| c.text = txt }
end
private
# This will convert a tree of commands into XML Builder calls
def command_to_builder_call(cmd)
case cmd
when NilClass
# pass
when Array
cmd.compact.each{|c| command_to_builder_call(c) }
when Command
if cmd.name
@builder.tag!(cmd.name) { @builder.text!(cmd.text.to_s.strip) if cmd.text; command_to_builder_call(cmd.children) }
else
@builder.text!(cmd.text)
end
when String
@builder.text!(cmd.strip) unless cmd.empty?
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment