ROXML Ruby Object to XML mapping library. For more information visit http://roxml.rubyforge.org =Quick Start Guide This is a short usage example. See ROXML::ClassMethods::Declarations and packaged test cases for more information. ==Basic Mapping Consider an XML document representing a Library containing a number of Books. You can map this structure to Ruby classes that provide addition useful behavior. With ROXML, you can annotate the Ruby classes as follows: class Book include ROXML xml_reader :isbn, :from => "@ISBN" # attribute with name 'ISBN' xml_reader :title xml_reader :description, :cdata => true # text node with cdata protection xml_reader :author end class Library include ROXML xml_accessor :name, :from => "NAME", :cdata => true xml_accessor :books, :as => [Book] end To create a library and put a number of books in it we could run the following code: book = Book.new() book.isbn = "0201710897" book.title = "The PickAxe" book.description = "Best Ruby book out there!" book.author = "David Thomas, Andrew Hunt, Dave Thomas" lib = Library.new() lib.name = "Favorite Books" lib << book To save this information to an XML file: File.open("library.xml", "w") do |f| lib.to_xml.write(f, 0) end To later populate the library object from the XML file: lib = Library.from_xml(File.read("library.xml")) Similarly, to do a one-to-one mapping between XML objects, such as book and publisher, you would add a reference to another ROXML class. For example: Programming Ruby - 2nd Edition Second edition of the great book. Pragmatic Bookshelf can be mapped using the following code: class BookWithPublisher include ROXML xml_name :book xml_reader :publisher, :as => Publisher end Note: In the above example, _xml_name_ annotation tells ROXML to set the element name to "book" for mapping to XML. The default is XML element name is the class name in lowercase; "bookwithpublisher" in this case. == Manipulation Extending the above examples, say you want to parse a book's page count and have it available as an Integer. In such a case, you can extend any object with a block to manipulate it's value at parse time. For example: class Dog include ROXML xml_reader(:age, :from => '@human_years', :as => Integer) {|years| years * 7 } end The result of the block above is stored, rather than the actual value parsed from the document. == Construction Object lifecycle is as follows: .from_xml is called with option initialization_args. .new, and thus #initialize, is called with those same args. Then the object is populated with the attribute values from xml. Then the #after_parse callback is called, with no arguments. In it you can ensure that your object initialization is complete, including initialization which requires more than one variable in concert. E.g.: class Measurement include ROXML xml_reader :units, :from => :attr xml_reader :value, :from => :content def initialize(value = 0, units = 'meters') to_metric end private def after_parse # xml attributes of self are already valid to_metric end def to_metric # translate units & value into metric, for example end end One important use of this approach is to make ROXML object which may or may not include an xml backing, which may be used via _new_ construction as well as _from_xml_ construction. == Selecting a parser By default, ROXML will use LibXML if it is available, or otherwise REXML. If you'd like to explicitly require one or the other, you may do the following: module ROXML XML_PARSER = 'libxml' # or 'rexml' end require 'roxml' For more information on available annotations, see ROXML::ClassMethods::Declarations