xml-mapping 0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/LICENSE +56 -0
  2. data/README +386 -0
  3. data/README_XPATH +175 -0
  4. data/Rakefile +214 -0
  5. data/TODO.txt +32 -0
  6. data/doc/xpath_impl_notes.txt +119 -0
  7. data/examples/company.rb +34 -0
  8. data/examples/company.xml +26 -0
  9. data/examples/company_usage.intin.rb +19 -0
  10. data/examples/company_usage.intout +39 -0
  11. data/examples/order.rb +61 -0
  12. data/examples/order.xml +54 -0
  13. data/examples/order_signature_enhanced.rb +7 -0
  14. data/examples/order_signature_enhanced.xml +9 -0
  15. data/examples/order_signature_enhanced_usage.intin.rb +12 -0
  16. data/examples/order_signature_enhanced_usage.intout +16 -0
  17. data/examples/order_usage.intin.rb +73 -0
  18. data/examples/order_usage.intout +147 -0
  19. data/examples/time_augm.intin.rb +19 -0
  20. data/examples/time_augm.intout +23 -0
  21. data/examples/time_node.rb +27 -0
  22. data/examples/xpath_create_new.intin.rb +85 -0
  23. data/examples/xpath_create_new.intout +181 -0
  24. data/examples/xpath_docvsroot.intin.rb +30 -0
  25. data/examples/xpath_docvsroot.intout +34 -0
  26. data/examples/xpath_ensure_created.intin.rb +62 -0
  27. data/examples/xpath_ensure_created.intout +114 -0
  28. data/examples/xpath_pathological.intin.rb +42 -0
  29. data/examples/xpath_pathological.intout +56 -0
  30. data/examples/xpath_usage.intin.rb +51 -0
  31. data/examples/xpath_usage.intout +57 -0
  32. data/install.rb +40 -0
  33. data/lib/xml/mapping.rb +14 -0
  34. data/lib/xml/mapping/base.rb +563 -0
  35. data/lib/xml/mapping/standard_nodes.rb +343 -0
  36. data/lib/xml/mapping/version.rb +8 -0
  37. data/lib/xml/xxpath.rb +354 -0
  38. data/test/all_tests.rb +6 -0
  39. data/test/company.rb +54 -0
  40. data/test/documents_folders.rb +33 -0
  41. data/test/fixtures/bookmarks1.xml +24 -0
  42. data/test/fixtures/company1.xml +85 -0
  43. data/test/fixtures/documents_folders.xml +71 -0
  44. data/test/fixtures/documents_folders2.xml +30 -0
  45. data/test/multiple_mappings.rb +80 -0
  46. data/test/tests_init.rb +2 -0
  47. data/test/xml_mapping_adv_test.rb +84 -0
  48. data/test/xml_mapping_test.rb +182 -0
  49. data/test/xpath_test.rb +273 -0
  50. metadata +96 -0
@@ -0,0 +1,39 @@
1
+ c = Company.load_from_file('company.xml')
2
+ => #<Company:0x40471c18 @address=#<Address:0x40471344 @zip=10113, @city="Berlin">, @name="ACME inc.", @customers=[#<Customer:0x4046fe90 @name="James Kirk", @id="jim">, #<Customer:0x4046f51c @name="Ernie", @id="ernie">, #<Customer:0x4046eba8 @name="Bert", @id="bert">]>
3
+ c.name
4
+ => "ACME inc."
5
+ c.customers.size
6
+ => 3
7
+ c.customers[1]
8
+ => #<Customer:0x4046f51c @name="Ernie", @id="ernie">
9
+ c.customers[1].name
10
+ => "Ernie"
11
+ c.customers[0].name
12
+ => "James Kirk"
13
+ c.customers[0].name = 'James Tiberius Kirk'
14
+ => "James Tiberius Kirk"
15
+ c.customers << Customer.new('cm','Cookie Monster')
16
+ => [#<Customer:0x4046fe90 @name="James Tiberius Kirk", @id="jim">, #<Customer:0x4046f51c @name="Ernie", @id="ernie">, #<Customer:0x4046eba8 @name="Bert", @id="bert">, #<Customer:0x4046d7a8 @name="Cookie Monster", @id="cm">]
17
+ xml2 = c.save_to_xml
18
+ => <company name='ACME inc.'> ... </>
19
+ xml2.write($stdout,2)
20
+ <company name='ACME inc.'>
21
+ <address>
22
+ <city>Berlin</city>
23
+ <zip>10113</zip>
24
+ </address>
25
+ <customers>
26
+ <customer id='539197256'>
27
+ <name>James Tiberius Kirk</name>
28
+ </customer>
29
+ <customer id='539196046'>
30
+ <name>Ernie</name>
31
+ </customer>
32
+ <customer id='539194836'>
33
+ <name>Bert</name>
34
+ </customer>
35
+ <customer id='539192276'>
36
+ <name>Cookie Monster</name>
37
+ </customer>
38
+ </customers>
39
+ </company>
@@ -0,0 +1,61 @@
1
+ require 'xml/mapping'
2
+
3
+ ## forward declarations
4
+ class Client; end
5
+ class Address; end
6
+ class Item; end
7
+ class Signature; end
8
+
9
+
10
+ class Order
11
+ include XML::Mapping
12
+
13
+ text_node :reference, "@reference"
14
+ object_node :client, "Client", :class=>Client
15
+ hash_node :items, "Item", "@reference", :class=>Item
16
+ array_node :signatures, "Signed-By", "Signature", :class=>Signature, :default_value=>[]
17
+
18
+ def total_price
19
+ items.values.map{|i| i.total_price}.inject(0){|x,y|x+y}
20
+ end
21
+ end
22
+
23
+
24
+ class Client
25
+ include XML::Mapping
26
+
27
+ text_node :name, "Name"
28
+ object_node :home_address, "Address[@where='home']", :class=>Address
29
+ object_node :work_address, "Address[@where='work']", :class=>Address, :default_value=>nil
30
+ end
31
+
32
+
33
+ class Address
34
+ include XML::Mapping
35
+
36
+ text_node :city, "City"
37
+ text_node :state, "State"
38
+ numeric_node :zip, "ZIP"
39
+ text_node :street, "Street"
40
+ end
41
+
42
+
43
+ class Item
44
+ include XML::Mapping
45
+
46
+ text_node :descr, "Description"
47
+ numeric_node :quantity, "Quantity"
48
+ numeric_node :unit_price, "UnitPrice"
49
+
50
+ def total_price
51
+ quantity*unit_price
52
+ end
53
+ end
54
+
55
+
56
+ class Signature
57
+ include XML::Mapping
58
+
59
+ text_node :name, "Name"
60
+ text_node :position, "Position", :default_value=>"Some Employee"
61
+ end
@@ -0,0 +1,54 @@
1
+ <?xml version="1.0" encoding="ISO-8859-1"?>
2
+
3
+ <Order reference="12343-AHSHE-314159">
4
+ <Client>
5
+ <Name>Jean Smith</Name>
6
+ <Address where="home">
7
+ <City>San Mateo</City>
8
+ <State>CA</State>
9
+ <ZIP>94403</ZIP>
10
+ <Street>2000, Alameda de las Pulgas</Street>
11
+ </Address>
12
+ <Address where="work">
13
+ <City>San Francisco</City>
14
+ <State>CA</State>
15
+ <ZIP>94102</ZIP>
16
+ <Street>98765, Fulton Street</Street>
17
+ </Address>
18
+ </Client>
19
+
20
+ <Item reference="RF-0001">
21
+ <Description>Stuffed Penguin</Description>
22
+ <Quantity>10</Quantity>
23
+ <UnitPrice>8.95</UnitPrice>
24
+ </Item>
25
+
26
+ <Item reference="RF-0034">
27
+ <Description>Chocolate</Description>
28
+ <Quantity>5</Quantity>
29
+ <UnitPrice>28.50</UnitPrice>
30
+ </Item>
31
+
32
+ <Item reference="RF-3341">
33
+ <Description>Cookie</Description>
34
+ <Quantity>30</Quantity>
35
+ <UnitPrice>0.85</UnitPrice>
36
+ </Item>
37
+
38
+ <Signed-By>
39
+ <Signature>
40
+ <Name>John Doe</Name>
41
+ <Position>product manager</Position>
42
+ </Signature>
43
+
44
+ <Signature>
45
+ <Name>Jill Smith</Name>
46
+ <Position>clerk</Position>
47
+ </Signature>
48
+
49
+ <Signature>
50
+ <Name>Miles O'Brien</Name>
51
+ </Signature>
52
+ </Signed-By>
53
+
54
+ </Order>
@@ -0,0 +1,7 @@
1
+ class Signature
2
+ include XML::Mapping
3
+
4
+ text_node :name, "Name"
5
+ text_node :position, "Position", :default_value=>"Some Employee"
6
+ time_node :signed_on, "signed-on", :default_value=>Time.now
7
+ end
@@ -0,0 +1,9 @@
1
+ <Signature>
2
+ <Name>John Doe</Name>
3
+ <Position>product manager</Position>
4
+ <signed-on>
5
+ <day>13</day>
6
+ <month>2</month>
7
+ <year>2005</year>
8
+ </signed-on>
9
+ </Signature>
@@ -0,0 +1,12 @@
1
+ #:invisible:
2
+ $:.unshift "../lib"
3
+ require 'xml/mapping'
4
+ require 'time_node.rb'
5
+ require 'order'
6
+ require 'order_signature_enhanced'
7
+ #<=
8
+ #:visible:
9
+ s=Signature.load_from_file("order_signature_enhanced.xml") #<=
10
+ s.signed_on #<=
11
+ s.signed_on=Time.local(1976,12,18) #<=
12
+ s.save_to_xml.write($stdout,2) #<=
@@ -0,0 +1,16 @@
1
+ s=Signature.load_from_file("order_signature_enhanced.xml")
2
+ => #<Signature:0x40476344 @name="John Doe", @signed_on=Sun Feb 13 00:00:00 CET 2005, @position="product manager">
3
+ s.signed_on
4
+ => Sun Feb 13 00:00:00 CET 2005
5
+ s.signed_on=Time.local(1976,12,18)
6
+ => Sat Dec 18 00:00:00 CET 1976
7
+ s.save_to_xml.write($stdout,2)
8
+ <signature>
9
+ <Name>John Doe</Name>
10
+ <Position>product manager</Position>
11
+ <signed-on>
12
+ <year>1976</year>
13
+ <month>12</month>
14
+ <day>18</day>
15
+ </signed-on>
16
+ </signature>=> #<File:examples/order_signature_enhanced_usage.intout>
@@ -0,0 +1,73 @@
1
+ #:invisible:
2
+ $:.unshift "../lib"
3
+ begin
4
+ Object.send(:remove_const, "Address") # name clash with company_usage...
5
+ rescue
6
+ end
7
+ require 'order' #<=
8
+ #:visible:
9
+ ####read access
10
+ o=Order.load_from_file("order.xml") #<=
11
+ o.reference #<=
12
+ o.client #<=
13
+ o.items.keys #<=
14
+ o.items["RF-0034"].descr #<=
15
+ o.items["RF-0034"].total_price #<=
16
+ o.signatures #<=
17
+ o.signatures[2].name #<=
18
+ o.signatures[2].position #<=
19
+ ## default value was set
20
+
21
+ o.total_price #<=
22
+
23
+ ####write access
24
+ o.client.name="James T. Kirk"
25
+ o.items['RF-4711'] = Item.new
26
+ o.items['RF-4711'].descr = 'power transfer grid'
27
+ o.items['RF-4711'].quantity = 2
28
+ o.items['RF-4711'].unit_price = 29.95
29
+
30
+ s=Signature.new
31
+ s.name='Harry Smith'
32
+ s.position='general manager'
33
+ o.signatures << s
34
+ xml=o.save_to_xml #convert to REXML node; there's also o.save_to_file(name) #<=
35
+ #:invisible_retval:
36
+ xml.write($stdout,2) #<=
37
+ #:visible_retval:
38
+
39
+ ####Starting a new order from scratch
40
+ o = Order.new #<=
41
+ ## attributes with default values (here: signatures) are set
42
+ ## automatically
43
+
44
+ #:handle_exceptions:
45
+ xml=o.save_to_xml #<=
46
+ #:no_exceptions:
47
+ ## can't save as long as there are still unset attributes without
48
+ ## default values
49
+
50
+ o.reference = "FOOBAR-1234"
51
+
52
+ o.client = Client.new
53
+ o.client.name = 'Ford Prefect'
54
+ o.client.home_address = Address.new
55
+ o.client.home_address.street = '42 Park Av.'
56
+ o.client.home_address.city = 'small planet'
57
+ o.client.home_address.zip = 17263
58
+ o.client.home_address.state = 'Betelgeuse system'
59
+
60
+ o.items={'XY-42' => Item.new}
61
+ o.items['XY-42'].descr = 'improbability drive'
62
+ o.items['XY-42'].quantity = 3
63
+ o.items['XY-42'].unit_price = 299.95
64
+
65
+ #:invisible_retval:
66
+ o.save_to_xml.write($stdout,2)
67
+ #<=
68
+ #:visible_retval:
69
+
70
+ ## the root element name when saving an object to XML will by default
71
+ ## be derived from the class name (in this example, "Order" became
72
+ ## "order"). This can be overridden on a per-class basis; see
73
+ ## XML::Mapping::ClassMethods#root_element_namefor details.
@@ -0,0 +1,147 @@
1
+ ####read access
2
+ o=Order.load_from_file("order.xml")
3
+ => #<Order:0x40441590 @signatures=[#<Signature:0x40436fc8 @name="John Doe", @position="product manager">, #<Signature:0x404363ac @name="Jill Smith", @position="clerk">, #<Signature:0x40435790 @name="Miles O'Brien", @position="Some Employee">], @items={"RF-3341"=>#<Item:0x40438f58 @unit_price=0.85, @quantity=30, @descr="Cookie">, "RF-0034"=>#<Item:0x4043a7a4 @unit_price=28.5, @quantity=5, @descr="Chocolate">, "RF-0001"=>#<Item:0x4043bff0 @unit_price=8.95, @quantity=10, @descr="Stuffed Penguin">}, @client=#<Client:0x40440be0 @name="Jean Smith", @work_address=#<Address:0x4043e05c @street="98765, Fulton Street", @zip=94102, @state="CA", @city="San Francisco">, @home_address=#<Address:0x4043ff10 @street="2000, Alameda de las Pulgas", @zip=94403, @state="CA", @city="San Mateo">>, @reference="12343-AHSHE-314159">
4
+ o.reference
5
+ => "12343-AHSHE-314159"
6
+ o.client
7
+ => #<Client:0x40440be0 @name="Jean Smith", @work_address=#<Address:0x4043e05c @street="98765, Fulton Street", @zip=94102, @state="CA", @city="San Francisco">, @home_address=#<Address:0x4043ff10 @street="2000, Alameda de las Pulgas", @zip=94403, @state="CA", @city="San Mateo">>
8
+ o.items.keys
9
+ => ["RF-3341", "RF-0034", "RF-0001"]
10
+ o.items["RF-0034"].descr
11
+ => "Chocolate"
12
+ o.items["RF-0034"].total_price
13
+ => 142.5
14
+ o.signatures
15
+ => [#<Signature:0x40436fc8 @name="John Doe", @position="product manager">, #<Signature:0x404363ac @name="Jill Smith", @position="clerk">, #<Signature:0x40435790 @name="Miles O'Brien", @position="Some Employee">]
16
+ o.signatures[2].name
17
+ => "Miles O'Brien"
18
+ o.signatures[2].position
19
+ => "Some Employee"
20
+ ## default value was set
21
+
22
+ o.total_price
23
+ => 257.5
24
+
25
+ ####write access
26
+ o.client.name="James T. Kirk"
27
+ o.items['RF-4711'] = Item.new
28
+ o.items['RF-4711'].descr = 'power transfer grid'
29
+ o.items['RF-4711'].quantity = 2
30
+ o.items['RF-4711'].unit_price = 29.95
31
+
32
+ s=Signature.new
33
+ s.name='Harry Smith'
34
+ s.position='general manager'
35
+ o.signatures << s
36
+ xml=o.save_to_xml #convert to REXML node; there's also o.save_to_file(name)
37
+ => <order reference='12343-AHSHE-314159'> ... </>
38
+ xml.write($stdout,2)
39
+ <order reference='12343-AHSHE-314159'>
40
+ <Client>
41
+ <Name>James T. Kirk</Name>
42
+ <Address where='home'>
43
+ <City>San Mateo</City>
44
+ <State>CA</State>
45
+ <ZIP>94403</ZIP>
46
+ <Street>2000, Alameda de las Pulgas</Street>
47
+ </Address>
48
+ <Address where='work'>
49
+ <City>San Francisco</City>
50
+ <State>CA</State>
51
+ <ZIP>94102</ZIP>
52
+ <Street>98765, Fulton Street</Street>
53
+ </Address>
54
+ </Client>
55
+ <Item reference='RF-3341'>
56
+ <Description>Cookie</Description>
57
+ <Quantity>30</Quantity>
58
+ <UnitPrice>0.85</UnitPrice>
59
+ </Item>
60
+ <Item reference='RF-0034'>
61
+ <Description>Chocolate</Description>
62
+ <Quantity>5</Quantity>
63
+ <UnitPrice>28.5</UnitPrice>
64
+ </Item>
65
+ <Item reference='RF-0001'>
66
+ <Description>Stuffed Penguin</Description>
67
+ <Quantity>10</Quantity>
68
+ <UnitPrice>8.95</UnitPrice>
69
+ </Item>
70
+ <Item reference='RF-4711'>
71
+ <Description>power transfer grid</Description>
72
+ <Quantity>2</Quantity>
73
+ <UnitPrice>29.95</UnitPrice>
74
+ </Item>
75
+ <Signed-By>
76
+ <Signature>
77
+ <Name>John Doe</Name>
78
+ <Position>product manager</Position>
79
+ </Signature>
80
+ <Signature>
81
+ <Name>Jill Smith</Name>
82
+ <Position>clerk</Position>
83
+ </Signature>
84
+ <Signature>
85
+ <Name>Miles O&apos;Brien</Name>
86
+ </Signature>
87
+ <Signature>
88
+ <Name>Harry Smith</Name>
89
+ <Position>general manager</Position>
90
+ </Signature>
91
+ </Signed-By>
92
+ </order>
93
+ ####Starting a new order from scratch
94
+ o = Order.new
95
+ => #<Order:0x4053a014 @signatures=[]>
96
+ ## attributes with default values (here: signatures) are set
97
+ ## automatically
98
+
99
+ xml=o.save_to_xml
100
+ XML::MappingError: no value, and no default value, for attribute: reference
101
+ from ../lib/xml/../xml/mapping/base.rb:377:in `obj_to_xml'
102
+ from ../lib/xml/../xml/mapping/base.rb:157:in `fill_into_xml'
103
+ from ../lib/xml/../xml/mapping/base.rb:156:in `each'
104
+ from ../lib/xml/../xml/mapping/base.rb:156:in `fill_into_xml'
105
+ from ../lib/xml/../xml/mapping/base.rb:168:in `save_to_xml'
106
+ ## can't save as long as there are still unset attributes without
107
+ ## default values
108
+
109
+ o.reference = "FOOBAR-1234"
110
+
111
+ o.client = Client.new
112
+ o.client.name = 'Ford Prefect'
113
+ o.client.home_address = Address.new
114
+ o.client.home_address.street = '42 Park Av.'
115
+ o.client.home_address.city = 'small planet'
116
+ o.client.home_address.zip = 17263
117
+ o.client.home_address.state = 'Betelgeuse system'
118
+
119
+ o.items={'XY-42' => Item.new}
120
+ o.items['XY-42'].descr = 'improbability drive'
121
+ o.items['XY-42'].quantity = 3
122
+ o.items['XY-42'].unit_price = 299.95
123
+
124
+ o.save_to_xml.write($stdout,2)
125
+
126
+ <order reference='FOOBAR-1234'>
127
+ <Client>
128
+ <Name>Ford Prefect</Name>
129
+ <Address where='home'>
130
+ <City>small planet</City>
131
+ <State>Betelgeuse system</State>
132
+ <ZIP>17263</ZIP>
133
+ <Street>42 Park Av.</Street>
134
+ </Address>
135
+ </Client>
136
+ <Item reference='XY-42'>
137
+ <Description>improbability drive</Description>
138
+ <Quantity>3</Quantity>
139
+ <UnitPrice>299.95</UnitPrice>
140
+ </Item>
141
+ </order>
142
+ ## the root element name when saving an object to XML will by default
143
+ ## be derived from the class name (in this example, "Order" became
144
+ ## "order"). This can be overridden on a per-class basis; see
145
+ ## XML::Mapping::ClassMethods#root_element_namefor details.
146
+
147
+ => nil
@@ -0,0 +1,19 @@
1
+ #:invisible:
2
+ $:.unshift "../lib"
3
+ require 'order' #<=
4
+ #:visible:
5
+ class Time
6
+ include XML::Mapping
7
+
8
+ numeric_node :year, "year"
9
+ numeric_node :month, "month"
10
+ numeric_node :day, "mday"
11
+ numeric_node :hour, "hours"
12
+ numeric_node :min, "minutes"
13
+ numeric_node :sec, "seconds"
14
+ end
15
+
16
+
17
+ nowxml=Time.now.save_to_xml #<=
18
+ #:invisible_retval:
19
+ nowxml.write($stdout,2)#<=