xml-mapping 0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +56 -0
- data/README +386 -0
- data/README_XPATH +175 -0
- data/Rakefile +214 -0
- data/TODO.txt +32 -0
- data/doc/xpath_impl_notes.txt +119 -0
- data/examples/company.rb +34 -0
- data/examples/company.xml +26 -0
- data/examples/company_usage.intin.rb +19 -0
- data/examples/company_usage.intout +39 -0
- data/examples/order.rb +61 -0
- data/examples/order.xml +54 -0
- data/examples/order_signature_enhanced.rb +7 -0
- data/examples/order_signature_enhanced.xml +9 -0
- data/examples/order_signature_enhanced_usage.intin.rb +12 -0
- data/examples/order_signature_enhanced_usage.intout +16 -0
- data/examples/order_usage.intin.rb +73 -0
- data/examples/order_usage.intout +147 -0
- data/examples/time_augm.intin.rb +19 -0
- data/examples/time_augm.intout +23 -0
- data/examples/time_node.rb +27 -0
- data/examples/xpath_create_new.intin.rb +85 -0
- data/examples/xpath_create_new.intout +181 -0
- data/examples/xpath_docvsroot.intin.rb +30 -0
- data/examples/xpath_docvsroot.intout +34 -0
- data/examples/xpath_ensure_created.intin.rb +62 -0
- data/examples/xpath_ensure_created.intout +114 -0
- data/examples/xpath_pathological.intin.rb +42 -0
- data/examples/xpath_pathological.intout +56 -0
- data/examples/xpath_usage.intin.rb +51 -0
- data/examples/xpath_usage.intout +57 -0
- data/install.rb +40 -0
- data/lib/xml/mapping.rb +14 -0
- data/lib/xml/mapping/base.rb +563 -0
- data/lib/xml/mapping/standard_nodes.rb +343 -0
- data/lib/xml/mapping/version.rb +8 -0
- data/lib/xml/xxpath.rb +354 -0
- data/test/all_tests.rb +6 -0
- data/test/company.rb +54 -0
- data/test/documents_folders.rb +33 -0
- data/test/fixtures/bookmarks1.xml +24 -0
- data/test/fixtures/company1.xml +85 -0
- data/test/fixtures/documents_folders.xml +71 -0
- data/test/fixtures/documents_folders2.xml +30 -0
- data/test/multiple_mappings.rb +80 -0
- data/test/tests_init.rb +2 -0
- data/test/xml_mapping_adv_test.rb +84 -0
- data/test/xml_mapping_test.rb +182 -0
- data/test/xpath_test.rb +273 -0
- 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
|