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,182 @@
1
+ require File.dirname(__FILE__)+"/tests_init"
2
+
3
+ require 'test/unit'
4
+ require 'company'
5
+
6
+ module XML::Mapping
7
+ def ==(other)
8
+ Marshal.dump(self) == Marshal.dump(other)
9
+ end
10
+ end
11
+
12
+ class XmlMappingTest < Test::Unit::TestCase
13
+ def setup
14
+ # need to undo mapping class definitions that may have been
15
+ # established by other tests (and outlive those tests)
16
+
17
+ # this requires some ugly hackery with internal variables
18
+ XML::Mapping.module_eval <<-EOS
19
+ Classes_w_default_rootelt_names.clear
20
+ Classes_w_nondefault_rootelt_names.clear
21
+ EOS
22
+ Object.send(:remove_const, "Company")
23
+ Object.send(:remove_const, "Address")
24
+ Object.send(:remove_const, "Office")
25
+ Object.send(:remove_const, "Customer")
26
+ $".delete "company.rb"
27
+ $:.unshift File.dirname(__FILE__) # test/unit may have undone this (see test/unit/collector/dir.rb)
28
+ require 'company'
29
+
30
+ @xml = REXML::Document.new(File.new(File.dirname(__FILE__) + "/fixtures/company1.xml"))
31
+ @c = Company.load_from_xml(@xml.root)
32
+ end
33
+
34
+ def test_getter_text_node
35
+ assert_equal "bar", @c.ent2
36
+ end
37
+
38
+ def test_getter_int_node
39
+ assert_equal 18, @c.offices[1].address.number
40
+ end
41
+
42
+ def test_getter_boolean_node
43
+ path=XML::XXPath.new("offices/office[2]/classified")
44
+ assert_equal(path.first(@xml.root).text == "yes",
45
+ @c.offices[1].classified)
46
+ end
47
+
48
+ def test_getter_hash_node
49
+ assert_equal 4, @c.customers.keys.size
50
+ ["cm", "ernie", "jim", "sad"].zip(@c.customers.keys.sort).each do |exp,ckey|
51
+ assert_equal exp, ckey
52
+ assert_equal exp, @c.customers[ckey].uid
53
+ end
54
+ end
55
+
56
+ def test_getter_array_node
57
+ assert_equal ["pencils", "weapons of mass destruction"],
58
+ @c.offices.map{|o|o.speciality}
59
+ end
60
+
61
+
62
+ def test_setter_text_node
63
+ @c.ent2 = "lalala"
64
+ assert_equal "lalala", REXML::XPath.first(@c.save_to_xml, "arrtest/entry[2]").text
65
+ end
66
+
67
+
68
+ def test_setter_array_node
69
+ xml=@c.save_to_xml
70
+ assert_equal ["pencils", "weapons of mass destruction"],
71
+ XML::XXPath.new("offices/office/@speciality").all(xml).map{|n|n.text}
72
+ end
73
+
74
+
75
+ def test_setter_hash_node
76
+ xml=@c.save_to_xml
77
+ assert_equal @c.customers.keys.sort,
78
+ XML::XXPath.new("customers/customer/@uid").all(@xml.root).map{|n|n.text}.sort
79
+ end
80
+
81
+
82
+ def test_setter_boolean_node
83
+ @c.offices[0].classified = !@c.offices[0].classified
84
+ xml=@c.save_to_xml
85
+ assert_equal @c.offices[0].classified,
86
+ XML::XXPath.new("offices/office[1]/classified").first(xml).text == "yes"
87
+ end
88
+
89
+
90
+ def test_root_element
91
+ assert_equal @c, XML::Mapping.load_object_from_file(File.dirname(__FILE__) + "/fixtures/company1.xml")
92
+ assert_equal @c, XML::Mapping.load_object_from_xml(@xml.root)
93
+
94
+ assert_equal "company", Company.root_element_name
95
+ assert_equal Company, XML::Mapping.class_for_root_elt_name("company")
96
+ xml=@c.save_to_xml
97
+ assert_equal "company", xml.name
98
+ # Company.root_element_name 'my-test'
99
+ Company.class_eval <<-EOS
100
+ root_element_name 'my-test'
101
+ EOS
102
+ assert_equal "my-test", Company.root_element_name
103
+ assert_equal Company, XML::Mapping.class_for_root_elt_name("my-test")
104
+ assert_nil XML::Mapping.class_for_root_elt_name("company")
105
+ xml=@c.save_to_xml
106
+ assert_equal "my-test", xml.name
107
+ assert_equal "office", @c.offices[0].save_to_xml.name
108
+
109
+ assert_raises(XML::MappingError) {
110
+ XML::Mapping.load_object_from_xml @xml.root
111
+ }
112
+ @xml.root.name = 'my-test'
113
+ assert_equal @c, XML::Mapping.load_object_from_xml(@xml.root)
114
+
115
+ # white-box tests
116
+ assert_equal [["my-test", Company]], XML::Mapping::Classes_w_nondefault_rootelt_names.sort
117
+ assert_equal [["address", Address], ["customer", Customer], ["office", Office]],
118
+ XML::Mapping::Classes_w_default_rootelt_names.sort
119
+ end
120
+
121
+
122
+ def test_optional_flag
123
+ hamburg_address_path = XML::XXPath.new("offices/office[1]/address")
124
+ baghdad_address_path = XML::XXPath.new("offices/office[2]/address")
125
+ hamburg_zip_path = XML::XXPath.new("offices/office[1]/address/zip")
126
+ baghdad_zip_path = XML::XXPath.new("offices/office[2]/address/zip")
127
+
128
+ assert_equal 18282, @c.offices[0].address.zip
129
+ assert_equal 12576, @c.offices[1].address.zip
130
+ xml=@c.save_to_xml
131
+ assert_equal "18282", hamburg_zip_path.first(xml).text
132
+ assert_nil baghdad_zip_path.first(xml,:allow_nil=>true)
133
+ @c.offices[1].address.zip = 12577
134
+ xml=@c.save_to_xml
135
+ assert_equal "12577", baghdad_zip_path.first(xml).text
136
+ c2 = Company.load_from_xml(xml)
137
+ assert_equal 12577, c2.offices[1].address.zip
138
+ @c.offices[1].address.zip = 12576
139
+ xml=@c.save_to_xml
140
+ assert_nil baghdad_zip_path.first(xml,:allow_nil=>true)
141
+
142
+ hamburg_address_path.first(xml).delete_element("zip")
143
+ c3 = Company.load_from_xml(xml)
144
+ assert_equal 12576, c3.offices[0].address.zip
145
+ hamburg_address_path.first(xml).delete_element("city")
146
+ assert_raises(XML::MappingError) {
147
+ Company.load_from_xml(xml)
148
+ }
149
+ end
150
+
151
+
152
+ def test_optional_flag_nodefault
153
+ hamburg_address_path = XML::XXPath.new("offices/office[1]/address")
154
+ hamburg_street_path = XML::XXPath.new("offices/office[1]/address/street")
155
+
156
+ assert_equal hamburg_street_path.first(@xml.root).text,
157
+ @c.offices[0].address.street
158
+
159
+ hamburg_address_path.first(@xml.root).delete_element("street")
160
+ c2 = Company.load_from_xml(@xml.root)
161
+ assert_nil c2.offices[0].address.street
162
+
163
+ xml2=c2.save_to_xml
164
+ assert_nil hamburg_street_path.first(xml2,:allow_nil=>true)
165
+ end
166
+
167
+
168
+ def test_polymorphic_node
169
+ assert_equal 3, @c.stuff.size
170
+ assert_equal 'Saddam Hussein', @c.stuff[0].name
171
+ assert_equal 'Berlin', @c.stuff[1].city
172
+ assert_equal 'weapons of mass destruction', @c.stuff[2].speciality
173
+
174
+ @c.stuff[1].city = 'Munich'
175
+ @c.stuff[2].classified = false
176
+
177
+ xml2=@c.save_to_xml
178
+ assert_equal 'Munich', xml2.root.elements[5].elements[2].elements[1].text
179
+ assert_equal 'no', xml2.root.elements[5].elements[3].elements[1].text
180
+ end
181
+
182
+ end
@@ -0,0 +1,273 @@
1
+ require File.dirname(__FILE__)+"/tests_init"
2
+
3
+ require 'test/unit'
4
+
5
+ require "rexml/document"
6
+ require "xml/xxpath"
7
+
8
+
9
+ class XPathTest < Test::Unit::TestCase
10
+ include REXML
11
+
12
+ def setup
13
+ @d = Document.new <<-EOS
14
+ <bla>
15
+ <foo>x</foo>
16
+ <bar>bar1</bar>
17
+ <foo key='xy'>
18
+ y
19
+ <u/>
20
+ </foo>
21
+ </bla>
22
+ EOS
23
+ end
24
+
25
+ def test_read_byname
26
+ assert_equal @d.root.elements.to_a("foo"), XML::XXPath.new("foo").all(@d.root)
27
+ assert_equal @d.root.elements.to_a("foo")[1].elements.to_a("u"), XML::XXPath.new("foo/u").all(@d.root)
28
+ assert_equal [], XML::XXPath.new("foo/notthere").all(@d.root)
29
+ end
30
+
31
+
32
+ def test_read_byidx
33
+ assert_equal [@d.root.elements[1]], XML::XXPath.new("foo[1]").all(@d.root)
34
+ assert_equal [@d.root.elements[3]], XML::XXPath.new("foo[2]").all(@d.root)
35
+ assert_equal [], XML::XXPath.new("foo[10]").all(@d.root)
36
+ assert_equal [], XML::XXPath.new("foo[3]").all(@d.root)
37
+ end
38
+
39
+
40
+ def test_read_byall
41
+ assert_equal @d.root.elements.to_a, XML::XXPath.new("*").all(@d.root)
42
+ assert_equal [], XML::XXPath.new("notthere/*").all(@d.root)
43
+ end
44
+
45
+
46
+ def test_read_byattr
47
+ assert_equal [@d.root.elements[3]], XML::XXPath.new("foo[@key='xy']").all(@d.root)
48
+ assert_equal [], XML::XXPath.new("foo[@key='notthere']").all(@d.root)
49
+ assert_equal [], XML::XXPath.new("notthere[@key='xy']").all(@d.root)
50
+ end
51
+
52
+
53
+ def test_attribute
54
+ elt = @d.root.elements[3]
55
+ attr1 = XML::XXPath::Accessors::Attribute.new(elt,"key",false)
56
+ attr2 = XML::XXPath::Accessors::Attribute.new(elt,"key",false)
57
+ assert_not_nil attr1
58
+ assert_not_nil attr2
59
+ assert_equal attr1,attr2 # tests Attribute.==
60
+ assert_nil XML::XXPath::Accessors::Attribute.new(elt,"notthere",false)
61
+ assert_nil XML::XXPath::Accessors::Attribute.new(elt,"notthere",false)
62
+ newattr = XML::XXPath::Accessors::Attribute.new(elt,"new",true)
63
+ assert_not_nil newattr
64
+ assert_equal newattr, XML::XXPath::Accessors::Attribute.new(elt,"new",false)
65
+ newattr.text = "lala"
66
+ assert_equal "lala", elt.attributes["new"]
67
+ end
68
+
69
+ def test_read_byattrname
70
+ assert_equal [XML::XXPath::Accessors::Attribute.new(@d.root.elements[3],"key",false)],
71
+ XML::XXPath.new("foo/@key").all(@d.root)
72
+ assert_equal [], XML::XXPath.new("foo/@notthere").all(@d.root)
73
+ end
74
+
75
+
76
+ def test_read_byidx_then_name
77
+ assert_equal [@d.root.elements[3].elements[1]], XML::XXPath.new("foo[2]/u").all(@d.root)
78
+ assert_equal [], XML::XXPath.new("foo[2]/notthere").all(@d.root)
79
+ assert_equal [], XML::XXPath.new("notthere[2]/u").all(@d.root)
80
+ assert_equal [], XML::XXPath.new("foo[3]/u").all(@d.root)
81
+ end
82
+
83
+ def test_read_first
84
+ assert_equal @d.root.elements[3].elements[1], XML::XXPath.new("foo[2]/u").first(@d.root)
85
+ end
86
+
87
+ def test_read_first_nil
88
+ assert_equal nil, XML::XXPath.new("foo[2]/notthere").first(@d.root, :allow_nil=>true)
89
+ end
90
+
91
+ def test_read_first_exception
92
+ assert_raises(XML::XXPathError) {
93
+ XML::XXPath.new("foo[2]/notthere").first(@d.root)
94
+ }
95
+ end
96
+
97
+
98
+ def test_write_noop
99
+ assert_equal @d.root.elements[1], XML::XXPath.new("foo").first(@d.root, :ensure_created=>true)
100
+ assert_equal @d.root.elements[3].elements[1], XML::XXPath.new("foo[2]/u").first(@d.root, :ensure_created=>true)
101
+ # TODO: deep-compare of REXML documents?
102
+ end
103
+
104
+ def test_write_byname_then_name
105
+ s1 = @d.elements[1].elements.size
106
+ s2 = @d.elements[1].elements[1].elements.size
107
+ node = XML::XXPath.new("foo/new1").first(@d.root, :ensure_created=>true)
108
+ assert_equal "new1", node.name
109
+ assert node.attributes.empty?
110
+ assert_equal @d.elements[1].elements[1].elements[1], node
111
+ assert_equal s1, @d.elements[1].elements.size
112
+ assert_equal s2+1, @d.elements[1].elements[1].elements.size
113
+ end
114
+
115
+
116
+ def test_write_byidx
117
+ XML::XXPath.new("foo[2]").first(@d.root, :ensure_created=>true)
118
+ # TODO: deep-compare of REXML documents?
119
+ assert_equal 2, @d.root.elements.select{|elt| elt.name=="foo"}.size
120
+ node = XML::XXPath.new("foo[10]").first(@d.root, :ensure_created=>true)
121
+ assert_equal 10, @d.root.elements.select{|elt| elt.name=="foo"}.size
122
+ assert_equal "foo", node.name
123
+ end
124
+
125
+
126
+ def test_write_byattrname
127
+ elt = @d.root.elements[3]
128
+ s1 = elt.attributes.size
129
+ attr_key = XML::XXPath.new("foo[2]/@key").first(@d.root, :ensure_created=>true)
130
+ assert_equal elt.attributes["key"], attr_key.text
131
+
132
+ attr_new = XML::XXPath.new("foo[2]/@new").first(@d.root, :ensure_created=>true)
133
+ attr_new.text = "haha"
134
+ assert_equal "haha", attr_new.text
135
+ assert_equal "haha", elt.attributes["new"]
136
+ assert_equal s1+1, elt.attributes.size
137
+ end
138
+
139
+
140
+ def test_write_byname_and_attr
141
+ node1 = XML::XXPath.new("hiho[@blubb='bla']").first(@d.root,:ensure_created=>true)
142
+ node2 = XML::XXPath.new("hiho[@blubb='bla']").first(@d.root,:ensure_created=>true)
143
+ node3 = XML::XXPath.new("hiho[@blubb2='bla2']").first(@d.root,:ensure_created=>true)
144
+ assert_equal node1, node2
145
+ assert_equal node2, node3
146
+ assert_equal "hiho", node1.name
147
+ assert_equal 4, @d.root.elements.size
148
+ assert_equal @d.root.elements[4], node1
149
+ assert_equal @d.root.elements[4], node3
150
+ assert_equal 'bla', node3.attributes['blubb']
151
+ assert_equal 'bla2', node3.attributes['blubb2']
152
+
153
+ node4 = XML::XXPath.new("hiho[@blubb='foo42']").first(@d.root,:ensure_created=>true)
154
+ assert_not_equal node3, node4
155
+ assert_equal 5, @d.root.elements.size
156
+ assert_equal @d.root.elements[5], node4
157
+ assert_equal 'foo42', node4.attributes['blubb']
158
+ end
159
+
160
+
161
+ def test_create_new_byname
162
+ s1 = @d.elements[1].elements.size
163
+ s2 = @d.elements[1].elements[1].elements.size
164
+ startnode = @d.elements[1].elements[1]
165
+ node1 = XML::XXPath.new("new1").create_new(startnode)
166
+ node2 = XML::XXPath.new("new1").first(startnode, :create_new=>true) #same as .create_new(...)
167
+ assert_equal "new1", node1.name
168
+ assert_equal "new1", node2.name
169
+ assert node1.attributes.empty?
170
+ assert node2.attributes.empty?
171
+ assert_equal @d.elements[1].elements[1].elements[1], node1
172
+ assert_equal @d.elements[1].elements[1].elements[2], node2
173
+ assert_equal s1, @d.elements[1].elements.size
174
+ assert_equal s2+2, @d.elements[1].elements[1].elements.size
175
+ end
176
+
177
+
178
+ def test_create_new_byname_then_name
179
+ s1 = @d.elements[1].elements.size
180
+ node1 = XML::XXPath.new("foo/new1").create_new(@d.root)
181
+ node2 = XML::XXPath.new("foo/new1").create_new(@d.root)
182
+ assert_equal "new1", node1.name
183
+ assert_equal "new1", node2.name
184
+ assert node1.attributes.empty?
185
+ assert node2.attributes.empty?
186
+ assert_equal @d.elements[1].elements[s1+1].elements[1], node1
187
+ assert_equal @d.elements[1].elements[s1+2].elements[1], node2
188
+ assert_equal s1+2, @d.elements[1].elements.size
189
+ end
190
+
191
+
192
+ def test_create_new_byidx
193
+ assert_raises(XML::XXPathError) {
194
+ XML::XXPath.new("foo[2]").create_new(@d.root)
195
+ }
196
+ node1 = XML::XXPath.new("foo[3]").create_new(@d.root)
197
+ assert_raises(XML::XXPathError) {
198
+ XML::XXPath.new("foo[3]").create_new(@d.root)
199
+ }
200
+ assert_equal @d.elements[1].elements[4], node1
201
+ assert_equal "foo", node1.name
202
+ node2 = XML::XXPath.new("foo[4]").create_new(@d.root)
203
+ assert_equal @d.elements[1].elements[5], node2
204
+ assert_equal "foo", node2.name
205
+ node3 = XML::XXPath.new("foo[10]").create_new(@d.root)
206
+ assert_raises(XML::XXPathError) {
207
+ XML::XXPath.new("foo[10]").create_new(@d.root)
208
+ }
209
+ XML::XXPath.new("foo[11]").create_new(@d.root)
210
+ assert_equal @d.elements[1].elements[11], node3
211
+ assert_equal "foo", node3.name
212
+ # @d.write
213
+ end
214
+
215
+ def test_create_new_byname_then_idx
216
+ node1 = XML::XXPath.new("hello/bar[3]").create_new(@d.root)
217
+ node2 = XML::XXPath.new("hello/bar[3]").create_new(@d.root)
218
+ # same as create_new
219
+ node3 = XML::XXPath.new("hello/bar[3]").create_new(@d.root)
220
+ assert_equal @d.elements[1].elements[4].elements[3], node1
221
+ assert_equal @d.elements[1].elements[5].elements[3], node2
222
+ assert_equal @d.elements[1].elements[6].elements[3], node3
223
+ assert_not_equal node1, node2
224
+ assert_not_equal node1, node3
225
+ assert_not_equal node2, node3
226
+ end
227
+
228
+
229
+ def test_create_new_byattrname
230
+ node1 = XML::XXPath.new("@lala").create_new(@d.root)
231
+ assert_raises(XML::XXPathError) {
232
+ XML::XXPath.new("@lala").create_new(@d.root)
233
+ }
234
+ assert node1.kind_of?(XML::XXPath::Accessors::Attribute)
235
+ node1.text = "val1"
236
+ assert_equal "val1", @d.elements[1].attributes["lala"]
237
+ foo2 = XML::XXPath.new("foo[2]").first(@d.root)
238
+ assert_raises(XML::XXPathError) {
239
+ XML::XXPath.new("@key").create_new(foo2)
240
+ }
241
+ node2 = XML::XXPath.new("@bar").create_new(foo2)
242
+ assert node2.kind_of?(XML::XXPath::Accessors::Attribute)
243
+ node2.text = "val2"
244
+ assert_equal "val2", @d.elements[1].elements[3].attributes["bar"]
245
+ end
246
+
247
+
248
+ def test_create_new_byname_and_attr
249
+ node1 = XML::XXPath.new("hiho[@blubb='bla']").create_new(@d.root)
250
+ node2 = XML::XXPath.new("hiho[@blubb='bla']").create_new(@d.root)
251
+ node3 = XML::XXPath.new("hiho[@blubb2='bla']").create_new(@d.root)
252
+ assert_equal "hiho", node1.name
253
+ assert_equal "hiho", node2.name
254
+ assert_equal @d.root.elements[4], node1
255
+ assert_equal @d.root.elements[5], node2
256
+ assert_equal @d.root.elements[6], node3
257
+ assert_not_equal @d.root.elements[5], node1
258
+ end
259
+
260
+
261
+ def test_unspecifiedness
262
+ node1 = XML::XXPath.new("foo/hello").create_new(@d.root)
263
+ assert(!(node1.unspecified?))
264
+ assert_equal @d.root, node1.parent.parent
265
+ node2 = XML::XXPath.new("foo/*").create_new(@d.root)
266
+ assert_equal @d.root, node2.parent.parent
267
+ assert node2.unspecified?
268
+ node2.name = "newone"
269
+ assert_equal "newone", node2.name
270
+ assert(!(node2.unspecified?))
271
+ end
272
+
273
+ end