Created
May 18, 2009 22:40
-
-
Save danlynn/113792 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# XmlObjectParser by Dan Lynn | |
xml_str = <<XMLEND | |
<inventory title="OmniCorp Store #45x10^3"> | |
<section name="health"> | |
<item upc="123456789" stock="12"> | |
<name>Invisibility Cream</name> | |
<price>14.50</price> | |
<description>Makes you invisible</description> | |
</item> | |
<item upc="445322344" stock="18"> | |
<name>Levitation Salve</name> | |
<price>23.99</price> | |
<description>Levitate yourself for up to 3 hours per application</description> | |
</item> | |
</section> | |
<section name="food"> | |
<item upc="485672034" stock="653"> | |
<name>Blork and Freen Instameal</name> | |
<price>4.95</price> | |
<description>A tasty meal in a tablet; just add water</description> | |
</item> | |
<item upc="132957764" stock="44"> | |
<name>Grob winglets</name> | |
<price>3.56</price> | |
<description>Tender winglets of Grob. Just add water</description> | |
</item> | |
</section> | |
<to_s>a string</to_s> | |
</inventory> | |
XMLEND | |
# REXML Tutorial = http://www.germane-software.com/software/rexml/docs/tutorial.html | |
require 'rexml/document' | |
class XmlObjectParser | |
retained_methods = %w(__send__ __id__ send class inspect instance_eval instance_variables) | |
instance_methods.each { |m| | |
undef_method(m) unless retained_methods.include?(m) | |
} | |
def initialize(node, parent_node=nil) | |
@node = node | |
@node = REXML::Document.new(node) if node.is_a?(String) | |
@parent_node = parent_node | |
end | |
def method_missing(method, *args) | |
child_node = @node.elements[method.to_s] || @node.attributes[method.to_s] | |
return child_node if child_node.is_a?(String) | |
return child_node.text if !child_node.has_elements? | |
return XmlObjectParser.new(child_node, @node) | |
end | |
def [](*args) | |
return XmlObjectParser.new(@parent_node.elements[*args], @parent_node) if args[0].is_a?(Fixnum) | |
return XmlObjectParser.new(@node.elements[*args], @node) | |
end | |
end | |
# my simple version | |
xml = XmlObjectParser.new(xml_str) | |
puts xml.inventory.section.name | |
puts xml.inventory.section.item.stock | |
puts xml.inventory.section[2].inspect | |
puts xml.inventory["section/item[@stock='44']"].upc | |
puts xml.inventory.section.item.name | |
puts xml.inventory.to_s # note that Object's to_s method has been undefined | |
# the long REXML version | |
puts "\n" | |
doc = REXML::Document.new(xml_str) | |
puts doc.elements['inventory'].elements['section'].attributes['name'] | |
puts doc.elements['inventory'].elements['section'].elements['item'].attributes['stock'] | |
puts doc.elements['inventory'].elements[2].attributes['name'] | |
puts doc.elements['inventory'].elements["section/item[@stock='44']"].attributes["upc"] | |
puts doc.elements['inventory'].elements['section'].elements['item'].elements['name'].text | |
puts doc.elements['inventory'].elements['to_s'].text | |
# SAMPLE OUTPUT ================= | |
# >> health | |
# >> 12 | |
# >> #<XmlObjectParser:0x48778 @parent_node=<inventory title='OmniCorp Store #45x10^3'> ... </>, @node=<section name='food'> ... </>> | |
# >> 132957764 | |
# >> Invisibility Cream | |
# >> a string | |
# >> | |
# >> health | |
# >> 12 | |
# >> food | |
# >> 132957764 | |
# >> Invisibility Cream | |
# >> a string |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment