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,23 @@
1
+ class Time
2
+ include XML::Mapping
3
+
4
+ numeric_node :year, "year"
5
+ numeric_node :month, "month"
6
+ numeric_node :day, "mday"
7
+ numeric_node :hour, "hours"
8
+ numeric_node :min, "minutes"
9
+ numeric_node :sec, "seconds"
10
+ end
11
+
12
+
13
+ nowxml=Time.now.save_to_xml
14
+ => <time> ... </>
15
+ nowxml.write($stdout,2)
16
+ <time>
17
+ <year>2005</year>
18
+ <month>7</month>
19
+ <mday>7</mday>
20
+ <hours>6</hours>
21
+ <minutes>10</minutes>
22
+ <seconds>49</seconds>
23
+ </time>
@@ -0,0 +1,27 @@
1
+ require 'xml/mapping/base'
2
+
3
+ class TimeNode < XML::Mapping::SingleAttributeNode
4
+ def initialize_impl(path)
5
+ @y_path = XML::XXPath.new(path+"/year")
6
+ @m_path = XML::XXPath.new(path+"/month")
7
+ @d_path = XML::XXPath.new(path+"/day")
8
+ end
9
+
10
+ def extract_attr_value(xml)
11
+ y,m,d = default_when_xpath_err{ [@y_path.first(xml).text.to_i,
12
+ @m_path.first(xml).text.to_i,
13
+ @d_path.first(xml).text.to_i]
14
+ }
15
+ Time.local(y,m,d)
16
+ end
17
+
18
+ def set_attr_value(xml, value)
19
+ raise "Not a Time: #{value}" unless Time===value
20
+ @y_path.first(xml,:ensure_created=>true).text = value.year
21
+ @m_path.first(xml,:ensure_created=>true).text = value.month
22
+ @d_path.first(xml,:ensure_created=>true).text = value.day
23
+ end
24
+ end
25
+
26
+
27
+ XML::Mapping.add_node_class TimeNode
@@ -0,0 +1,85 @@
1
+ #:invisible:
2
+ $:.unshift "../lib" #<=
3
+ #:visible:
4
+ require 'xml/xxpath'
5
+
6
+ d=REXML::Document.new <<EOS
7
+ <foo>
8
+ <bar>
9
+ <baz key="work">Java</baz>
10
+ <baz key="play">Ruby</baz>
11
+ </bar>
12
+ </foo>
13
+ EOS
14
+
15
+
16
+ rootelt=d.root
17
+
18
+ #:invisible_retval:
19
+ path1=XML::XXPath.new("/bar/baz[@key='work']")
20
+
21
+ #:visible_retval:
22
+ path1.create_new(rootelt)#<=
23
+ #:invisible_retval:
24
+ d.write($stdout,2)#<=
25
+ ### a new element is created for *each* path element, regardless of
26
+ ### what existed before. So a new "bar" element was added, with a new
27
+ ### "baz" element inside it
28
+
29
+ ### same call again...
30
+ #:visible_retval:
31
+ path1.create_new(rootelt)#<=
32
+ #:invisible_retval:
33
+ d.write($stdout,2)#<=
34
+ ### same procedure -- new elements added for each path element
35
+
36
+
37
+ #:visible_retval:
38
+ ## get reference to 1st "baz" element
39
+ firstbazelt=XML::XXPath.new("/bar/baz").first(rootelt)#<=
40
+
41
+ #:invisible_retval:
42
+ path2=XML::XXPath.new("@key2")
43
+
44
+ #:visible_retval:
45
+ path2.create_new(firstbazelt)#<=
46
+ #:invisible_retval:
47
+ d.write($stdout,2)#<=
48
+ ### ok, new attribute node added
49
+
50
+ ### same call again...
51
+ #:visible_retval:
52
+ #:handle_exceptions:
53
+ path2.create_new(firstbazelt)#<=
54
+ #:no_exceptions:
55
+ ### can't create that path anew again -- an element can't have more
56
+ ### than one attribute with the same name
57
+
58
+ #:invisible_retval:
59
+ ### the document hasn't changed
60
+ d.write($stdout,2)#<=
61
+
62
+
63
+
64
+ ### create_new the same path as in the ensure_created example
65
+ #:visible_retval:
66
+ baz6elt=XML::XXPath.new("/bar/baz[6]").create_new(rootelt)#<=
67
+ #:invisible_retval:
68
+ d.write($stdout,2)#<=
69
+ ### ok, new "bar" element and 6th "baz" element inside it created
70
+
71
+
72
+ #:visible_retval:
73
+ #:handle_exceptions:
74
+ XML::XXPath.new("baz[6]").create_new(baz6elt.parent)#<=
75
+ #:no_exceptions:
76
+ #:invisible_retval:
77
+ ### yep, baz[6] already existed and thus couldn't be created once
78
+ ### again
79
+
80
+ ### but of course...
81
+ #:visible_retval:
82
+ XML::XXPath.new("/bar/baz[6]").create_new(rootelt)#<=
83
+ #:invisible_retval:
84
+ d.write($stdout,2)#<=
85
+ ### this works because *all* path elements are newly created
@@ -0,0 +1,181 @@
1
+ require 'xml/xxpath'
2
+
3
+ d=REXML::Document.new <<EOS
4
+ <foo>
5
+ <bar>
6
+ <baz key="work">Java</baz>
7
+ <baz key="play">Ruby</baz>
8
+ </bar>
9
+ </foo>
10
+ EOS
11
+
12
+
13
+ rootelt=d.root
14
+
15
+ path1=XML::XXPath.new("/bar/baz[@key='work']")
16
+
17
+ path1.create_new(rootelt)
18
+ => <baz key='work'/>
19
+ d.write($stdout,2)
20
+ <foo>
21
+ <bar>
22
+ <baz key='work'>Java</baz>
23
+ <baz key='play'>Ruby</baz>
24
+ </bar>
25
+ <bar>
26
+ <baz key='work'/>
27
+ </bar>
28
+ </foo>
29
+
30
+ ### a new element is created for *each* path element, regardless of
31
+ ### what existed before. So a new "bar" element was added, with a new
32
+ ### "baz" element inside it
33
+
34
+ ### same call again...
35
+ path1.create_new(rootelt)
36
+ => <baz key='work'/>
37
+ d.write($stdout,2)
38
+ <foo>
39
+ <bar>
40
+ <baz key='work'>Java</baz>
41
+ <baz key='play'>Ruby</baz>
42
+ </bar>
43
+ <bar>
44
+ <baz key='work'/>
45
+ </bar>
46
+ <bar>
47
+ <baz key='work'/>
48
+ </bar>
49
+ </foo>
50
+
51
+ ### same procedure -- new elements added for each path element
52
+
53
+
54
+ ## get reference to 1st "baz" element
55
+ firstbazelt=XML::XXPath.new("/bar/baz").first(rootelt)
56
+ => <baz key='work'> ... </>
57
+
58
+ path2=XML::XXPath.new("@key2")
59
+
60
+ path2.create_new(firstbazelt)
61
+ => #<XML::XXPath::Accessors::Attribute:0x404b0c4c @name="key2", @parent=<baz key2='[unset]' key='work'> ... </>>
62
+ d.write($stdout,2)
63
+ <foo>
64
+ <bar>
65
+ <baz key2='[unset]' key='work'>Java</baz>
66
+ <baz key='play'>Ruby</baz>
67
+ </bar>
68
+ <bar>
69
+ <baz key='work'/>
70
+ </bar>
71
+ <bar>
72
+ <baz key='work'/>
73
+ </bar>
74
+ </foo>
75
+
76
+ ### ok, new attribute node added
77
+
78
+ ### same call again...
79
+ path2.create_new(firstbazelt)
80
+ XML::XXPathError: XPath (): @key2: create_new and attribute already exists
81
+ from ../lib/xml/../xml/xxpath.rb:341:in `create_subnode_by_attr_name'
82
+ from ../lib/xml/../xml/xxpath.rb:68:in `initialize'
83
+ from ../lib/xml/../xml/xxpath.rb:67:in `call'
84
+ from ../lib/xml/../xml/xxpath.rb:146:in `all'
85
+ from ../lib/xml/../xml/xxpath.rb:125:in `first'
86
+ from ../lib/xml/../xml/xxpath.rb:167:in `create_new'
87
+ ### can't create that path anew again -- an element can't have more
88
+ ### than one attribute with the same name
89
+
90
+ ### the document hasn't changed
91
+ d.write($stdout,2)
92
+ <foo>
93
+ <bar>
94
+ <baz key2='[unset]' key='work'>Java</baz>
95
+ <baz key='play'>Ruby</baz>
96
+ </bar>
97
+ <bar>
98
+ <baz key='work'/>
99
+ </bar>
100
+ <bar>
101
+ <baz key='work'/>
102
+ </bar>
103
+ </foo>
104
+
105
+
106
+
107
+
108
+ ### create_new the same path as in the ensure_created example
109
+ baz6elt=XML::XXPath.new("/bar/baz[6]").create_new(rootelt)
110
+ => <baz/>
111
+ d.write($stdout,2)
112
+ <foo>
113
+ <bar>
114
+ <baz key2='[unset]' key='work'>Java</baz>
115
+ <baz key='play'>Ruby</baz>
116
+ </bar>
117
+ <bar>
118
+ <baz key='work'/>
119
+ </bar>
120
+ <bar>
121
+ <baz key='work'/>
122
+ </bar>
123
+ <bar>
124
+ <baz/>
125
+ <baz/>
126
+ <baz/>
127
+ <baz/>
128
+ <baz/>
129
+ <baz/>
130
+ </bar>
131
+ </foo>
132
+
133
+ ### ok, new "bar" element and 6th "baz" element inside it created
134
+
135
+
136
+ XML::XXPath.new("baz[6]").create_new(baz6elt.parent)
137
+ XML::XXPathError: XPath (): baz[6]: create_new and element already exists
138
+ from ../lib/xml/../xml/xxpath.rb:330:in `create_subnode_by_name_and_index'
139
+ from ../lib/xml/../xml/xxpath.rb:52:in `initialize'
140
+ from ../lib/xml/../xml/xxpath.rb:51:in `call'
141
+ from ../lib/xml/../xml/xxpath.rb:146:in `all'
142
+ from ../lib/xml/../xml/xxpath.rb:125:in `first'
143
+ from ../lib/xml/../xml/xxpath.rb:167:in `create_new'
144
+ ### yep, baz[6] already existed and thus couldn't be created once
145
+ ### again
146
+
147
+ ### but of course...
148
+ XML::XXPath.new("/bar/baz[6]").create_new(rootelt)
149
+ => <baz/>
150
+ d.write($stdout,2)
151
+ <foo>
152
+ <bar>
153
+ <baz key2='[unset]' key='work'>Java</baz>
154
+ <baz key='play'>Ruby</baz>
155
+ </bar>
156
+ <bar>
157
+ <baz key='work'/>
158
+ </bar>
159
+ <bar>
160
+ <baz key='work'/>
161
+ </bar>
162
+ <bar>
163
+ <baz/>
164
+ <baz/>
165
+ <baz/>
166
+ <baz/>
167
+ <baz/>
168
+ <baz/>
169
+ </bar>
170
+ <bar>
171
+ <baz/>
172
+ <baz/>
173
+ <baz/>
174
+ <baz/>
175
+ <baz/>
176
+ <baz/>
177
+ </bar>
178
+ </foo>
179
+
180
+ ### this works because *all* path elements are newly created
181
+
@@ -0,0 +1,30 @@
1
+ #:invisible:
2
+ $:.unshift "../lib" #<=
3
+ #:visible:
4
+ require 'xml/xxpath'
5
+
6
+ d=REXML::Document.new <<EOS
7
+ <foo>
8
+ <bar x="hello">
9
+ <first>
10
+ <second>pingpong</second>
11
+ </first>
12
+ </bar>
13
+ <bar x="goodbye"/>
14
+ </foo>
15
+ EOS
16
+
17
+ XML::XXPath.new("/foo/bar").all(d)#<=
18
+
19
+ XML::XXPath.new("/bar").all(d)#<=
20
+
21
+ XML::XXPath.new("/foo/bar").all(d.root)#<=
22
+
23
+ XML::XXPath.new("/bar").all(d.root)#<=
24
+
25
+
26
+ firstelt = XML::XXPath.new("/foo/bar/first").first(d)#<=
27
+
28
+ XML::XXPath.new("/first/second").all(firstelt)#<=
29
+
30
+ XML::XXPath.new("/second").all(firstelt)#<=
@@ -0,0 +1,34 @@
1
+ require 'xml/xxpath'
2
+
3
+ d=REXML::Document.new <<EOS
4
+ <foo>
5
+ <bar x="hello">
6
+ <first>
7
+ <second>pingpong</second>
8
+ </first>
9
+ </bar>
10
+ <bar x="goodbye"/>
11
+ </foo>
12
+ EOS
13
+
14
+ XML::XXPath.new("/foo/bar").all(d)
15
+ => [<bar x='hello'> ... </>, <bar x='goodbye'/>]
16
+
17
+ XML::XXPath.new("/bar").all(d)
18
+ => []
19
+
20
+ XML::XXPath.new("/foo/bar").all(d.root)
21
+ => []
22
+
23
+ XML::XXPath.new("/bar").all(d.root)
24
+ => [<bar x='hello'> ... </>, <bar x='goodbye'/>]
25
+
26
+
27
+ firstelt = XML::XXPath.new("/foo/bar/first").first(d)
28
+ => <first> ... </>
29
+
30
+ XML::XXPath.new("/first/second").all(firstelt)
31
+ => []
32
+
33
+ XML::XXPath.new("/second").all(firstelt)
34
+ => [<second> ... </>]
@@ -0,0 +1,62 @@
1
+ #:invisible:
2
+ $:.unshift "../lib" #<=
3
+ #:visible:
4
+ require 'xml/xxpath'
5
+
6
+ d=REXML::Document.new <<EOS
7
+ <foo>
8
+ <bar>
9
+ <baz key="work">Java</baz>
10
+ <baz key="play">Ruby</baz>
11
+ </bar>
12
+ </foo>
13
+ EOS
14
+
15
+
16
+ rootelt=d.root
17
+
18
+ #### ensuring that a specific path exists inside the document
19
+
20
+ #:visible_retval:
21
+ XML::XXPath.new("/bar/baz[@key='work']").first(rootelt,:ensure_created=>true)#<=
22
+ #:invisible_retval:
23
+ d.write($stdout,2)#<=
24
+ ### no change (path existed before)
25
+
26
+
27
+ #:visible_retval:
28
+ XML::XXPath.new("/bar/baz[@key='42']").first(rootelt,:ensure_created=>true)#<=
29
+ #:invisible_retval:
30
+ d.write($stdout,2)#<=
31
+ ### path was added
32
+
33
+ #:visible_retval:
34
+ XML::XXPath.new("/bar/baz[@key='42']").first(rootelt,:ensure_created=>true)#<=
35
+ #:invisible_retval:
36
+ d.write($stdout,2)#<=
37
+ ### no change this time
38
+
39
+ #:visible_retval:
40
+ XML::XXPath.new("/bar/baz[@key2='hello']").first(rootelt,:ensure_created=>true)#<=
41
+ #:invisible_retval:
42
+ d.write($stdout,2)#<=
43
+ ### this fit in the 1st "baz" element since
44
+ ### there was no "key2" attribute there before.
45
+
46
+ #:visible_retval:
47
+ XML::XXPath.new("/bar/baz[2]").first(rootelt,:ensure_created=>true)#<=
48
+ #:invisible_retval:
49
+ d.write($stdout,2)#<=
50
+ ### no change
51
+
52
+ #:visible_retval:
53
+ XML::XXPath.new("/bar/baz[6]/@haha").first(rootelt,:ensure_created=>true)#<=
54
+ #:invisible_retval:
55
+ d.write($stdout,2)#<=
56
+ ### for there to be a 6th "baz" element, there must be 1st..5th "baz" elements
57
+
58
+ #:visible_retval:
59
+ XML::XXPath.new("/bar/baz[6]/@haha").first(rootelt,:ensure_created=>true)#<=
60
+ #:invisible_retval:
61
+ d.write($stdout,2)#<=
62
+ ### no change this time