# Fun with XEXPR

**URL:** <https://www.ruby-forum.com/t/fun-with-xexpr/67147>\
**Category:** Ruby\
**Created:** [September 1, 2006, 1:43am UTC](https://www.ruby-forum.com/t/fun-with-xexpr/67147 "2006-09-01T01:43:28Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![phrogz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/2acd7d/32.png) [@phrogz](https://www.ruby-forum.com/u/phrogz)\
**Post date:** [September 1, 2006, 1:43am UTC](https://www.ruby-forum.com/t/fun-with-xexpr/67147/1 "2006-09-01T01:43:28Z")

</div>

Just sharing some fun code. I think I cranked this out in 30 minutes.  
Ruby is so cool.  
It’s not a full specification of the XEXPR language  
[XEXPR - XML Expression Language](http://www.w3.org/TR/xexpr/), but at this point that’s just a trivial  
amount of additional work.

require ‘rexml/document’  
include REXML

class Element  
def self.handle\_expression( expr\_name, &eval\_code )  
(@@expression\_code ||= {})[expr\_name] = eval\_code  
end

def run\_expression  
unless proc = @@expression\_code[self.name]  
raise “I don’t know how to handle ‘#{self.name}’ expressions yet”  
end  
proc.call( self )  
end

def run\_children  
last\_value = nil  
self.elements.each{ |c|  
last\_value = c.run\_expression  
}  
last\_value  
end  
end

Element.handle\_expression( ‘expr’ ){ |me|  
me.run\_children  
}

Element.handle\_expression( ‘set’ ){ |me|  
name = me.attributes[‘name’]  
val = me.attributes[‘value’] || me.run\_children  
(@@global\_expression\_variables ||= {})[name] = val  
}

Element.handle\_expression( ‘get’ ){ |me|  
name = me.attributes[‘name’] || me.run\_children  
(@@global\_expression\_variables ||= {})[name]  
}

Element.handle\_expression( ‘print’ ){ |me|  
puts name = me.attributes[‘string’] || me.run\_children  
name  
}

Element.handle\_expression( ‘if’ ){ |me|  
if me.elements[1].run\_expression  
me.elements[2].run\_expression  
else  
me.elements[3] && me.elements[3].run\_expression  
end  
}

Element.handle\_expression( ‘false’ ){ false }

Element.handle\_expression( ‘add’ ){ |me|  
case me.elements[1].run\_expression  
when String  
me.elements.to\_a.map{ |el| el.run\_expression }.join  
else  
me.elements.to\_a.inject(0){ |sum,el| sum + el.run\_expression }  
end  
}

Element.handle\_expression( ‘string’ ){ |me|  
me.text.to\_s  
}

d = REXML::Document.new( \<\<ENDXML )  
  
  
  
  
  
BAD NEWS!  
  
Hello   
  
location  
  
  
  
  
  
ENDXML

d.root.run\_expression  
#=\> Hello World
