YAML2XML in 33 lines or your money back

Posted by Ben Jackson Fri, 23 Sep 2005 18:44:00 GMT

After spending more than a few hours trying to find a decent YAML2XML converter, struggling with CPAN to install the required perl modules for the hack that I found and finding that the output was buggy and incomplete, I decided to have a shot at doing it myself and learn about ruby's XML libraries in the process.

Two and a half hours and 33 lines of code later and I've got a basic converter that will work with sephiroth's XML2Object library for Actionscript. The secret (courtesy of Jim Weirich) is the use of builder.method_missing() to pass an arbitrary tag name instead of the usual syntax:

# normal usage
builder.div {
  builder.p("hello world!")
}

# equivalent
builder.method_missing("div") {
  builder.method_missing("p", "hello world!")
}

Here's the final script:

# yaml2xml.rb
# converts a yaml document to a corresponding xml 
# format for use with XML2Object class from sephiroth.it
# for more details on the class visit
#   http://www.sephiroth.it/file_detail.php?pageNum_comments=10&id=129
# usage: ruby yaml2xml.rb input.yml > output.xml

require 'yaml' 
require 'rubygems'
require_gem 'builder'

@builder = Builder::XmlMarkup.new(:target=>STDOUT, :indent=>2)

def yaml2xml src, tagname="root"
  unless src.is_a?(Array)
    @builder.method_missing(tagname) {
      process_source src, tagname
    }
  else
    process_source src, tagname
  end
end

def process_source src, tagname
  if src.is_a?(Hash)
    src.each do |name, value|
      unless value.kind_of?(Hash) or value.kind_of?(Array)
        @builder.method_missing(name, value)
      else 
        yaml2xml value, name
      end
    end
  elsif src.is_a?(Array)
    src.each do |value|
      yaml2xml value, tagname
    end
  end
end

yaml2xml YAML::load(File.open(ARGV[0]))

Posted in  | 1 comment | no trackbacks

Comments

  1. ondrej said 3 months later:

    ! /usr/bin/python

    you need syck (python2.3-syck package on debian)

    usage: yaml2xml input.yml > output.xml

    import sys,syck,yaml2xml print yaml2xml.yaml2xml(syck.load(file(sys.argv[1]).read()))

Trackbacks

Use the following link to trackback from your own site:
http://www.unfitforprint.com/trackbacks?article_id=yaml2xml-in-33-lines-or-your-money-back&day=23&month=09&year=2005

Comments are disabled