From: John Carter Date: 2005-07-08T09:22:29+09:00 Subject: Ruby in XML. I have just stuck this on.. http://www.rubygarden.org/ruby?RubyInXML I like XML. There is a firm standard, there is a rich toolset to work on it. I like HTML. It is simply the fastest way to deliver good looking documents to the widest audience. No surprise. I like XHTML it _is_ HTML in XML. I can validate my XHTML documents and know that they conform exactly to the standard, and hence will render properly on a wide set of browsers. I love ruby. It is quite the easiest way to program. It has a lovely XML API called REXML. I sometimes need to do spreadsheet sort of things. Basically a document that describes my reasoning and findings, supported by numbers. Long time ago, when I still did Perl, I found by actual trials that I was about as fast in Perl as the average guy is using a Spreadsheet. Sometimes faster, sometimes slower. But for the next hundred data sets, my perl scripts where a thousand times faster. So I don't do spreadsheets these days, I write ruby scripts. So I have taken to combining Ruby & HTML. Sometimes via cgi. It works for me. But sometimes I have documents that are more HTML than ruby. So it makes sense to write them in HTML, with a bit of Ruby embedded. That's where erb and eruby live. But I don't like erb and eruby's tags. I can't validate my XHTML. So add REXML and I present a very small script I call rubyexml. Ruby Embedded in XML. #!/usr/bin/ruby -w require 'rexml/document' require 'rexml/streamlistener' require 'pp' # All eval's are evaluated in the context of an instance of this class. # Extend this, or add this method to a class of your own. class Context def eval_value( value) value.gsub( %r{ \#\{ ( [^\}]+ ) \} }x) do | match| instance_eval( $1).to_s end end end # This does the work. class Listener include REXML::StreamListener def initialize( context) @context = context end def comment( text) print @context.instance_eval( text) rescue SyntaxError => details pp @context pp text raise "Failed to compile '#{text}' in context : #{details}" end def tag_start(name,attrs) print "<",name attrs.each_pair do |key, value| print " #{key}=\"#{@context.eval_value( value)}\"" end print ">" end def tag_end( name) print "" end def text( text) print @context.eval_value(text) end def cdata( ctext) text( ctext) end end # This comes for free from REXML. Stream parse an XML document. REXML::Document::parse_stream( REXML::SourceFactory::create_from( STDIN), Listener::new( Context.new)) So take a chunk of XHTML...

The answer to life, the universe and everything is

The following image is #{@file_name.sub(/\.jpg/,'')}

It validates as correct xml against the XHTML DTD. Feed it through rubyexml and get...

The answer to life, the universe and everything is 42

The following image is pretty_picture.jpg pretty_picture

Just so blooming simple. And if you have a big hairy object that knows all the deeper secrets of life, just change rubyexml to... REXML::Document::parse_stream( REXML::SourceFactory::create_from( STDIN), Listener::new( BigHairyObjectThatKnowsTheDeeperSecretsOfLife.new)) And you can refer to all it's instance variables and methods. It all so blooming simple! John Carter Phone : (64)(3) 358 6639 Tait Electronics Fax : (64)(3) 359 4632 PO Box 1645 Christchurch Email : john.carter@tait.co.nz New Zealand "At first I hoped that such a technically unsound project would collapse but I soon realized it was doomed to success. Almost anything in software can be implemented, sold, and even used given enough determination. There is nothing a mere scientist can say that will stand against the flood of a hundred million dollars. But there is one quality that cannot be purchased in this way---and that is reliability. The price of reliability is the pursuit of the utmost simplicity. It is a price which the very rich find most hard to pay." -- C.A.R. Hoare in The Emperor's Old Clothes, Turing Award Lecture (27 October 1980)