Skip to content

Instantly share code, notes, and snippets.

@arjunmenon
Forked from kimjoar/create_xml.rb
Created June 12, 2018 12:01
Show Gist options
  • Save arjunmenon/f8e628c0b91c0001e161b310679456b8 to your computer and use it in GitHub Desktop.
Save arjunmenon/f8e628c0b91c0001e161b310679456b8 to your computer and use it in GitHub Desktop.
Simple Ruby DSL to generate XML

I've tried to do some thing differently from Jonas and Torgeir.

Some notes:

  • I've used 1.9 hash syntax
  • I've tried to remove most variables, and use methods instead (I like reading xml instead of @xml)
  • I don't like the fact that I have to join the result, as it's now an array, not a string
  • I tried to use a block to handle indentation
require './xmldsl'
Twitter = Struct.new :name, :avatar, :text
twitters = []
5.times { twitters << Twitter.new("Jonas", "/profile.png", "Hello World!") }
xml = XML.generate do
html do
body do
twitters.each do |tw|
img src: tw.avatar, alt: tw.name, width: 25, height: 25
content [" : ", tw.text]
br
br
end
form action: '/page', method: 'post' do
input type: 'text', name: 'str', maxlength: 3, size: 3
input type: 'submit', value: 'page'
end
end
end
end
open('sample_twitters.html', 'w') {|f| f.puts xml}
puts xml
class XML
def self.generate &block
XML.new.xml_generate &block
end
def xml_generate &block
instance_eval(&block).join
end
def xml
@xml or @xml = []
end
def method_missing name, args = {}
xml << "#{indent}<#{name} #{attributes(args)}"
if block_given?
xml << ">\n"
indent do
yield
end
xml << "#{indent}</#{name}>\n"
else
xml << "/>\n"
end
end
def indent
@indent or @indent = 0
if block_given?
@indent += 3
yield
@indent -= 3
else
" "*@indent
end
end
def attributes args
args.map { |key, value| "#{key}='#{value}'"}.join(" ")
end
def content txt
xml << "#{indent}#{[txt].join}\n"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment