om 1.4.2 → 1.4.3
Sign up to get free protection for your applications and to get access to all the features.
- data/COMMON_OM_PATTERNS.textile +264 -55
- data/lib/om/version.rb +1 -1
- data/lib/om/xml/document.rb +19 -4
- data/lib/om/xml/dynamic_node.rb +8 -4
- data/spec/unit/dynamic_node_spec.rb +7 -1
- metadata +4 -4
data/COMMON_OM_PATTERNS.textile
CHANGED
@@ -2,19 +2,32 @@ h1. Common Patterns You'll Use with OM
|
|
2
2
|
|
3
3
|
h2. Common Terminology Patterns
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
We want an OM term to be assigned so its value is the value of an element.
|
8
|
-
|
9
|
-
Given this xml:
|
5
|
+
Let's say we have xml like this:
|
10
6
|
|
11
7
|
<pre>
|
12
|
-
<outer>
|
13
|
-
<
|
14
|
-
</
|
8
|
+
<outer outerId="hypatia:outer" type="outer type">
|
9
|
+
<elementA>valA</elementA>
|
10
|
+
<elementB>valB1</elementB>
|
11
|
+
<elementB animal="vole">valB2<elementC>
|
12
|
+
<elementC type="c type" animal="seagull">valC<elementC>
|
13
|
+
<resource type="ead" id="coll.ead" objectId="hypatia:ead_file_asset_fixture">
|
14
|
+
<file id="my_ead.xml" format="XML" mimetype="text/xml" size="47570">
|
15
|
+
<checksum type="md5">123</checksum>
|
16
|
+
<checksum type="sha1">456</checksum>
|
17
|
+
</file>
|
18
|
+
</resource>
|
19
|
+
<resource type="image" id="image" objectId="hypatia:coll_img_file_asset_fixture">
|
20
|
+
<file id="my_image.jpg" format="JPG" mimetype="image/jpeg" size="302080">
|
21
|
+
<checksum type="md5">789</checksum>
|
22
|
+
<checksum type="sha1">666</checksum>
|
23
|
+
</file>
|
24
|
+
</resource>
|
25
|
+
</outer>
|
15
26
|
</pre>
|
16
27
|
|
17
|
-
|
28
|
+
h4. element value
|
29
|
+
|
30
|
+
We want an OM term for the value of an element.
|
18
31
|
|
19
32
|
In the Datastream Model:
|
20
33
|
|
@@ -23,111 +36,307 @@ In the Datastream Model:
|
|
23
36
|
class ExampleXMLDS < ActiveFedora::NokogiriDatastream
|
24
37
|
# OM (Opinionated Metadata) terminology mapping
|
25
38
|
set_terminology do |t|
|
26
|
-
t.root(:path => "outer", :xmlns => '')
|
27
|
-
t.
|
39
|
+
t.root(:path => "outer", :xmlns => '', :namespace_prefix => nil)
|
40
|
+
t.elementA
|
41
|
+
t.elB(:path => "elementB", :namespace_prefix => nil)
|
42
|
+
t.elC(:path => "elementC", :namespace_prefix => nil)
|
28
43
|
end
|
29
|
-
end
|
44
|
+
end
|
30
45
|
</pre>
|
31
46
|
|
32
|
-
|
47
|
+
This results in :elementA having a value of "valA" and :elB having two values of "valB1" and "valB2", and :elC having a value of "valC"
|
48
|
+
|
49
|
+
h4. element value given a specific attribute value
|
50
|
+
|
51
|
+
We want an OM term for the value of an element, but only if the element has a specific attribute value.
|
33
52
|
|
34
|
-
|
53
|
+
In the Datastream Model:
|
35
54
|
|
36
55
|
<pre>
|
56
|
+
# defines the expected OM terminology for example xml
|
37
57
|
class ExampleXMLDS < ActiveFedora::NokogiriDatastream
|
58
|
+
# OM (Opinionated Metadata) terminology mapping
|
38
59
|
set_terminology do |t|
|
39
60
|
t.root(:path => "outer", :xmlns => '')
|
40
|
-
t.
|
61
|
+
t.elementC(:attributes=>{:animal=>"seagull"}, :namespace_prefix => nil)
|
62
|
+
t.here(:path=>"resource", :attributes=>{:type=>"ead"}, :namespace_prefix => nil)
|
63
|
+
t.there(:path=>"resource", :attributes=>{:type=>"nowhere"}, :namespace_prefix => nil)
|
41
64
|
end
|
42
|
-
end
|
65
|
+
end
|
43
66
|
</pre>
|
44
67
|
|
45
|
-
|
68
|
+
This results in :elementC having a value of "valC" and :here having a value of "123 456", and :there having a value of nil (or is it ""?)
|
46
69
|
|
47
|
-
|
70
|
+
h4. element value given absence of a specific attribute
|
48
71
|
|
49
|
-
|
72
|
+
We want an OM term for an element's value, but only if the element does not have a specific attribute.
|
50
73
|
|
51
|
-
<pre>
|
52
|
-
|
53
|
-
|
54
|
-
|
74
|
+
<pre>
|
75
|
+
# defines the expected OM terminology for example xml
|
76
|
+
class ExampleXMLDS < ActiveFedora::NokogiriDatastream
|
77
|
+
# OM (Opinionated Metadata) terminology mapping
|
78
|
+
set_terminology do |t|
|
79
|
+
t.root(:path => "outer", :xmlns => '', :namespace_prefix => nil)
|
80
|
+
t.elementB(:attributes=>{:animal=>:none}, :namespace_prefix => nil)
|
81
|
+
t.no_attrib(:path => "elementB", :attributes=>{:animal=>:none}, :namespace_prefix => nil)
|
82
|
+
end
|
83
|
+
end
|
55
84
|
</pre>
|
56
85
|
|
57
|
-
|
86
|
+
This results in both :elementB and :no_attib having the single value "valB1"
|
58
87
|
|
59
|
-
|
88
|
+
|
89
|
+
h4. attribute value
|
90
|
+
|
91
|
+
We want an OM term for an attribute value
|
60
92
|
|
61
93
|
<pre>
|
62
94
|
# defines the expected OM terminology for example xml
|
63
95
|
class ExampleXMLDS < ActiveFedora::NokogiriDatastream
|
64
96
|
# OM (Opinionated Metadata) terminology mapping
|
65
97
|
set_terminology do |t|
|
66
|
-
t.root(:path => "outer", :xmlns => '')
|
67
|
-
t.
|
98
|
+
t.root(:path => "outer", :xmlns => '', :namespace_prefix => nil)
|
99
|
+
t.elementB {
|
100
|
+
t.my_attr(:path => {:attribute=>"animal"}, :namespace_prefix => nil)
|
101
|
+
}
|
102
|
+
t.alternate(:path => "elementB/@animal", :namespace_prefix => nil)
|
103
|
+
t.another(:proxy=>[:elementB, :my_attr_])
|
104
|
+
t.animal_attrib(:path => {:attribute=>"animal"}, :namespace_prefix => nil)
|
68
105
|
end
|
69
|
-
end
|
106
|
+
end
|
70
107
|
</pre>
|
71
108
|
|
72
|
-
|
109
|
+
This results in :my_attr, :alternate and :another all having the single value of "vole", and :animal_attrib having the values "vole" and "seagull"
|
110
|
+
|
73
111
|
|
74
|
-
|
112
|
+
h4. an example with :proxy and :ref
|
75
113
|
|
76
114
|
<pre>
|
115
|
+
# defines the expected OM terminology for example xml
|
77
116
|
class ExampleXMLDS < ActiveFedora::NokogiriDatastream
|
117
|
+
# OM (Opinionated Metadata) terminology mapping
|
78
118
|
set_terminology do |t|
|
79
|
-
t.root(:path => "outer", :xmlns => '')
|
80
|
-
|
119
|
+
t.root(:path => "outer", :xmlns => '', :namespace_prefix => nil)
|
120
|
+
|
121
|
+
t.resource(:namespace_prefix => nil) {
|
122
|
+
t.fedora_pid(:path=>{:attribute=>"objectId"}, :namespace_prefix => nil)
|
123
|
+
t.file(:ref=>[:file], :namespace_prefix => nil, :namespace_prefix => nil)
|
124
|
+
}
|
125
|
+
t.file(:namespace_prefix => nil) {
|
126
|
+
t.ds_label(:path=>{:attribute=>"id"}, :namespace_prefix => nil)
|
127
|
+
t.size(:path=>{:attribute=>"size"}, :namespace_prefix => nil)
|
128
|
+
t.md5(:path=>"checksum", :attributes=>{:type=>"md5"}, :namespace_prefix => nil)
|
129
|
+
t.sha1(:path=>"checksum", :attributes=>{:type=>"sha1"}, :namespace_prefix => nil)
|
130
|
+
}
|
131
|
+
# really want ead where the type is ead and the file format is XML and the file mimetype is text/xml (and the file id is (?coll_ead.xml ... can be whatever the label of the DS is in the FileAsset object))
|
132
|
+
t.ead(:ref=>:resource, :attributes=>{:type=>"ead"})
|
133
|
+
t.image(:ref=>:resource, :attributes=>{:type=>"image"})
|
134
|
+
|
135
|
+
t.ead_fedora_pid(:proxy=>[:ead, :fedora_pid])
|
136
|
+
t.ead_ds_label(:proxy=>[:ead, :file, :ds_label])
|
137
|
+
t.ead_size(:proxy=>[:ead, :file, :size])
|
138
|
+
t.ead_md5(:proxy=>[:ead, :file, :md5])
|
139
|
+
t.ead_sha1(:proxy=>[:ead, :file, :sha1])
|
140
|
+
|
141
|
+
t.image_fedora_pid(:proxy=>[:image, :fedora_pid])
|
142
|
+
t.image_ds_label(:proxy=>[:image, :file, :ds_label])
|
143
|
+
t.image_size(:proxy=>[:image, :file, :size])
|
144
|
+
t.image_md5(:proxy=>[:image, :file, :md5])
|
145
|
+
t.image_sha1(:proxy=>[:image, :file, :sha1])
|
81
146
|
end
|
82
147
|
end
|
83
148
|
</pre>
|
84
149
|
|
85
|
-
|
150
|
+
This results in
|
151
|
+
:ead_fedora_pid has value "hypatia:ead_file_asset_fixture"
|
152
|
+
:ead_ds_label has value "my_ead.xml"
|
153
|
+
:ead_size has value "47570"
|
154
|
+
:ead_md5 has value"123"
|
155
|
+
:ead_sha1 has value "456"
|
86
156
|
|
87
|
-
|
157
|
+
:image_fedora_pid has value "hypatia:coll_img_file_asset_fixture"
|
158
|
+
:image_ds_label has value "my_image.jpg"
|
159
|
+
:image_size has value "302080"
|
160
|
+
:image_md5 has value "789"
|
161
|
+
:image_sha1 has value "666"
|
88
162
|
|
89
|
-
|
163
|
+
|
164
|
+
h4. xpath-y stuff, also using :ref and :proxy and namespaces
|
165
|
+
|
166
|
+
Let's say we have xml like this:
|
90
167
|
|
91
168
|
<pre>
|
92
|
-
|
93
|
-
|
94
|
-
|
169
|
+
<contentMetadata>
|
170
|
+
<resource type="file" id="BU3A5" objectId="val2">
|
171
|
+
<file id="BURCH1" format="BINARY">
|
172
|
+
<location>content</location>
|
173
|
+
</file>
|
174
|
+
<file id="BURCH1.html" format="HTML">
|
175
|
+
<location>html</location>
|
176
|
+
</file>
|
177
|
+
</resource>
|
178
|
+
</contentMetadata>
|
95
179
|
</pre>
|
96
180
|
|
97
|
-
we want to have
|
181
|
+
We want an OM term corresponding to the <file> element based on the value of the <location> element. That is, we want to have a :content term when the value of <location> is "content" and an :html term when the value of <location> is "html".
|
98
182
|
|
99
183
|
In the Datastream Model:
|
100
184
|
|
101
|
-
FIXME: is this correct? (Naomi wonders 2011-06-22)
|
102
|
-
|
103
185
|
<pre>
|
104
186
|
# defines the expected OM terminology for example xml
|
105
187
|
class ExampleXMLDS < ActiveFedora::NokogiriDatastream
|
106
188
|
# OM (Opinionated Metadata) terminology mapping
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
189
|
+
t.root(:path=>"contentMetadata", :xmlns => '', :namespace_prefix => nil)
|
190
|
+
|
191
|
+
t.resource(:namespace_prefix => nil) {
|
192
|
+
t.file(:ref=>[:file], :namespace_prefix => nil)
|
193
|
+
}
|
194
|
+
|
195
|
+
t.file(:namespace_prefix => nil) {
|
196
|
+
t.location(:path=>"location", :namespace_prefix => nil)
|
197
|
+
t.filename(:path=>{:attribute=>"id"}, :namespace_prefix => nil)
|
198
|
+
t.format(:path=>{:attribute=>"format"}, :namespace_prefix => nil)
|
199
|
+
}
|
200
|
+
t.content(:ref=>:file, :path=>'resource/file[location="content"]', :namespace_prefix => nil)
|
201
|
+
t.html(:ref=>:file, :path=>'resource/file[location="derivative_html"]', :namespace_prefix => nil)
|
202
|
+
|
203
|
+
t.content_location(:proxy=>[:content, :location])
|
204
|
+
t.content_filename(:proxy=>[:content, :filename])
|
205
|
+
t.content_format(:proxy=>[:content, :format])
|
206
|
+
|
207
|
+
t.html_location(:proxy=>[:html, :location])
|
208
|
+
t.html_filename(:proxy=>[:html, :filename])
|
209
|
+
t.html_format(:proxy=>[:html, :format])
|
210
|
+
end
|
114
211
|
</pre>
|
115
212
|
|
116
|
-
|
213
|
+
Another example from Molly Pickral of UVa:
|
214
|
+
|
215
|
+
We want to access just the author and the advisor from the XML below. The two <name> elements must be distinguished by their <roleTerm> value, a grandchild of the <name> element.
|
216
|
+
We want an :author term with value "Mary Pickral", and an :advisor term with value "David Jones".
|
117
217
|
|
118
|
-
|
218
|
+
<pre>
|
219
|
+
<mods xmlns="http://www.loc.gov/mods/v3"
|
220
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3"
|
221
|
+
xsi:schemaLocation="http://www.loc.gov/mods/v3
|
222
|
+
http://www.loc.gov/standards/mods/v3/mods-3-3.xsd">
|
223
|
+
<name type="personal">
|
224
|
+
<namePart type="given">Mary</namePart>
|
225
|
+
<namePart type="family">Pickral</namePart>
|
226
|
+
<affiliation>University of Virginia</affiliation>
|
227
|
+
<namePart>mpc3c</namePart>
|
228
|
+
<affiliation>University of Virginia Library</affiliation>
|
229
|
+
<role>
|
230
|
+
<roleTerm authority="marcrelator" type="code">aut</roleTerm>
|
231
|
+
<roleTerm authority="marcrelator" type="text">author</roleTerm>
|
232
|
+
</role>
|
233
|
+
</name>
|
234
|
+
<name type="personal">
|
235
|
+
<namePart>der5y</namePart>
|
236
|
+
<namePart type="given">David</namePart>
|
237
|
+
<namePart type="family">Jones</namePart>
|
238
|
+
<affiliation>University of Virginia</affiliation>
|
239
|
+
<affiliation>Architectural History Dept.</affiliation>
|
240
|
+
<role>
|
241
|
+
<roleTerm authority="marcrelator" type="code">ths</roleTerm>
|
242
|
+
<roleTerm authority="marcrelator" type="text">advisor</roleTerm>
|
243
|
+
</role>
|
244
|
+
</name>
|
245
|
+
</mods>
|
246
|
+
</pre>
|
247
|
+
|
248
|
+
In the Datastream Model:
|
119
249
|
|
120
250
|
<pre>
|
121
|
-
|
251
|
+
# defines the expected OM terminology for mods thesis example xml
|
252
|
+
class ModsThesis < ActiveFedora::NokogiriDatastream
|
122
253
|
set_terminology do |t|
|
123
|
-
t.root(:path
|
124
|
-
t.
|
125
|
-
t.
|
254
|
+
t.root(:path=>"mods", :xmlns=>"http://www.loc.gov/mods/v3"))
|
255
|
+
t.person(:path=>"name", :namespace_prefix => nil) {
|
256
|
+
t.given(:path=>"namePart", attribtues=>{:type=>"given"})
|
257
|
+
t.family(:path=>"namePart", attribtues=>{:type=>"family"})
|
258
|
+
t.role(:namespace_prefix => nil) {
|
259
|
+
t.text(:path=>"roleTerm", :attributes=>{:type=>"text"})
|
260
|
+
t.code(:path=>"roleTerm", :attributes=>{:type=>"code"})
|
261
|
+
}
|
126
262
|
}
|
127
|
-
|
263
|
+
t.author(:ref=>:person, :path=>'name[./role/roleTerm="aut"]')
|
264
|
+
t.advisor(:ref=>:person, :path=>'name[./role/roleTerm="ths"]')
|
265
|
+
|
266
|
+
t.author_given(:proxy=>[:author, :given])
|
267
|
+
t.author_family(:proxy=>[:author, :family])
|
268
|
+
t.advisor_given(:proxy=>[:advisor, :given])
|
269
|
+
t.advisor_family(:proxy=>[:advisor, :family])
|
270
|
+
end
|
128
271
|
end
|
129
272
|
</pre>
|
130
273
|
|
274
|
+
This isn't quite what the doctor ordered, but :author_given and :author_family can be used to get the author name; similarly for advisor.
|
275
|
+
|
276
|
+
|
277
|
+
|
278
|
+
And a variant on the previous example using namespace prefixes.
|
279
|
+
|
280
|
+
We want to access just the creator and the repository from the XML below. The two <name> elements must be distinguished by their <roleTerm> value, a grandchild of the <name> element.
|
281
|
+
We want a :creator term with value "David Small", and a :repository term with value "Graphic Novel Repository".
|
282
|
+
|
283
|
+
Our xml:
|
284
|
+
|
285
|
+
<pre>
|
286
|
+
<mods:mods xmlns:mods="http://www.loc.gov/mods/v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3" xsi:schemaLocation="http://www.loc.gov/mods/v3 http://www.loc.gov/standards/mods/v3/mods-3-3.xsd">
|
287
|
+
|
288
|
+
<mods:name type="personal">
|
289
|
+
<mods:namePart>David Small</mods:namePart>
|
290
|
+
<mods:role>
|
291
|
+
<mods:roleTerm authority="marcrelator" type="text">creator</mods:roleTerm>
|
292
|
+
</mods:role>
|
293
|
+
</mods:name>
|
294
|
+
<mods:name type="corporate">
|
295
|
+
<mods:namePart>Graphic Novel Repository</mods:namePart>
|
296
|
+
<mods:role>
|
297
|
+
<mods:roleTerm authority="local" type="text">repository</mods:roleTerm>
|
298
|
+
</mods:role>
|
299
|
+
</mods:name>
|
300
|
+
</mods:mods>
|
301
|
+
</pre>
|
302
|
+
|
303
|
+
In the Datastream model:
|
304
|
+
|
305
|
+
<pre>
|
306
|
+
# defines the expected OM terminology for mods name example xml
|
307
|
+
class ModsName < ActiveFedora::NokogiriDatastream
|
308
|
+
t.root(:path=>"mods", :xmlns=>"http://www.loc.gov/mods/v3", :schema=>"http://www.loc.gov/standards/mods/v3/mods-3-3.xsd", :namespace_prefix => "mods")
|
309
|
+
|
310
|
+
t.name_ {
|
311
|
+
t.name_part(:path=>"namePart")
|
312
|
+
t.family_name(:path=>"namePart", :attributes=>{:type=>"family"})
|
313
|
+
t.given_name(:path=>"namePart", :attributes=>{:type=>"given"}, :label=>"first name")
|
314
|
+
t.terms_of_address(:path=>"namePart", :attributes=>{:type=>"termsOfAddress"})
|
315
|
+
t.role(:ref=>[:role])
|
316
|
+
}
|
317
|
+
t.role {
|
318
|
+
t.role_term_text(:path=>"roleTerm", :attributes=>{:type=>"text"})
|
319
|
+
}
|
320
|
+
|
321
|
+
t.person_full(:ref=>:name, :attributes=>{:type=>"personal"})
|
322
|
+
t.person(:proxy=>[:person_full, :name_part])
|
323
|
+
t.creator(:ref=>:person, :path=>'name[mods:role/mods:roleTerm="creator"]', :xmlns=>"http://www.loc.gov/mods/v3", :namespace_prefix => "mods")
|
324
|
+
|
325
|
+
t.corporate_full(:ref=>:name, :attributes=>{:type=>"corporate"})
|
326
|
+
t.corporate(:proxy=>[:corporate_full, :name_part])
|
327
|
+
t.repository(:ref=>:corporate, :path=>'name[mods:role/mods:roleTerm="repository"]', :xmlns=>"http://www.loc.gov/mods/v3", :namespace_prefix => "mods")
|
328
|
+
end
|
329
|
+
</pre>
|
330
|
+
|
331
|
+
This terminology not only gives the :creator and :repository values as desired, but also has :person and :corporate terms for more generic <name> xml. The :person_full and :corporate_full values include the value of the <roleTerm> field, which is undesirable for display, if not the index.
|
332
|
+
|
333
|
+
|
334
|
+
h3. Arguments that can be used in the terminology
|
335
|
+
|
336
|
+
e.g. :path, :default_content_path, :namespace_prefix ...
|
337
|
+
|
338
|
+
ok if this is a link to the rdoc that describes ALL of these with
|
339
|
+
|
131
340
|
|
132
341
|
h3. Reserved method names (ie. id_, root_)
|
133
342
|
|
data/lib/om/version.rb
CHANGED
data/lib/om/xml/document.rb
CHANGED
@@ -46,12 +46,25 @@ module OM::XML::Document
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def method_missing(name, *args)
|
49
|
-
|
50
|
-
|
51
|
-
|
49
|
+
if matches = /([^=]*)=$/.match(name.to_s)
|
50
|
+
modified_name = matches[1].to_sym
|
51
|
+
term = self.class.terminology.retrieve_term(modified_name)
|
52
|
+
if (term)
|
53
|
+
node = OM::XML::DynamicNode.new(modified_name, nil, self, term)
|
54
|
+
node.val=args
|
55
|
+
else
|
56
|
+
super
|
57
|
+
end
|
52
58
|
else
|
53
|
-
|
59
|
+
term = self.class.terminology.retrieve_term(name)
|
60
|
+
if (term)
|
61
|
+
OM::XML::DynamicNode.new(name, args.first, self, term)
|
62
|
+
else
|
63
|
+
super
|
64
|
+
end
|
54
65
|
end
|
66
|
+
|
67
|
+
|
55
68
|
end
|
56
69
|
|
57
70
|
|
@@ -73,6 +86,8 @@ module OM::XML::Document
|
|
73
86
|
# @example
|
74
87
|
# find_by_terms( [:person, 1, :first_name] )
|
75
88
|
# Currently, indexes must be integers.
|
89
|
+
# @example Pass in your own xpath query if you don't want to bother with Term pointers but do want OM to handle namespaces for you.
|
90
|
+
# find_by_terms('//oxns:name[@type="personal"][contains(oxns:role, "donor")]')
|
76
91
|
def find_by_terms(*term_pointer)
|
77
92
|
xpath = self.class.terminology.xpath_with_indexes(*term_pointer)
|
78
93
|
find_by_xpath(xpath) unless xpath.nil?
|
data/lib/om/xml/dynamic_node.rb
CHANGED
@@ -2,27 +2,29 @@ module OM
|
|
2
2
|
module XML
|
3
3
|
#
|
4
4
|
# Provides a natural syntax for using OM Terminologies to access values from xml Documents
|
5
|
+
#
|
6
|
+
# *Note*: All of these examples assume that @article is an instance of OM::Samples::ModsArticle. Look at that file to see the Terminology.
|
5
7
|
#
|
6
8
|
# @example Return an array of the value(s) "start page" node(s) from the second issue node within the first journal node
|
7
9
|
# # Using DynamicNode syntax:
|
8
10
|
# @article.journal(0).issue(1).pages.start
|
9
11
|
# # Other ways to perform this query:
|
10
12
|
# @article.find_by_terms({:journal => 0}, {:issue => 1}, :pages, :start)
|
11
|
-
# @article.xpath("//oxns:relatedItem[@type=\"host\"]/oxns:part[2]/extent[@unit="pages"]")
|
13
|
+
# @article.ng_xml.xpath("//oxns:relatedItem[@type=\"host\"]/oxns:part[2]/extent[@unit="pages"]", {"oxns"=>"http://www.loc.gov/mods/v3"})
|
12
14
|
#
|
13
15
|
# @example Return an NodeSet of the _first titles_ of all journal nodes
|
14
16
|
# # Using DynamicNode syntax:
|
15
17
|
# @article.journal.title(1)
|
16
18
|
# # Other ways to perform this query:
|
17
19
|
# @article.find_by_terms(:journal, {:title => 1})
|
18
|
-
# @article.xpath("//oxns:relatedItem[@type=\"host\"]/oxns:titleInfo/oxns:title[1]")
|
20
|
+
# @article.ng_xml.xpath("//oxns:relatedItem[@type=\"host\"]/oxns:titleInfo/oxns:title[1]", {"oxns"=>"http://www.loc.gov/mods/v3"})
|
19
21
|
#
|
20
22
|
# @example Find all of the titles from all journals & return the first title Node from that NodeSet
|
21
23
|
# # Using DynamicNode syntax:
|
22
24
|
# @article.journal.title[1]
|
23
25
|
# # Other ways to perform this query:
|
24
26
|
# @article.find_by_terms(:journal, :title)[1]
|
25
|
-
# @article.xpath("//oxns:relatedItem[@type=\"host\"]/oxns:titleInfo/oxns:title")[1]
|
27
|
+
# @article.ng_xml.xpath("//oxns:relatedItem[@type=\"host\"]/oxns:titleInfo/oxns:title", {"oxns"=>"http://www.loc.gov/mods/v3"})[1]
|
26
28
|
#
|
27
29
|
class DynamicNode
|
28
30
|
attr_accessor :key, :index, :parent, :addressed_node, :term
|
@@ -73,7 +75,9 @@ module OM
|
|
73
75
|
@document.term_value_update(xpath, y.to_i, z)
|
74
76
|
end
|
75
77
|
end
|
76
|
-
@document.dirty
|
78
|
+
if @document.respond_to?(:dirty=)
|
79
|
+
@document.dirty = true
|
80
|
+
end
|
77
81
|
end
|
78
82
|
|
79
83
|
def sanitize_new_values(new_values)
|
@@ -17,6 +17,11 @@ describe "OM::XML::DynamicNode" do
|
|
17
17
|
expected_values.each {|v| result.should include(v)}
|
18
18
|
end
|
19
19
|
|
20
|
+
it "should be able to set first level elements" do
|
21
|
+
@article.abstract = "My Abstract"
|
22
|
+
@article.abstract.should == ["My Abstract"]
|
23
|
+
end
|
24
|
+
|
20
25
|
it "should find elements two deep" do
|
21
26
|
#TODO reimplement so that method_missing with name is only called once. Create a new method for name.
|
22
27
|
@article.name.name_content.val.should == ["Describes a person"]
|
@@ -66,7 +71,8 @@ describe "OM::XML::DynamicNode" do
|
|
66
71
|
end
|
67
72
|
end
|
68
73
|
|
69
|
-
it "should append nodes at the specified index if possible" do
|
74
|
+
it "should append nodes at the specified index if possible, setting dirty to true if the object responds to dirty" do
|
75
|
+
@article.stubs(:respond_to?).with(:dirty=).returns(true)
|
70
76
|
@article.expects(:dirty=).with(true).twice
|
71
77
|
@article.journal.title_info = ["all", "for", "the"]
|
72
78
|
@article.journal.title_info(3, 'glory')
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: om
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 1
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 4
|
9
|
-
-
|
10
|
-
version: 1.4.
|
9
|
+
- 3
|
10
|
+
version: 1.4.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Matt Zumwalt
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-10-19 00:00:00 -05:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|