From: ser@... (Sean Russell) Date: 2004-05-06T04:53:57+09:00 Subject: Re: XML Data Binding for Ruby ? Markus Jais wrote in message news:... > with this I can take an XML document like this .... > and this python code > ============= > #!/usr/bin/env python > > import anobind Here's something that'll do the job. I just threw this together, so it is probably fragile, and it is one-way -- it only converts XML to Ruby objects. But it implements the functionality that you described in the example you gave -- it does so in 25 lines of code, and took about as many minutes to write and test. :-) I'm sure it could be compressed and/or optimized; there were a number of solutions to choose from. By the way, I personally believe that this class of XML-to-Objects mechanism has extremely limited use. If you use real XML objects and XPath, you have access to a much broader set of XML documents, and it is often easier to work with -- especially with deeply nested XML. And if all you're looking for is serialization, there are a number of projects available; some, even, that generate XML -- albeit, not as clear of a 1-to-1 mapping as here. For an example of where I expect the Python code to fail (and I *know* the Ruby code I've supplied will fail), given: B2 TAG1 TAG2 <:tag>TAG3 How do you differentiate between @b and b? Can you get any of the TAG text values? Anyway, here's the Ruby version of the Python module. ############## START CODE # A quasi-serialization class. Accepts a limited subset of XML and turns it # into Ruby objects. require "rexml/document" class XMLObject def initialize element @element = element @methods = {} end def method_missing method m_name = method.to_s return @methods[m_name] if @methods[m_name] el = REXML::XPath.match( @element, m_name ) case el.size when 0 return @element.attributes[ m_name ] when 1 @methods[ m_name ] = XMLObject.new( el[0] ) else el.collect!{ |e| XMLObject.new( e ) } @methods[ m_name ] = el end return @methods[m_name] end def to_s return REXML::XPath.match( @element, "text()" ).join.squeeze(" \n\t").strip end end # Cut here if you want to reuse this code. Everything that follows is # just an example of how it works. d = REXML::Document.new( DATA.read ) a = XMLObject.new( d.root ) puts "a.b.x = #{a.b.x}" puts "a.b.to_s = #{a.b.to_s}" puts "a.b.c[0].y = #{a.b.c[0].y}" puts "a.b.c[1].to_s = #{a.b.c[1].to_s}" __END__ C1 C2 Text --- SER