om 3.1.0 → 3.1.1

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/{COMMON_OM_PATTERNS.textile → COMMON_OM_PATTERNS.md} +136 -126
  3. data/CONTRIBUTING.md +2 -2
  4. data/GETTING_FANCY.md +153 -0
  5. data/GETTING_STARTED.md +329 -0
  6. data/Gemfile +1 -1
  7. data/History.md +164 -0
  8. data/LICENSE +15 -20
  9. data/QUERYING_DOCUMENTS.md +162 -0
  10. data/README.md +2 -2
  11. data/UPDATING_DOCUMENTS.md +6 -0
  12. data/gemfiles/gemfile.rails3 +1 -1
  13. data/gemfiles/gemfile.rails4 +1 -1
  14. data/lib/om/version.rb +1 -1
  15. data/lib/om/xml/dynamic_node.rb +42 -51
  16. data/lib/tasks/om.rake +1 -1
  17. data/om.gemspec +1 -2
  18. data/spec/integration/differentiated_elements_spec.rb +2 -2
  19. data/spec/integration/element_value_spec.rb +13 -13
  20. data/spec/integration/proxies_and_ref_spec.rb +10 -10
  21. data/spec/integration/querying_documents_spec.rb +20 -27
  22. data/spec/integration/rights_metadata_integration_example_spec.rb +4 -4
  23. data/spec/integration/selective_querying_spec.rb +1 -1
  24. data/spec/integration/serialization_spec.rb +15 -15
  25. data/spec/integration/set_reentrant_terminology_spec.rb +6 -6
  26. data/spec/integration/subclass_terminology_spec.rb +8 -8
  27. data/spec/integration/xpathy_stuff_spec.rb +10 -10
  28. data/spec/unit/container_spec.rb +27 -27
  29. data/spec/unit/document_spec.rb +24 -24
  30. data/spec/unit/dynamic_node_spec.rb +60 -49
  31. data/spec/unit/named_term_proxy_spec.rb +12 -7
  32. data/spec/unit/node_generator_spec.rb +4 -4
  33. data/spec/unit/nokogiri_sanity_spec.rb +17 -18
  34. data/spec/unit/om_spec.rb +2 -2
  35. data/spec/unit/template_registry_spec.rb +51 -51
  36. data/spec/unit/term_builder_spec.rb +45 -44
  37. data/spec/unit/term_spec.rb +55 -55
  38. data/spec/unit/term_value_operators_spec.rb +205 -205
  39. data/spec/unit/term_xpath_generator_spec.rb +33 -36
  40. data/spec/unit/terminology_builder_spec.rb +50 -47
  41. data/spec/unit/terminology_spec.rb +92 -92
  42. data/spec/unit/validation_spec.rb +12 -12
  43. data/spec/unit/xml_serialization_spec.rb +20 -20
  44. data/spec/unit/xml_spec.rb +3 -3
  45. data/spec/unit/xml_terminology_based_solrizer_spec.rb +18 -18
  46. metadata +11 -38
  47. data/GETTING_FANCY.textile +0 -145
  48. data/GETTING_STARTED.textile +0 -254
  49. data/History.textile +0 -186
  50. data/QUERYING_DOCUMENTS.textile +0 -139
  51. data/UPDATING_DOCUMENTS.textile +0 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 774ca56c42282c5d31bef07b86d7f6e5e54d74b7
4
- data.tar.gz: bcf4d74285aa0283c8c4a926e988b5444f0706ae
3
+ metadata.gz: 47b327a1e5c5c97aaced259dfada9e0272a7e011
4
+ data.tar.gz: 43198216111873a28f12a414d420bccf3f1453f6
5
5
  SHA512:
6
- metadata.gz: 8c277df99dae62c250a6747bd05f68aa058477ccec12c03861818880e2ce828f20e21a1203bda0204d088830ecf59b9769caba20929fd0643bd3d28362c38091
7
- data.tar.gz: d145e98cd6c1387c58b6c98715d502b5bdb30e970050f0ab75c52c1c7fdb00b23ee83f09fdcf1c70565bd5fb6aecd3ab1794bc86b59d83dc0a2aaa1ed7a0d1a4
6
+ metadata.gz: 509267f8bedd654a287e8c97dbd55076f6c21beb31e6af88b0910a5b33c505e2e1efff7f36ae5b831731e58fe4d9723c9e6e56da568bdc12e56f7321bb87fab5
7
+ data.tar.gz: 717a6650a821571adac1077be22ef1e56d4c56d74821601c3372f48caa29ce2217a1c2d47fdb9c2be2356f3c09cd3225db80037f9a36065f057f4a1ec3aa1b12
@@ -1,10 +1,10 @@
1
- h1. Common Patterns You'll Use with OM
1
+ # Common Patterns Youll Use with OM
2
2
 
3
- h2. Common Terminology Patterns
3
+ ## Common Terminology Patterns
4
4
 
5
- Let's say we have xml like this:
5
+ Lets say we have xml like this:
6
6
 
7
- <pre>
7
+ ```text/xml
8
8
  <outer outerId="hypatia:outer" type="outer type">
9
9
  <elementA>valA</elementA>
10
10
  <elementB>valB1</elementB>
@@ -23,16 +23,15 @@ Let's say we have xml like this:
23
23
  </file>
24
24
  </resource>
25
25
  </outer>
26
- </pre>
26
+ ```
27
27
 
28
- h4. element value
28
+ #### element value
29
29
 
30
- We want an OM term for the value of an element.
30
+ We want an OM term for the value of an element.
31
31
 
32
32
  In the Datastream Model:
33
33
 
34
- <pre>
35
- # defines the expected OM terminology for example xml
34
+ ```ruby
36
35
  class ExampleXMLDS < ActiveFedora::NokogiriDatastream
37
36
  # OM (Opinionated Metadata) terminology mapping
38
37
  set_terminology do |t|
@@ -42,18 +41,19 @@ class ExampleXMLDS < ActiveFedora::NokogiriDatastream
42
41
  t.elC(:path => "elementC", :namespace_prefix => nil)
43
42
  end
44
43
  end
45
- </pre>
44
+ ```
46
45
 
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"
46
+ This results in :elementA having a value of valA and :elB having two
47
+ values of “valB1” and “valB2”, and :elC having a value of “valC”
48
48
 
49
- h4. element value given a specific attribute value
49
+ #### Element value given a specific attribute value
50
50
 
51
- We want an OM term for the value of an element, but only if the element has a specific attribute value.
51
+ We want an OM term for the value of an element, but only if the element
52
+ has a specific attribute value.
52
53
 
53
54
  In the Datastream Model:
54
55
 
55
- <pre>
56
- # defines the expected OM terminology for example xml
56
+ ```ruby
57
57
  class ExampleXMLDS < ActiveFedora::NokogiriDatastream
58
58
  # OM (Opinionated Metadata) terminology mapping
59
59
  set_terminology do |t|
@@ -63,16 +63,17 @@ class ExampleXMLDS < ActiveFedora::NokogiriDatastream
63
63
  t.there(:path=>"resource", :attributes=>{:type=>"nowhere"}, :namespace_prefix => nil)
64
64
  end
65
65
  end
66
- </pre>
66
+ ```
67
67
 
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 ""?)
68
+ This results in :elementC having a value of valC and :here having a
69
+ value of “123 456”, and :there having a value of nil (or is it “”?)
69
70
 
70
- h4. element value given absence of a specific attribute
71
+ #### element value given absence of a specific attribute
71
72
 
72
- We want an OM term for an element's value, but only if the element does not have a specific attribute.
73
+ We want an OM term for an elements value, but only if the element does
74
+ not have a specific attribute.
73
75
 
74
- <pre>
75
- # defines the expected OM terminology for example xml
76
+ ```ruby
76
77
  class ExampleXMLDS < ActiveFedora::NokogiriDatastream
77
78
  # OM (Opinionated Metadata) terminology mapping
78
79
  set_terminology do |t|
@@ -81,19 +82,18 @@ class ExampleXMLDS < ActiveFedora::NokogiriDatastream
81
82
  t.no_attrib(:path => "elementB", :attributes=>{:animal=>:none}, :namespace_prefix => nil)
82
83
  end
83
84
  end
84
- </pre>
85
+ ```
85
86
 
86
- This results in both :elementB and :no_attib having the single value "valB1"
87
+ This results in both :elementB and :no\_attib having the single value
88
+ “valB1”
87
89
 
88
-
89
- h4. attribute value
90
+ #### attribute value
90
91
 
91
92
  We want an OM term for an attribute value
92
93
 
93
- <pre>
94
- # defines the expected OM terminology for example xml
95
- class ExampleXMLDS < ActiveFedora::NokogiriDatastream
96
- # OM (Opinionated Metadata) terminology mapping
94
+ ```ruby
95
+ class ExampleXMLDS < ActiveFedora::NokogiriDatastream
96
+ # OM (Opinionated Metadata) terminology mapping
97
97
  set_terminology do |t|
98
98
  t.root(:path => "outer", :xmlns => '', :namespace_prefix => nil)
99
99
  t.elementB {
@@ -102,17 +102,17 @@ class ExampleXMLDS < ActiveFedora::NokogiriDatastream
102
102
  t.alternate(:path => "elementB/@animal", :namespace_prefix => nil)
103
103
  t.another(:proxy=>[:elementB, :my_attr_])
104
104
  t.animal_attrib(:path => {:attribute=>"animal"}, :namespace_prefix => nil)
105
- end
105
+ end
106
106
  end
107
- </pre>
108
-
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"
107
+ ```
110
108
 
109
+ This results in :my\_attr, :alternate and :another all having the single
110
+ value of “vole”, and :animal\_attrib having the values “vole” and
111
+ “seagull”
111
112
 
112
- h4. an example with :proxy and :ref
113
+ #### an example with :proxy and :ref
113
114
 
114
- <pre>
115
- # defines the expected OM terminology for example xml
115
+ ```ruby
116
116
  class ExampleXMLDS < ActiveFedora::NokogiriDatastream
117
117
  # OM (Opinionated Metadata) terminology mapping
118
118
  set_terminology do |t|
@@ -145,27 +145,25 @@ class ExampleXMLDS < ActiveFedora::NokogiriDatastream
145
145
  t.image_sha1(:proxy=>[:image, :file, :sha1])
146
146
  end
147
147
  end
148
- </pre>
148
+ ```
149
149
 
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"
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 value123
155
+ - :ead_sha1 has value 456
156
+ - :image_fedora_pid has value “hypatia:coll_img_file_asset_fixture”
157
+ - :image_ds_label has value “my_image.jpg”
158
+ - :image_size has value “302080”
159
+ - :image_md5 has value “789”
160
+ - :image_sha1 has value “666”
156
161
 
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"
162
+ #### xpath-y stuff, also using :ref and :proxy and namespaces
162
163
 
164
+ Let’s say we have xml like this:
163
165
 
164
- h4. xpath-y stuff, also using :ref and :proxy and namespaces
165
-
166
- Let's say we have xml like this:
167
-
168
- <pre>
166
+ ```text/xml
169
167
  <contentMetadata>
170
168
  <resource type="file" id="BU3A5" objectId="val2">
171
169
  <file id="BURCH1" format="BINARY">
@@ -176,14 +174,16 @@ Let's say we have xml like this:
176
174
  </file>
177
175
  </resource>
178
176
  </contentMetadata>
179
- </pre>
177
+ ```
180
178
 
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".
179
+ We want an OM term corresponding to the `<file>` element based on the
180
+ value of the `<location>` element. That is, we want to have a :content
181
+ term when the value of `<location>` is “content” and an :html term when
182
+ the value of `<location>` is “html”.
182
183
 
183
184
  In the Datastream Model:
184
185
 
185
- <pre>
186
- # defines the expected OM terminology for example xml
186
+ ```ruby
187
187
  class ExampleXMLDS < ActiveFedora::NokogiriDatastream
188
188
  # OM (Opinionated Metadata) terminology mapping
189
189
  t.root(:path=>"contentMetadata", :xmlns => '', :namespace_prefix => nil)
@@ -208,47 +208,50 @@ class ExampleXMLDS < ActiveFedora::NokogiriDatastream
208
208
  t.html_filename(:proxy=>[:html, :filename])
209
209
  t.html_format(:proxy=>[:html, :format])
210
210
  end
211
- </pre>
211
+ ```
212
212
 
213
213
  Another example from Molly Pickral of UVa:
214
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".
217
-
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>
215
+ We want to access just the author and the advisor from the XML below.
216
+ The two `<name>` elements must be distinguished by their `<roleTerm>` value,
217
+ a grandchild of the `<name>` element.
218
+
219
+ We want an :author term with value “Mary Pickral”, and an :advisor term
220
+ with value “David Jones”.
221
+
222
+ ```text/xml
223
+ <mods xmlns="http://www.loc.gov/mods/v3"
224
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.3"
225
+ xsi:schemaLocation="http://www.loc.gov/mods/v3
226
+ http://www.loc.gov/standards/mods/v3/mods-3-3.xsd">
227
+ <name type="personal">
228
+ <namePart type="given">Mary</namePart>
229
+ <namePart type="family">Pickral</namePart>
230
+ <affiliation>University of Virginia</affiliation>
231
+ <namePart>mpc3c</namePart>
232
+ <affiliation>University of Virginia Library</affiliation>
233
+ <role>
234
+ <roleTerm authority="marcrelator" type="code">aut</roleTerm>
235
+ <roleTerm authority="marcrelator" type="text">author</roleTerm>
236
+ </role>
237
+ </name>
238
+ <name type="personal">
239
+ <namePart>der5y</namePart>
240
+ <namePart type="given">David</namePart>
241
+ <namePart type="family">Jones</namePart>
242
+ <affiliation>University of Virginia</affiliation>
243
+ <affiliation>Architectural History Dept.</affiliation>
244
+ <role>
245
+ <roleTerm authority="marcrelator" type="code">ths</roleTerm>
246
+ <roleTerm authority="marcrelator" type="text">advisor</roleTerm>
247
+ </role>
248
+ </name>
249
+ </mods>
250
+ ```
247
251
 
248
252
  In the Datastream Model:
249
253
 
250
- <pre>
251
- # defines the expected OM terminology for mods thesis example xml
254
+ ```ruby
252
255
  class ModsThesis < ActiveFedora::NokogiriDatastream
253
256
  set_terminology do |t|
254
257
  t.root(:path=>"mods", :xmlns=>"http://www.loc.gov/mods/v3"))
@@ -269,20 +272,24 @@ class ModsThesis < ActiveFedora::NokogiriDatastream
269
272
  t.advisor_family(:proxy=>[:advisor, :family])
270
273
  end
271
274
  end
272
- </pre>
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
-
275
+ ```
276
276
 
277
+ This isn’t quite what the doctor ordered, but :author\_given and
278
+ :author\_family can be used to get the author name; similarly for
279
+ advisor.
277
280
 
278
281
  And a variant on the previous example using namespace prefixes.
279
282
 
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".
283
+ We want to access just the creator and the repository from the XML
284
+ below. The two `<name>` elements must be distinguished by their `<roleTerm>`
285
+ value, a grandchild of the `<name>` element.
286
+
287
+ We want a :creator term with value “David Small”, and a :repository term
288
+ with value “Graphic Novel Repository”.
282
289
 
283
290
  Our xml:
284
291
 
285
- <pre>
292
+ ```text/xml
286
293
  <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
294
 
288
295
  <mods:name type="personal">
@@ -298,12 +305,11 @@ Our xml:
298
305
  </mods:role>
299
306
  </mods:name>
300
307
  </mods:mods>
301
- </pre>
308
+ ```
302
309
 
303
310
  In the Datastream model:
304
311
 
305
- <pre>
306
- # defines the expected OM terminology for mods name example xml
312
+ ```ruby
307
313
  class ModsName < ActiveFedora::NokogiriDatastream
308
314
  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
315
 
@@ -326,37 +332,41 @@ class ModsName < ActiveFedora::NokogiriDatastream
326
332
  t.corporate(:proxy=>[:corporate_full, :name_part])
327
333
  t.repository(:ref=>:corporate, :path=>'name[mods:role/mods:roleTerm="repository"]', :xmlns=>"http://www.loc.gov/mods/v3", :namespace_prefix => "mods")
328
334
  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.
335
+ ```
332
336
 
337
+ This terminology not only gives the :creator and :repository values as
338
+ desired, but also has :person and :corporate terms for more generic
339
+ `<name>` xml. The `:person_full` and `:corporate_full` values include the
340
+ value of the `<roleTerm>` field, which is undesirable for display, if not
341
+ the index.
333
342
 
334
- h3. Arguments that can be used in the terminology
343
+ ### Arguments that can be used in the terminology
335
344
 
336
- e.g. :path, :default_content_path, :namespace_prefix ...
345
+ e.g. :path, :default\_content\_path, :namespace\_prefix
337
346
 
338
- ok if this is a link to the rdoc that describes ALL of these with
347
+ ok if this is a link to the rdoc that describes ALL of these with
339
348
 
349
+ ### Reserved method names (ie. id\_, root\_)
340
350
 
341
- h3. Reserved method names (ie. id_, root_)
351
+ Like Nokogiri
342
352
 
343
- Like Nokogiri ...
353
+ ### Namespaces
354
+ - oxns
355
+ - document namespaces & node namespaces
356
+ - *no namespace* (suppressing oxns in xpath queries)
344
357
 
345
- h3. Namespaces
346
- oxns
347
- document namespaces & node namespaces
348
- _no namespace_ (suppressing oxns in xpath queries)
358
+ ### :ref and :proxy Terms
349
359
 
350
- h3. :ref and :proxy Terms
360
+ If needed (as a differentiator) you can use the root element as a member
361
+ of the proxy address:
351
362
 
352
- If needed (as a differentiator) you can use the root element as a member of the proxy address:
353
- <pre>
354
- t.root(:path=>"mods")
355
- t.titleInfo {
356
- t.title
357
- }
358
- This produces a relative xpath: (e.g. //titleInfo/title)
359
- t.title(:proxy=>[:titleInfo, :title])
360
- This produces an absolute query (e.g. /mods/titleInfo/title)
361
- t.title(:proxy=>[:mods, :titleInfo, :title])
362
- </pre>
363
+ ```ruby
364
+ t.root(:path=>"mods")
365
+ t.titleInfo {
366
+ t.title
367
+ }
368
+ This produces a relative xpath: (e.g. //titleInfo/title)
369
+ t.title(:proxy=>[:titleInfo, :title])
370
+ This produces an absolute query (e.g. /mods/titleInfo/title)
371
+ t.title(:proxy=>[:mods, :titleInfo, :title])
372
+ ```
@@ -39,7 +39,7 @@ You should also add yourself to the `CONTRIBUTORS.md` file in the root of the pr
39
39
  * Please avoid working directly on the `master` branch.
40
40
  * You may find the [hub suite of commands](https://github.com/defunkt/hub) helpful
41
41
  * Make commits of logical units.
42
- * Your commit should include a high level description of your work in HISTORY.textile
42
+ * Your commit should include a high level description of your work in HISTORY.md
43
43
  * Check for unnecessary whitespace with `git diff --check` before committing.
44
44
  * Make sure your commit messages are [well formed](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
45
45
  * If you created an issue, you can close it by including "Closes #issue" in your commit message. See [Github's blog post for more details](https://github.com/blog/1386-closing-issues-via-commit-messages)
@@ -96,7 +96,7 @@ You should also add yourself to the `CONTRIBUTORS.md` file in the root of the pr
96
96
 
97
97
  ### Merging Changes
98
98
 
99
- * It is considered "poor from" to merge your own request.
99
+ * It is considered "poor form" to merge your own request.
100
100
  * Please take the time to review the changes and get a sense of what is being changed. Things to consider:
101
101
  * Does the commit message explain what is going on?
102
102
  * Does the code changes have tests? _Not all changes need new tests, some changes are refactorings_
@@ -0,0 +1,153 @@
1
+ # Getting Fancy
2
+
3
+ ## Alternative ways to Manipulate Terms, Terminologies and their Builders
4
+
5
+ There is more than one way to build a terminology.
6
+
7
+ ### OM::XML::Terminology::Builder Block Syntax
8
+
9
+ The simplest way to create an OM Terminology is to use the
10
+ [OM::XML::Terminology::Builder](OM/XML/Terminology/Builder.html) block
11
+ syntax.
12
+
13
+ In the following examples, we will show different ways of building this
14
+ Terminology:
15
+
16
+ ```ruby
17
+ builder = OM::XML::Terminology::Builder.new do |t|
18
+ t.root(:path=>"grants", :xmlns=>"http://yourmediashelf.com/schemas/hydra-dataset/v0", :schema=>"http://example.org/schemas/grants-v1.xsd")
19
+ t.grant {
20
+ t.org(:path=>"organization", :attributes=>{:type=>"funder"}) {
21
+ t.name(:index_as=>:searchable)
22
+ }
23
+ t.number
24
+ }
25
+ end
26
+ another_terminology = builder.build
27
+ ```
28
+
29
+ ### Using [OM::XML::Term](OM/XML/Term.html)::Builders
30
+
31
+ First, create the Terminology Builder object:
32
+
33
+ ```ruby
34
+ terminology_builder = OM::XML::Terminology::Builder.new
35
+ ```
36
+
37
+ The .root method handles creating the root term and setting namespaces,
38
+ schema, etc. on the Terminology:
39
+
40
+ ```ruby
41
+ terminology_builder.root(:path=>"grants", :xmlns=>"http://yourmediashelf.com/schemas/hydra-dataset/v0", :schema=>"http://example.org/schemas/grants-v1.xsd")
42
+ ```
43
+
44
+ This sets the namespaces for you and created the “grants” root term:
45
+
46
+ ```ruby
47
+ terminology_builder.namespaces
48
+ => {"oxns"=>"http://yourmediashelf.com/schemas/hydra-dataset/v0", "xmlns"=>"http://yourmediashelf.com/schemas/hydra-dataset/v0"}
49
+ terminology_builder.term_builders
50
+ ```
51
+
52
+ Create Term Builders for each of the Terms:
53
+
54
+ ```ruby
55
+ term1_builder = OM::XML::Term::Builder.new("grant", terminology_builder).path("grant")
56
+ subterm1_builder = OM::XML::Term::Builder.new("org", terminology_builder).attributes(:type=>"funder")
57
+ subsubterm_builder = OM::XML::Term::Builder.new("name", terminology_builder).index_as(:searchable)
58
+ subterm2_builder = OM::XML::Term::Builder.new("number", terminology_builder)
59
+ ```
60
+
61
+ Assemble the tree of Term builders by adding child builders to their
62
+ parents; then add the top level terms to the root term in the
63
+ Terminology builder:
64
+
65
+ ```ruby
66
+ subterm1_builder.add_child(subsubterm_builder)
67
+ term1_builder.add_child(subterm1_builder)
68
+ term1_builder.add_child(subterm2_builder)
69
+ terminology_builder.term_builders["grant"] = term1_builder
70
+ ```
71
+
72
+ Now build the Terminology, which will also call .build on each of the
73
+ Term Builders in the tree:
74
+
75
+ ```ruby
76
+ built_terminology = terminology_builder.build
77
+ ```
78
+
79
+ Test it out:
80
+
81
+ ```ruby
82
+ built_terminology.retrieve_term(:grant, :org, :name)
83
+ built_terminology.xpath_for(:grant, :org, :name)
84
+ built_terminology.root_terms
85
+ built_terminology.terms.keys # This will only return the Terms at the root of the terminology hierarchy
86
+ built_terminology.retrieve_term(:grant).children.keys
87
+ ```
88
+
89
+ ### Creating Terms & Terminologies without any Builders
90
+
91
+ If you want to manipulate Terms and Terminologies directly rather than
92
+ using the Builder classes, you can consume their APIs at any time.
93
+
94
+ People don’t often do this, but the option is there if you need it.
95
+
96
+ Create the Terminology, set its namespaces & (optional) schema:
97
+ (Note that you have to set the :oxns namespaces to match :xmlns. This is
98
+ usually done for you by the Terminology::Builder.root method.)
99
+
100
+ ```ruby
101
+ handcrafted_terminology = OM::XML::Terminology.new
102
+ handcrafted_terminology.namespaces[:xmlns] = "http://yourmediashelf.com/schemas/hydra-dataset/v0"
103
+ handcrafted_terminology.namespaces[:oxns] = "http://yourmediashelf.com/schemas/hydra-dataset/v0"
104
+ handcrafted_terminology.schema = "http://example.org/schemas/grants-v1.xsd"
105
+ ```
106
+
107
+ Create the Terms:
108
+
109
+ ```ruby
110
+ # Create term1 (the root) and set it as the root term
111
+ root_term = OM::XML::Term.new("grants")
112
+ root_term.is_root_term = true
113
+
114
+ # Create term1 (grant) and its subterms
115
+ term1 = OM::XML::Term.new("grant")
116
+
117
+ subterm1 = OM::XML::Term.new("org")
118
+ subterm1.path = "organization"
119
+ subterm1.attributes = {:type=>"funder"}
120
+
121
+ subsubterm = OM::XML::Term.new("name")
122
+ subsubterm.index_as = :searchable
123
+
124
+ subterm2 = OM::XML::Term.new("number")
125
+ ```
126
+
127
+ Assemble the tree of terms by adding child terms to their parents, then
128
+ add those to the Terminology.
129
+
130
+ ```ruby
131
+ subterm1.add_child(subsubterm)
132
+ term1.add_child(subterm1)
133
+ term1.add_child(subterm2)
134
+ handcrafted_terminology.add_term(root_term)
135
+ handcrafted_terminology.add_term(term1)
136
+ ```
137
+
138
+ Generate the xpath queries for each term. This is usually done for you
139
+ by the Term Builder.build method:
140
+
141
+ ```ruby
142
+ [root_term, term1, subterm1, subsubterm, subterm2].each {|t| t.generate_xpath_queries!}
143
+ ```
144
+
145
+ Test it out:
146
+
147
+ ```ruby
148
+ handcrafted_terminology.retrieve_term(:grant, :org, :name)
149
+ handcrafted_terminology.xpath_for(:grant, :org, :name)
150
+ handcrafted_terminology.root_terms
151
+ handcrafted_terminology.terms.keys # This will only return the Terms at the root of the terminology hierarchy
152
+ handcrafted_terminology.retrieve_term(:grant).children.keys
153
+ ```