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
@@ -0,0 +1,329 @@
1
+ # OM (Opinionated Metadata) - Getting Started
2
+
3
+ OM allows you to define a “terminology” to ease translation between XML
4
+ and ruby objects - you can query the xml for Nodes *or* node values
5
+ without ever writing a line of XPath.
6
+
7
+ OM “terms” are ruby symbols you define (in the terminology) that map
8
+ specific XML content into ruby object attributes.
9
+
10
+ The API documentation at [http://rdoc.info/github/projecthydra/om]
11
+ provides additional, more targeted information. We will provide links to
12
+ the API as appropriate.
13
+
14
+ ## What you will learn from this document
15
+
16
+ 1. Install OM and run it in IRB
17
+ 2. Build an OM Terminology
18
+ 3. Use OM XML Document class
19
+ 4. Create XML from the OM XML Document
20
+ 5. Load existing XML into an OM XML Document
21
+ 6. Query OM XML Document to get term values
22
+ 7. Access the Terminology of an OM XML Document
23
+ 8. Retrieve XPath from the terminology
24
+
25
+ ## Install OM
26
+
27
+ To get started, you will create a new folder, set up a Gemfile to
28
+ install OM, and then run bundler.
29
+
30
+ ```bash
31
+ mkdir omtest
32
+ cd omtest
33
+ ```
34
+
35
+ Using whichever editor you prefer, create a file (in omtest directory)
36
+ called Gemfile with the following contents:
37
+
38
+ ```ruby
39
+ source 'https://rubygems.org'
40
+ gem 'om'
41
+ ```
42
+
43
+ Now run bundler to install the gem: (you will need the bundler Gem)
44
+
45
+ bundle install
46
+
47
+ You should now be set to use irb to run the following example.
48
+
49
+ ## Build a simple OM terminology (in irb)
50
+
51
+ To experiment with abbreviated terminology examples, irb is your friend.
52
+ If you are working on a persistent terminology and have to experiment to
53
+ make sure you declare your terminology correctly, we recommend writing
54
+ test code (e.g. with rspec). You can see examples of this
55
+ [here](https://github.com/projecthydra/hydra-tutorial-application/blob/master/spec/models/journal_article_mods_datastream_spec.rb)
56
+
57
+ ```irb
58
+ irb
59
+ require "rubygems"
60
+ => true
61
+ require "om"
62
+ => true
63
+ ```
64
+
65
+ Create a simple (simplish?) Terminology Builder
66
+ ([OM::XML::Terminology::Builder](OM/XML/Terminology/Builder.html))
67
+ based on a couple of elements from the MODS schema.
68
+
69
+ ```ruby
70
+ terminology_builder = OM::XML::Terminology::Builder.new do |t|
71
+ t.root(:path=>"mods", :xmlns=>"http://www.loc.gov/mods/v3", :schema=>"http://www.loc.gov/standards/mods/v3/mods-3-2.xsd")
72
+ # This is a mods:name. The underscore is purely to avoid namespace conflicts.
73
+ t.name_ {
74
+ t.namePart
75
+ t.role(:ref=>[:role])
76
+ t.family_name(:path=>"namePart", :attributes=>{:type=>"family"})
77
+ t.given_name(:path=>"namePart", :attributes=>{:type=>"given"}, :label=>"first name")
78
+ t.terms_of_address(:path=>"namePart", :attributes=>{:type=>"termsOfAddress"})
79
+ }
80
+
81
+ # Re-use the structure of a :name Term with a different @type attribute
82
+ t.person(:ref=>:name, :attributes=>{:type=>"personal"})
83
+ t.organization(:ref=>:name, :attributes=>{:type=>"corporate"})
84
+
85
+ # This is a mods:role, which is used within mods:namePart elements
86
+ t.role {
87
+ t.text(:path=>"roleTerm",:attributes=>{:type=>"text"})
88
+ t.code(:path=>"roleTerm",:attributes=>{:type=>"code"})
89
+ }
90
+ end
91
+ ```
92
+
93
+ Now tell the Terminology Builder to build your
94
+ [OM::XML::Terminology](OM/XML/Terminology.html):
95
+
96
+ terminology = terminology_builder.build
97
+
98
+ ## OM Documents
99
+
100
+ Generally you will use an [OM::XML::Document](OM/XML/Document.html) to
101
+ work with your xml. Here’s how to define a Document class that uses the
102
+ same Terminology as above.
103
+
104
+ In a separate window (so you can keep irb running), create the file
105
+ `my_mods_document.rb` in the omtest directory, with this content:
106
+
107
+ ```ruby
108
+ class MyModsDocument < ActiveFedora::NokogiriDatastream
109
+ include OM::XML::Document
110
+
111
+ set_terminology do |t|
112
+ t.root(:path=>"mods", :xmlns=>"http://www.loc.gov/mods/v3", :schema=>"http://www.loc.gov/standards/mods/v3/mods-3-2.xsd")
113
+ # This is a mods:name. The underscore is purely to avoid namespace conflicts.
114
+ t.name_ {
115
+ t.namePart
116
+ t.role(:ref=>[:role])
117
+ t.family_name(:path=>"namePart", :attributes=>{:type=>"family"})
118
+ t.given_name(:path=>"namePart", :attributes=>{:type=>"given"}, :label=>"first name")
119
+ t.terms_of_address(:path=>"namePart", :attributes=>{:type=>"termsOfAddress"})
120
+ }
121
+ t.person(:ref=>:name, :attributes=>{:type=>"personal"})
122
+ t.organization(:ref=>:name, :attributes=>{:type=>"corporate"})
123
+
124
+ # This is a mods:role, which is used within mods:namePart elements
125
+ t.role {
126
+ t.text(:path=>"roleTerm",:attributes=>{:type=>"text"})
127
+ t.code(:path=>"roleTerm",:attributes=>{:type=>"code"})
128
+ }
129
+ end
130
+
131
+ # Generates an empty Mods Article (used when you call ModsArticle.new without passing in existing xml)
132
+ # (overrides default behavior of creating a plain xml document)
133
+ def self.xml_template
134
+ # use Nokogiri to build the XML
135
+ builder = Nokogiri::XML::Builder.new do |xml|
136
+ xml.mods(:version=>"3.3", "xmlns:xlink"=>"http://www.w3.org/1999/xlink",
137
+ "xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
138
+ "xmlns"=>"http://www.loc.gov/mods/v3",
139
+ "xsi:schemaLocation"=>"http://www.loc.gov/mods/v3 http://www.loc.gov/standards/mods/v3/mods-3-3.xsd") {
140
+ xml.titleInfo(:lang=>"") {
141
+ xml.title
142
+ }
143
+ xml.name(:type=>"personal") {
144
+ xml.namePart(:type=>"given")
145
+ xml.namePart(:type=>"family")
146
+ xml.affiliation
147
+ xml.computing_id
148
+ xml.description
149
+ xml.role {
150
+ xml.roleTerm("Author", :authority=>"marcrelator", :type=>"text")
151
+ }
152
+ }
153
+ }
154
+ end
155
+ # return a Nokogiri::XML::Document, not an OM::XML::Document
156
+ return builder.doc
157
+ end
158
+ end
159
+ ```
160
+
161
+ (Note that we are now also using the ActiveFedora gem.)
162
+
163
+ [OM::XML::Document](OM/XML/Document.html) provides the `set_terminology`
164
+ method to handle the details of creating a TerminologyBuilder and
165
+ building the terminology for you. This allows you to focus on defining
166
+ the structures of the Terminology itself.
167
+
168
+ ### Creating XML Documents from Scratch using OM
169
+
170
+ By default, new OM Document instances will create an empty xml document,
171
+ but if you override `self.xml_template` to return a different object
172
+ (e.g.
173
+ [Nokogiri::XML::Document](http://nokogiri.rubyforge.org/nokogiri/Nokogiri/XML/Document.html)),
174
+ that will be created instead.
175
+
176
+ In the example above, we have overridden `xml_template` to build an
177
+ empty, relatively simple MODS document as a
178
+ [Nokogiri::XML::Document](http://nokogiri.rubyforge.org/nokogiri/Nokogiri/XML/Document.html).
179
+ We use
180
+ [Nokogiri::XML::Builder](http://nokogiri.rubyforge.org/nokogiri/Nokogiri/XML/Builder.html)
181
+ and call its .doc method at the end of xml\_template in order to return
182
+ the
183
+ [Nokogiri::XML::Document](http://nokogiri.rubyforge.org/nokogiri/Nokogiri/XML/Document.html)
184
+ object. Instead of using
185
+ [Nokogiri::XML::Builder](http://nokogiri.rubyforge.org/nokogiri/Nokogiri/XML/Builder.html),
186
+ you could put your template into an actual xml file and have
187
+ xml\_template use
188
+ [Nokogiri::XML::Document.parse](http://nokogiri.rubyforge.org/nokogiri/Nokogiri/XML/Document.html#M000225)
189
+ to load it. That’s up to you. Create the documents however you want, just return a
190
+ [Nokogiri::XML::Document](http://nokogiri.rubyforge.org/nokogiri/Nokogiri/XML/Document.html).
191
+
192
+ To use
193
+ [Nokogiri::XML::Builder](http://nokogiri.rubyforge.org/nokogiri/Nokogiri/XML/Builder.html)
194
+
195
+ ```
196
+ require "my_mods_document"
197
+ newdoc = MyModsDocument.new
198
+ newdoc.to_xml
199
+ => NoMethodError: undefined method `to_xml' for nil:NilClass
200
+ ```
201
+
202
+ ### Loading an existing XML document with OM
203
+
204
+ To load existing XML into your OM Document, use
205
+ [#from_xml](OM/XML/Container/ClassMethods.html#from_xml-instance_method")
206
+
207
+ For an example, download
208
+ [hydrangea_article1.xml](https://github.com/projecthydra/om/blob/master/spec/fixtures/mods_articles/hydrangea_article1.xml)
209
+ into your working directory (omtest), then run this in irb:
210
+
211
+ ```ruby
212
+ sample_xml = File.new("hydrangea_article1.xml")
213
+ doc = MyModsDocument.from_xml(sample_xml)
214
+ ```
215
+
216
+ Take a look at the document object’s xml that you’ve just populated. We
217
+ will use this document for the next few examples.
218
+
219
+ ```ruby
220
+ doc.to_xml
221
+ ```
222
+
223
+ ### Querying OM Documents
224
+
225
+ Using the Terminology associated with your Document, you can query the
226
+ xml for nodes *or* node values without ever writing a line of XPath.
227
+
228
+ You can use OM::XML::Document.find\_by\_terms to retrieve xml *nodes*
229
+ from the datastream. It returns Nokogiri::XML::Node objects:
230
+
231
+ ```ruby
232
+ doc.find_by_terms(:person)
233
+ doc.find_by_terms(:person).length
234
+ doc.find_by_terms(:person).each {|n| puts n.to_xml}
235
+ ```
236
+
237
+ You might prefer to use nodes as a way of getting multiple values
238
+ pertaining to a node, rather than doing more expensive lookups for each
239
+ desired value.
240
+
241
+ If you want to get directly to the *values* within those nodes, use
242
+ `OM::XML::Document.term_values`:
243
+
244
+ ```ruby
245
+ doc.term_values(:person, :given_name)
246
+ doc.term_values(:person, :family_name)
247
+ ```
248
+
249
+ If the xpath points to XML nodes that contain other nodes, the response
250
+ to `term_values` will contain `Nokogiri::XML::Node` objects instead of text
251
+ values:
252
+
253
+ ```ruby
254
+ doc.term_values(:name)
255
+ ```
256
+
257
+ For more examples of Querying OM Documents, see [Querying
258
+ Documents](https://github.com/projecthydra/om/blob/master/QUERYING_DOCUMENTS.md)
259
+
260
+ ### Updating, Inserting & Deleting Elements (TermValueOperators)
261
+
262
+ For more examples of Updating OM Documents, see [Updating
263
+ Documents](https://github.com/projecthydra/om/blob/master/UPDATING_DOCUMENTS.md)
264
+
265
+ ### Validating Documents
266
+
267
+ If you have an XML schema defined in your Terminology’s root Term, you
268
+ can validate any xml document by calling `.validate` on any instance of
269
+ your Document classes.
270
+
271
+ ```ruby
272
+ doc.validate
273
+ ```
274
+
275
+ **Note:** this method *requires an internet connection*, as it will
276
+ download the XML schema from the URL you have specified in the
277
+ Terminology’s root term.
278
+
279
+ ### Directly accessing the [Nokogiri::XML::Document](http://nokogiri.rubyforge.org/nokogiri/Nokogiri/XML/Document.html) and the [OM::XML::Terminology](https://github.com/projecthydra/om/blob/master/lib/om/xml/terminology.rb)
280
+
281
+ [OM::XML::Document](https://github.com/projecthydra/om/blob/master/lib/om/xml/document.rb)
282
+ is implemented as a container for a
283
+ [Nokogiri::XML::Document](http://nokogiri.rubyforge.org/nokogiri/Nokogiri/XML/Document.html).
284
+ It uses the associated OM Terminology to provide a bunch of convenience
285
+ methods that wrap calls to Nokogiri. If you ever need to operate
286
+ directly on the Nokogiri Document, simply call ng\_xml and do what you
287
+ need to do. OM will not get in your way.
288
+
289
+ ```ruby
290
+ ng_document = doc.ng_xml
291
+ ```
292
+
293
+ If you need to look at the Terminology associated with your Document,
294
+ call
295
+ [#terminology](OM/XML/Document/ClassMethods.html#terminology-instance_method)
296
+ on the Document’s *class*.
297
+
298
+ ```ruby
299
+ MyModsDocument.terminology
300
+ doc.class.terminology
301
+ ```
302
+
303
+ ### Using a Terminology to generate XPath Queries based on Term Pointers
304
+
305
+ Because the Terminology is essentially a mapping from XPath queries to
306
+ ruby object attributes, in most cases you won’t need to know the actual
307
+ XPath queries. Nevertheless, when you *do* want to know the Xpath
308
+ (e.g. for ensuring your terminology is correct) for a term, the
309
+ Terminology can generate xpath queries based on the structures you’ve
310
+ defined ([OM::XML::TermXPathGenerator](OM/XML/TermXpathGenerator.html)).
311
+
312
+ Here are the xpaths for `:name` and two variants of `:name` that were
313
+ created using the `:ref` argument in the Terminology Builder:
314
+
315
+ ```irb
316
+ terminology.xpath_for(:name)
317
+ => "//oxns:name"
318
+ terminology.xpath_for(:person)
319
+ => "//oxns:name[@type=\"personal\"]"
320
+ terminology.xpath_for(:organization)
321
+ => "//oxns:name[@type=\"corporate\"]"
322
+ ```
323
+
324
+ ### Solrizing Documents
325
+
326
+ The solrizer gem provides support for indexing XML documents into Solr
327
+ based on OM Terminologies. That process is documented in the [solrizer
328
+ documentation](http://rdoc.info/github/projecthydra/solrizer).
329
+
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source "http://rubygems.org"
1
+ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
@@ -0,0 +1,164 @@
1
+ - 2014-09-11: Use HTTPS URLs for RubyGems [Michael Slone]
2
+
3
+ ### 3.1.0 (17 Jul 2014)
4
+ - 2014-07-17: Bump solrizer version to \~\> 3.3 [Justin Coyne]
5
+ - 2014-07-17: Use the system libxml2 on travis [Justin Coyne]
6
+ - 2014-07-17: Remove dependency on mediashelf-loggable [Justin Coyne]
7
+ - 2014-06-13: Setting values on a proxy term should build the parent terms if they don’t exist [Justin Coyne]
8
+ - 2014-06-05: Handle invalid time for Rails 3 [Justin Coyne]
9
+ - 2014-06-02: Updating solrizer, correcting rspec deprecations [Adam Wead]
10
+
11
+ ### 3.0.1 (25 Jun 2013)
12
+ - Fix bug where values that were the same as the existing values were removed from the update list
13
+
14
+ ### 3.0.0 (20 Jun 2013)
15
+ - Return an array instead of a hash Term\#update\_values
16
+ - When passing an array to Term\#update\_values, it will overwrite all of the existing values of that term.
17
+ - OM::XML::Document\#find\_by\_terms\_and\_value should match strings with text() = xpath query, rather than contains().
18
+
19
+ ### 2.2.1 (20 Jun 2013)
20
+ - Revert deprecation of passing Hash values
21
+
22
+ ### 2.2.0 (20 June 2013)
23
+ - Deprecate passing Hash values into DynamicNode\#val= or
24
+ - Document\#update\_attributes. This behavior will be removed in 3.0.0
25
+ - Rails 4 support
26
+ - Pass nil in order to remove a node (instead of blank string)
27
+
28
+ ### 2.1.2 (3 May 2013)
29
+ - Fix missing comma after exception
30
+
31
+ ### 2.1.1 (2 May 2013)
32
+ - bump solrizer to 3.1.0
33
+
34
+ ### 2.1.0 (29 April 2013)
35
+ - support for element names with periods in them
36
+ - support for ‘type: :time’
37
+
38
+ ### 2.0.0
39
+ - Support new solr schema
40
+
41
+ ### 1.8.0
42
+ - Removed unused mods\_article\_terminology.xml
43
+ - Replacing :data\_type with :type; deprecating :data\_type
44
+ - Making test related to HYDRA-647 pending
45
+ - Adding .type method for ruby 1.8.7 compatibility
46
+ - XML serialization should use the data\_type node name and not type
47
+ - Update homepage in gemspec
48
+ - Remove .rvmrc
49
+ - Remove debugger from gemfile
50
+
51
+ ### 1.7.0
52
+ - Add casting to dates and integers when you specify the :type attribute on a terminology node
53
+
54
+ ### 1.6.1
55
+ - Integration spec to illustrate selective querying.
56
+ - Add \#use\_terminology and \#extend\_terminology methods to extend existing OM terminologies
57
+
58
+ ### 1.6.0
59
+ - Delegate all methods on the dynamic node to the found values
60
+ - Allow arrays to be set on dynamic nodes
61
+
62
+ ### 1.5.3
63
+ - HYDRA-657 OM Terms that share a name with methods on Nokogiri Builders
64
+ have incorrect builder templates
65
+ - HYDRA-674 XML Builder templates incorrect for :none attributes
66
+
67
+ ### 1.5.2
68
+ - HYDRA-742 Can’t modify frozen string (parameters in rails 3.2, when using ruby 1.9.3)
69
+
70
+ ### 1.5.1
71
+ - HYDRA-737 OM tests fail under ree 1.8.7-2011.12 (Fix also applies to ruby 1.8.7-p357)
72
+
73
+ ### 1.5.0
74
+ - HYDRA-358 Added support for namespaceless terminologies
75
+
76
+ ### 1.4.4
77
+ - HYDRA-415 [https://jira.duraspace.org/browse/HYDRA-415] Fixed insert of attribute nodes
78
+ - update to rspec2
79
+ - compatibility fixes for ruby 1.9
80
+ - RedCloth updated to 4.2.9
81
+ - Replace local ‘delimited_list’ logic with `Array#join`
82
+
83
+ ### 1.4.3
84
+ - HYDRA-681 https://jira.duraspace.org/browse/HYDRA-681 Om was calling
85
+ `.dirty` when updating nodes, it should only do that when it’s operating on a `Nokogiri:Datastream`
86
+ - HYDRA-682 https://jira.duraspace.org/browse/HYDRA-682 Om first level terms support update
87
+
88
+ ### 1.4.2
89
+ - [HYDRA-667](https://jira.duraspace.org/browse/HYDRA-667) Fixed bug where
90
+ updating nodes wasn’t marking the document as dirty
91
+
92
+ ### 1.4.0
93
+ - Added dynamic node access DSL. Added a warning when calling an index on a proxy term.
94
+
95
+ ### 1.3.0
96
+ - Document automatically includes Validation module, meaning that you can
97
+ now call .validate on any document
98
+
99
+ ### 1.2.4
100
+ - TerminologyBuilder.root now passes on its options to the root term builder that it creates.
101
+
102
+ ### 1.2.3
103
+ - NamedTermProxies can now point to terms at the root of a Terminology
104
+
105
+ ### 1.2.0
106
+ - Added OM::XML::TemplateRegistry for built-in templating and creation of new XML nodes
107
+
108
+ ### 1.1.1
109
+ - [HYDRA-395](https://jira.duraspace.org/browse/HYDRA-395): Fixed bug that
110
+ prevented you from appending term values with apostrophes in them
111
+
112
+ ### 1.1.0
113
+ - HYDRA-371: Provide a way to specify a term that points to nodes where an attribute is not set
114
+
115
+ Add support for this syntax in Terminologies, where an attribute value
116
+ can be :none. When an attribute’s value is set to :none, a not()
117
+ predicate is used in the resulting xpath
118
+
119
+ ```ruby
120
+ t.computing\_id(:path=\>“namePart”, :attributes=\>{:type=\>:none})
121
+ ```
122
+
123
+ will result in an xpath that looks like:
124
+
125
+ ```
126
+ //namePart[not(@type)]
127
+ namePart[not(@type)]
128
+ ```
129
+
130
+ ### 1.0.1
131
+ - HYDRA-329: Allow for NamedTermProxies at root of Terminology
132
+
133
+ ### 1.0.0
134
+ **Stable release**
135
+
136
+ ### 0.1.10
137
+ - Improving generation of constrained xpath queries
138
+
139
+ ### 0.1.9
140
+ - Improving support for deeply nested nodes (still needs work though)
141
+
142
+ ### 0.1.5
143
+ - root\_property now inserts an entry into the properties hash
144
+ - added `.generate` method for building new instances of declared properties
145
+ - refinements to accessor\_xpath
146
+
147
+ ### 0.1.4
148
+ - made attribute\_xpath idempotent
149
+
150
+ ### 0.1.3
151
+ - added accessor\_generic\_name and accessor\_hierarchical\_name methods
152
+
153
+ ### 0.1.2
154
+ - changed syntax for looking up accessors with (optional) index values
155
+ — no using [{:person=\>1}, :first\_name] instead of [:person, 1, :first\_name]
156
+
157
+ ### 0.1.1
158
+ - RENAMED to om (formerly opinionated-xml)
159
+ - broke up functionality into Modules
160
+ - added `OM::XML::Accessor` functionality
161
+
162
+ ### 0.1
163
+ - Note: OX v.1 Does not handle treating attribute values as the changing “value” of a node
164
+