require 'rubygems' require 'metaid' class XML # blank slate instance_methods.each { |m| undef_method m unless (m =~ /^__|instance_eval|meta/)} # Each item in @doc is an array containing three values: type, value, attributes def initialize(&block) @doc = [] instance_eval(&block) end def method_missing(tag, *args, &block) meta_def(tag) do |*args| @__to_s = nil # invalidate to_s cache if block @doc << [:open, tag, args.first] instance_eval(&block) @doc << [:close, tag] else value, atts = args.pop, args.pop subtags, atts = atts, nil if atts.is_a?(Array) if subtags @doc << [:open, tag, atts] subtags.each {|k| __send__(k, value[k])} @doc << [:close, tag] else @doc << [:open, tag, atts] << [:value, value] << [:close, tag] end end end __send__(tag, *args) end def instruct!(atts = nil) @doc << [:instruct, atts || {:version => "1.0", :encoding => "UTF-8"}] end def to_s @__to_s ||= @doc.map{|i| _fmt_part i}.join end alias_method :inspect, :to_s def _fmt_part(part) case part[0] when :instruct "" when :open part[2] ? "<#{part[1]} #{_fmt_atts(part[2])}>" : "<#{part[1]}>" when :close "" when :value part[1].to_s end end def _fmt_atts(atts) atts.inject([]) {|m, i| m << "#{i[0]}=#{i[1].to_s.inspect}"}.join(' ') end end def t1(list) xml = XML.new do instruct! reality(:time => Time.now) do event do type 1 path "/sharon" value "abcdefg" end list.each {|i| item i} end end xml.to_s end puts "**************" x = 10000 list = (1..x).map { {:quality => rand(5), :value => rand(77865)} } t1 = Time.now xml = XML.new do states {list.each {|s| state [:quality, :value], s}} end t2 = Time.now s = xml.to_s t3 = Time.now e1 = t2 - t1 e2 = t3 - t2 r1 = x / e1 r2 = x / e2 e3 = e1 + e2 r3 = x / e3 puts "build: #{e1} (#{r1}); format: #{e2} (#{r2}); total: #{e3} (#{r3})" __END__ class EventsController < ServerSide::Controller::Base.mount('/events/:format') invoke_by_parameter :format, :default => :html def before_response @events = Events.select end def xml render_xml('text/xml+svg') do events @events.to_xml end end end xml = XML.new do instruct! reality(:time => Time.now) do event do type 1 path "/sharon" value "abcdefg" end list.each {|i| item i} end end xml.to_s