rsxml

A Ruby library to translate XML documents into an s-expression representation, and back again, in the style of SXML

Why would you want to do this ? Well, s-expressions can be == compared natively in Ruby, are easy to read and editors indent them nicely when embedded in code. These features make them very suitable for writing readable XML generation code and readable tests for XML generating code

Rsxml uses Nokogiri for parsing XML, and Builder to generate it. Rsxml is not intended to be a feature complete XML representation : It does not attempt to represent PIs, CDATA etc, but it does make it very easy to use and generate straightforward XML documents from Ruby

Rsxml represents XML documents as s-expressions thus :

["Foo", {"foofoo"=>"10"}, ["Bar", "barbar"], ["Baz"]]

represents the XML document :

<Foo foofoo="10"><Bar>barbar</Bar><Baz></Baz></Foo>

It is easy to convert XML docuemnts to Rsxml representation and back again :

xml = Rsxml.to_xml(["Foo", {"foofoo"=>"10"}, ["Bar", "barbar"]])
  => '<Foo foofoo="10"><Bar>barbar</Bar></Foo>'

Rsxml.to_rsxml(xml)
  => ["Foo", {"foofoo"=>"10"}, ["Bar", "barbar"]]

Namespaces

XML namespaces are dealt with straightforwardly. When an XML document is converted to Rsxml, namespaces are preserved, and you can specify namespaces in an Rsxml structure in two ways

  • using QName prefixes and declarative attributes, exactly as with XML

  • using exploded QNames consisting of [local_name, prefix, uri] triples and [local_name, prefix] pairs

Converting to Rsxml

When you convert an XML document to Rsxml you can choose either :xml or :exploded style

:xml style

In :xml style namespaces are declared using attributes, and namespaces are referenced using prefixed QNames, just as in XML

Rsxml.to_rsxml('<foo:foofoo xmlns:foo="http://foo.com/foo" foo:bar="barbar"/>', :style=>:xml)
  => ["foo:foofoo", {"foo:bar"=>"barbar", "xmlns:foo"=>"http://foo.com/foo"}]

:exploded style

In :exploded style namespaces are not declared using attributes, and QNames are specified using [local_name, prefix, uri] triples

Rsxml.to_rsxml('<foo:foofoo xmlns:foo="http://foo.com/foo" foo:bar="barbar"/>', :style=>:exploded)
  => [["foofoo", "foo", "http://foo.com/foo"], {["bar", "foo", "http://foo.com/foo"]=>"barbar"}]

Converting to XML

Rsxml styles can be mixed, and unnecessary namespace references can be skipped for readability

Rsxml.to_xml([["foofoo", "foo", "http://foo.com/foo"], {"foo:bar"=>"1", ["baz", "foo"]=>"2"}])
  => '<foo:foofoo foo:baz="2" foo:bar="1" xmlns:foo="http://foo.com/foo"></foo:foofoo>'

Fragments

XML Fragments, without proper namespace declarations, can be parsed by passing a Hash of namespace prefix bindings

Rsxml.to_rsxml('<foo:foofoo foo:bar="barbar"/>', :ns=>{"foo"=>"http://foo.com/foo"}, :style=>:xml)
  => ["foo:foofoo", {"foo:bar"=>"barbar"}]

Fragments can be generated similarly :

Rsxml.to_xml(["foo:foofoo", {"foo:bar"=>"barbar"}], :ns=>{"foo"=>"http://foo.com/foo"})
  => '<foo:foofoo foo:bar="barbar"></foo:foofoo>'

Install

gem install rsxml

Contributing to rsxml

  • Check out the latest master to make sure the feature hasn’t been implemented or the bug hasn’t been fixed yet

  • Check out the issue tracker to make sure someone already hasn’t requested it and/or contributed it

  • Fork the project

  • Start a feature/bugfix branch

  • Commit and push until you are happy with your contribution

  • Make sure to add tests for it. This is important so I don’t break it in a future version unintentionally.

  • Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.

Copyright © 2011 Trampoline Systems Ltd. See LICENSE.txt for further details.