xml-mapping 0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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)#<=