Skip to content

Instantly share code, notes, and snippets.

@kimjoar
Created May 23, 2012 06:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kimjoar/2773597 to your computer and use it in GitHub Desktop.
Save kimjoar/2773597 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
@Tails
Copy link

Tails commented Sep 15, 2017

Does it work with hyphenated xml element names?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment