Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > [ANN] xml-mapping 0.8

Reply
Thread Tools

[ANN] xml-mapping 0.8

 
 
Olaf Klischat
Guest
Posts: n/a
 
      07-07-2005
Project Homepage: http://xml-mapping.rubyforge.org/
Download, CVS etc.: http://rubyforge.org/projects/xml-mapping


xml-mapping is an easy to use, extensible library for mapping Ruby
objects to XML trees and back. It includes an XPath interpreter (see
below).


===========================
Example:

----------------------------
Input document:
----------------------------
(example document stolen + extended from
www.castor.org/xml-mapping.html)

<?xml version="1.0" encoding="ISO-8859-1"?>

<order reference="12343-AHSHE-314159">
<client>
<name>Jean Smith</name>
<address where="home">
<city>San Mateo</city>
<state>CA</state>
<zip>94403</zip>
<street>2000, Alameda de las Pulgas</street>
</address>
<address where="work">
<city>San Francisco</city>
<state>CA</state>
<zip>94102</zip>
<street>98765, Fulton street</street>
</address>
</client>

<item reference="RF-0001">
<description>Stuffed Penguin</description>
<quantity>10</quantity>
<unit-price>8.95</unit-price>
</item>

<item reference="RF-0034">
<description>Chocolate</description>
<quantity>5</quantity>
<unit-price>28.50</unit-price>
</item>

<item reference="RF-3341">
<description>Cookie</description>
<quantity>30</quantity>
<unit-price>0.85</unit-price>
</item>

<signed-by>
<signature>
<name>John Doe</name>
<position>product manager</position>
</signature>

<signature>
<name>Jill Smith</name>
<position>clerk</position>
</signature>

<signature>
<name>Miles O'Brien</name>
</signature>
</signed-by>

</order>


----------------------------
Mapping class declarations:
----------------------------

require 'xml/mapping'

## forward declarations
class Client; end
class Address; end
class Item; end
class Signature; end


class Order
include XML::Mapping

text_node :reference, "@reference"
object_node :client, "client", :class=>Client
hash_node :items, "item", "@reference", :class=>Item
array_node :signatures, "signed-by", "signature", :class=>Signature, :default_value=>[]

def total_price
items.values.map{|i| i.total_price}.inject(0){|x,y|x+y}
end
end


class Client
include XML::Mapping

text_node :name, "name"
object_node :home_address, "address[@where='home']", :class=>Address
object_node :work_address, "address[@where='work']", :class=>Address, :default_value=>nil
end


class Address
include XML::Mapping

text_node :city, "city"
text_node :state, "state"
numeric_node :zip, "zip"
text_node :street, "street"
end


class Item
include XML::Mapping

text_node :descr, "description"
numeric_node :quantity, "quantity"
numeric_node :unit_price, "unit-price"

def total_price
quantity*unit_price
end
end


class Signature
include XML::Mapping

text_node :name, "name"
text_node osition, "position", :default_value=>"Some Employee"
end



----------------------------
Usage
----------------------------

####read access
o=Order.load_from_file("order.xml")
=> #<Order:0x40461390 @signatures=[#<Signature[....] @reference="12343-AHSHE-314159">
o.reference
=> "12343-AHSHE-314159"
o.client
=> #<Client:0x404609e0 @name="Jean Smith", @work_address=#<Address:0x4045de5c @city="San Francisco", @street="98765, Fulton street", @zip=94102, @state="CA">, @home_address=#<Address:0x4045fd10 @city="San Mateo", @street="2000, Alameda de las Pulgas", @zip=94403, @state="CA">>
o.items.keys
=> ["RF-3341", "RF-0034", "RF-0001"]
o.items["RF-0034"].descr
=> "Chocolate"
o.items["RF-0034"].total_price
=> 142.5
o.signatures
=> [#<Signature:0x40456f30 @name="John Doe", @position="product manager">, #<Signature:0x40456314 @name="Jill Smith", @position="clerk">, #<Signature:0x404556f8 @name="Miles O'Brien", @position="Some Employee">]
o.signatures[2].name
=> "Miles O'Brien"
o.signatures[2].position
=> "Some Employee"
## default value was set

o.total_price
=> 257.5


####write access
o.client.name="James T. Kirk"
o.items['RF-4711'] = Item.new
o.items['RF-4711'].descr = 'power transfer grid'
o.items['RF-4711'].quantity = 2
o.items['RF-4711'].unit_price = 29.95

s=Signature.new
s.name='Harry Smith'
s.position='general manager'
o.signatures << s
xml=o.save_to_xml #convert to REXML node; there's also o.save_to_file(name)
=> <order reference='12343-AHSHE-314159'> ... </>
xml.write($stdout,2)
<order reference='12343-AHSHE-314159'>
<client>
<name>James T. Kirk</name>
<address where='home'>
<city>San Mateo</city>
<state>CA</state>
<zip>94403</zip>
<street>2000, Alameda de las Pulgas</street>
</address>
<address where='work'>
<city>San Francisco</city>
<state>CA</state>
<zip>94102</zip>
<street>98765, Fulton street</street>
</address>
</client>
<item reference='RF-3341'>
<description>Cookie</description>
<quantity>30</quantity>
<unit-price>0.85</unit-price>
</item>
<item reference='RF-0034'>
<description>Chocolate</description>
<quantity>5</quantity>
<unit-price>28.5</unit-price>
</item>
<item reference='RF-0001'>
<description>Stuffed Penguin</description>
<quantity>10</quantity>
<unit-price>8.95</unit-price>
</item>
<item reference='RF-4711'>
<description>power transfer grid</description>
<quantity>2</quantity>
<unit-price>29.95</unit-price>
</item>
<signed-by>
<signature>
<name>John Doe</name>
<position>product manager</position>
</signature>
<signature>
<name>Jill Smith</name>
<position>clerk</position>
</signature>
<signature>
<name>Miles O&apos;Brien</name>
</signature>
<signature>
<name>Harry Smith</name>
<position>general manager</position>
</signature>
</signed-by>
</order>



####Starting a new order from scratch
o = Order.new
=> #<Order:0x4043c9f0 @signatures=[]>
## attributes with default values (here: signatures) are set
## automatically

xml=o.save_to_xml
XML::MappingError: no value, and no default value, for attribute: reference
from ../../lib/xml/../xml/mapping/base.rb:377:in `obj_to_xml'
from ../../lib/xml/../xml/mapping/base.rb:157:in `fill_into_xml'
from ../../lib/xml/../xml/mapping/base.rb:156:in `each'
from ../../lib/xml/../xml/mapping/base.rb:156:in `fill_into_xml'
from ../../lib/xml/../xml/mapping/base.rb:168:in `save_to_xml'
## can't save as long as there are still unset attributes without
## default values

o.reference = "FOOBAR-1234"

o.client = Client.new
o.client.name = 'Ford Prefect'
o.client.home_address = Address.new
o.client.home_address.street = '42 Park Av.'
o.client.home_address.city = 'small planet'
o.client.home_address.zip = 17263
o.client.home_address.state = 'Betelgeuse system'

o.items={'XY-42' => Item.new}
o.items['XY-42'].descr = 'improbability drive'
o.items['XY-42'].quantity = 3
o.items['XY-42'].unit_price = 299.95

o.save_to_xml.write($stdout,2)

<order reference='FOOBAR-1234'>
<client>
<name>Ford Prefect</name>
<address where='home'>
<city>small planet</city>
<state>Betelgeuse system</state>
<zip>17263</zip>
<street>42 Park Av.</street>
</address>
</client>
<item reference='XY-42'>
<description>improbability drive</description>
<quantity>3</quantity>
<unit-price>299.95</unit-price>
</item>
</order>
## the root element name when saving an object to XML will by default
## be derived from the class name (in this example, "Order" became
## "order"). This can be overridden on a per-class basis; see
## XML::Mapping::ClassMethods#root_element_namefor details.



=======

As shown in the example, you generally include XML::Mapping in a class
to turn it into a "mapping class", and then map instance attributes to
XML sub-trees at will. XPath expressions like "@reference",
"signed-by", or "address[@where='home']" in the mapping class
definition locate the sub-trees; an XPath interpreter is bundled with
xml-mapping for reading and writing data from/to them.

The XPath interpreter can also be used on its own; it does not depend
on the rest of the library.

Several "node types" like text_node, numeric_node, array_node etc. are
provided; it is easy to write your own ones and register them with the
xml-mapping library. There is even documentation on all this =

Olaf
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off




Advertisments