om 1.8.1 → 1.9.0.pre1
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.
- data/Rakefile +1 -1
- data/container_spec.rb +14 -14
- data/lib/om.rb +12 -9
- data/lib/om/samples/mods_article.rb +9 -9
- data/lib/om/tree_node.rb +6 -6
- data/lib/om/version.rb +1 -1
- data/lib/om/xml.rb +33 -31
- data/lib/om/xml/container.rb +12 -12
- data/lib/om/xml/document.rb +19 -18
- data/lib/om/xml/dynamic_node.rb +50 -45
- data/lib/om/xml/named_term_proxy.rb +13 -13
- data/lib/om/xml/node_generator.rb +3 -3
- data/lib/om/xml/template_registry.rb +26 -18
- data/lib/om/xml/term.rb +46 -30
- data/lib/om/xml/term_value_operators.rb +56 -52
- data/lib/om/xml/term_xpath_generator.rb +57 -51
- data/lib/om/xml/terminology.rb +10 -8
- data/lib/om/xml/terminology_based_solrizer.rb +90 -0
- data/lib/om/xml/validation.rb +19 -19
- data/lib/om/xml/vocabulary.rb +4 -4
- data/lib/tasks/om.rake +6 -4
- data/om.gemspec +2 -1
- data/spec/fixtures/mods_article.rb +90 -0
- data/spec/fixtures/mods_articles/hydrangea_article1.xml +2 -2
- data/spec/integration/differentiated_elements_spec.rb +2 -2
- data/spec/integration/element_value_spec.rb +13 -13
- data/spec/integration/proxies_and_ref_spec.rb +15 -15
- data/spec/integration/querying_documents_spec.rb +18 -24
- data/spec/integration/rights_metadata_integration_example_spec.rb +18 -18
- data/spec/integration/selective_querying_spec.rb +1 -1
- data/spec/integration/serialization_spec.rb +13 -13
- data/spec/integration/set_reentrant_terminology_spec.rb +10 -10
- data/spec/integration/xpathy_stuff_spec.rb +16 -16
- data/spec/spec_helper.rb +2 -2
- data/spec/unit/container_spec.rb +29 -28
- data/spec/unit/document_spec.rb +50 -49
- data/spec/unit/dynamic_node_spec.rb +45 -57
- data/spec/unit/named_term_proxy_spec.rb +16 -16
- data/spec/unit/node_generator_spec.rb +7 -7
- data/spec/unit/nokogiri_sanity_spec.rb +30 -30
- data/spec/unit/om_spec.rb +5 -5
- data/spec/unit/template_registry_spec.rb +69 -69
- data/spec/unit/term_builder_spec.rb +77 -77
- data/spec/unit/term_spec.rb +73 -79
- data/spec/unit/term_value_operators_spec.rb +191 -186
- data/spec/unit/term_xpath_generator_spec.rb +43 -37
- data/spec/unit/terminology_builder_spec.rb +85 -85
- data/spec/unit/terminology_spec.rb +98 -98
- data/spec/unit/validation_spec.rb +22 -22
- data/spec/unit/xml_serialization_spec.rb +22 -21
- data/spec/unit/xml_spec.rb +7 -7
- data/spec/unit/xml_terminology_based_solrizer_spec.rb +109 -0
- metadata +57 -17
- checksums.yaml +0 -7
- data/.rspec +0 -1
- data/.rubocop.yml +0 -1
- data/.rubocop_todo.yml +0 -382
- data/.travis.yml +0 -10
- data/gemfiles/gemfile.rails3 +0 -11
- data/gemfiles/gemfile.rails4 +0 -10
@@ -3,12 +3,12 @@ require "logger"
|
|
3
3
|
|
4
4
|
class OM::XML::ParentNodeNotFoundError < RuntimeError; end
|
5
5
|
module OM::XML::TermValueOperators
|
6
|
-
|
6
|
+
|
7
7
|
# Retrieves all of the nodes from the current document that match +term_pointer+ and returns an array of their values
|
8
8
|
def term_values(*term_pointer)
|
9
9
|
result = []
|
10
10
|
xpath = self.class.terminology.xpath_with_indexes(*term_pointer)
|
11
|
-
#
|
11
|
+
#if value is on line by itself sometimes does not trim leading and trailing whitespace for a text node so will detect and fix it
|
12
12
|
trim_text = !xpath.nil? && !xpath.index("text()").nil?
|
13
13
|
find_by_terms(*term_pointer).each {|node| result << (trim_text ? node.text.strip : node.text) }
|
14
14
|
|
@@ -20,59 +20,61 @@ module OM::XML::TermValueOperators
|
|
20
20
|
term.deserialize(result)
|
21
21
|
end
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
# alias for term_values
|
25
25
|
def property_values(*lookup_args)
|
26
26
|
term_values(*lookup_args)
|
27
27
|
end
|
28
|
-
|
29
|
-
#
|
28
|
+
|
29
|
+
#
|
30
30
|
# example term values hash: {[{":person"=>"0"}, "role", "text"]=>{"0"=>"role1", "1"=>"role2", "2"=>"role3"}, [{:person=>1}, :family_name]=>"Andronicus", [{"person"=>"1"},:given_name]=>["Titus"],[{:person=>1},:role,:text]=>["otherrole1","otherrole2"] }
|
31
31
|
def update_values(params={})
|
32
|
-
# remove any terms from params that this datastream doesn't recognize
|
33
|
-
|
34
|
-
params.delete_if do |term_pointer,new_values|
|
32
|
+
# remove any terms from params that this datastream doesn't recognize
|
33
|
+
|
34
|
+
params.delete_if do |term_pointer,new_values|
|
35
35
|
if term_pointer.kind_of?(String)
|
36
36
|
true
|
37
37
|
else
|
38
38
|
!self.class.terminology.has_term?(*OM.destringify(term_pointer))
|
39
39
|
end
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
result = params.dup
|
43
|
-
|
43
|
+
|
44
44
|
params.each_pair do |term_pointer,new_values|
|
45
45
|
pointer = OM.destringify(term_pointer)
|
46
46
|
template_pointer = OM.pointers_to_flat_array(pointer,false)
|
47
47
|
hn = OM::XML::Terminology.term_hierarchical_name(*pointer)
|
48
|
-
|
48
|
+
|
49
49
|
term = self.class.terminology.retrieve_term( *OM.pointers_to_flat_array(pointer,false) )
|
50
50
|
|
51
51
|
# Sanitize new_values to always be a hash with indexes
|
52
52
|
new_values = term.sanitize_new_values(new_values)
|
53
|
-
|
53
|
+
|
54
54
|
# Populate the response hash appropriately, using hierarchical names for terms as keys rather than the given pointers.
|
55
55
|
result.delete(term_pointer)
|
56
56
|
result[hn] = new_values.dup
|
57
|
-
|
57
|
+
|
58
58
|
# Skip any submitted values if the new value matches the current values
|
59
59
|
current_values = term_values(*pointer)
|
60
60
|
new_values.keys.sort { |a,b| a.to_i <=> b.to_i }.each do |y|
|
61
61
|
z = new_values[y]
|
62
|
-
|
63
|
-
|
64
|
-
|
62
|
+
if current_values[y.to_i]==z and y.to_i > -1
|
63
|
+
new_values.delete(y)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
65
67
|
# Fill out the pointer completely if the final term is a NamedTermProxy
|
66
68
|
if term.kind_of? OM::XML::NamedTermProxy
|
67
69
|
pointer.pop
|
68
70
|
pointer = pointer.concat(term.proxy_pointer)
|
69
71
|
end
|
70
|
-
|
72
|
+
|
71
73
|
xpath = self.class.terminology.xpath_with_indexes(*pointer)
|
72
74
|
parent_pointer = pointer.dup
|
73
75
|
parent_pointer.pop
|
74
76
|
parent_xpath = self.class.terminology.xpath_with_indexes(*parent_pointer)
|
75
|
-
|
77
|
+
|
76
78
|
# If the value doesn't exist yet, append it. Otherwise, update the existing value.
|
77
79
|
new_values.keys.sort { |a,b| a.to_i <=> b.to_i }.each do |y|
|
78
80
|
z = new_values[y]
|
@@ -87,18 +89,18 @@ module OM::XML::TermValueOperators
|
|
87
89
|
end
|
88
90
|
end
|
89
91
|
end
|
90
|
-
result
|
92
|
+
return result
|
91
93
|
end
|
92
|
-
|
94
|
+
|
93
95
|
def term_values_append(opts={})
|
94
96
|
parent_select = Array( opts[:parent_select] )
|
95
97
|
parent_index = opts[:parent_index]
|
96
98
|
template = opts[:template]
|
97
|
-
new_values = Array( opts[:values] )
|
98
|
-
|
99
|
+
new_values = Array( opts[:values] )
|
100
|
+
|
99
101
|
parent_nodeset = find_by_terms(*parent_select)
|
100
102
|
parent_node = node_from_set(parent_nodeset, parent_index)
|
101
|
-
|
103
|
+
|
102
104
|
if parent_node.nil?
|
103
105
|
if parent_select.empty?
|
104
106
|
parent_node = ng_xml.root
|
@@ -108,12 +110,12 @@ module OM::XML::TermValueOperators
|
|
108
110
|
end
|
109
111
|
|
110
112
|
insert_from_template(parent_node, new_values, template)
|
111
|
-
|
112
|
-
parent_node
|
113
|
-
|
113
|
+
|
114
|
+
return parent_node
|
115
|
+
|
114
116
|
end
|
115
117
|
|
116
|
-
# Insert xml containing +new_values+ into +parent_node+. Generate the xml based on +template+
|
118
|
+
# Insert xml containing +new_values+ into +parent_node+. Generate the xml based on +template+
|
117
119
|
# @param [Nokogiri::XML::Node] parent_node to insert new xml into
|
118
120
|
# @param [Array] new_values to build the xml around
|
119
121
|
# @param [Array -- (OM term pointer array) OR String -- (like what you would pass into Nokogiri::XML::Builder.new)] template for building the new xml. Use the syntax that Nokogiri::XML::Builder uses.
|
@@ -131,23 +133,23 @@ module OM::XML::TermValueOperators
|
|
131
133
|
template = self.class.terminology.xml_builder_template( *template_args )
|
132
134
|
end
|
133
135
|
|
134
|
-
#
|
136
|
+
#if there is an xpath element pointing to text() need to change to just 'text' so it references the text method for the parent node
|
135
137
|
template.gsub!(/text\(\)/, 'text')
|
136
|
-
|
138
|
+
|
137
139
|
builder = Nokogiri::XML::Builder.with(parent_node) do |xml|
|
138
140
|
new_values.each do |builder_new_value|
|
139
141
|
builder_new_value = builder_new_value.gsub(/'/, "\\\\'") # escape any apostrophes in the new value
|
140
142
|
if matchdata = /xml\.@(\w+)/.match(template)
|
141
143
|
parent_node.set_attribute(matchdata[1], builder_new_value)
|
142
|
-
else
|
144
|
+
else
|
143
145
|
builder_arg = eval('"'+ template + '"') # this inserts builder_new_value into the builder template
|
144
146
|
eval(builder_arg)
|
145
147
|
end
|
146
148
|
end
|
147
149
|
end
|
148
|
-
parent_node
|
150
|
+
return parent_node
|
149
151
|
end
|
150
|
-
|
152
|
+
|
151
153
|
# Creates necesary ancestor nodes to support inserting a new term value where the ancestor node(s) don't exist yet.
|
152
154
|
# Corrects node indexes in the pointer array to correspond to the ancestors that it creates.
|
153
155
|
# Returns a two-value array with the 'parent' node and a corrected pointer array
|
@@ -157,18 +159,20 @@ module OM::XML::TermValueOperators
|
|
157
159
|
parent_select = Array(parent_select)
|
158
160
|
parent_nodeset = find_by_terms(*parent_select)
|
159
161
|
starting_point = node_from_set(parent_nodeset, parent_index)
|
160
|
-
|
162
|
+
if starting_point.nil?
|
163
|
+
starting_point = []
|
164
|
+
end
|
161
165
|
to_build = []
|
162
|
-
|
166
|
+
until !starting_point.empty?
|
163
167
|
to_build = [parent_select.pop] + to_build
|
164
168
|
starting_point = find_by_terms(*parent_select)
|
165
|
-
if starting_point.empty? && parent_select.empty?
|
169
|
+
if starting_point.empty? && parent_select.empty?
|
166
170
|
raise OM::XML::TemplateMissingException, "Cannot insert nodes into the document because it is empty. Try defining self.xml_template on the #{self.class} class."
|
167
171
|
end
|
168
172
|
end
|
169
|
-
to_build.each do |term_pointer|
|
173
|
+
to_build.each do |term_pointer|
|
170
174
|
parent_select << term_pointer
|
171
|
-
|
175
|
+
|
172
176
|
# If pointers in parent_select don't match with the indexes of built ancestors, correct the hash
|
173
177
|
if find_by_terms(*parent_select+[{}]).length == 0
|
174
178
|
if parent_select.last.kind_of?(Hash)
|
@@ -194,13 +198,13 @@ module OM::XML::TermValueOperators
|
|
194
198
|
if parent_index > starting_point.length
|
195
199
|
parent_index = starting_point.length - 1
|
196
200
|
end
|
197
|
-
node_from_set(starting_point, parent_index)
|
201
|
+
return node_from_set(starting_point, parent_index)
|
198
202
|
end
|
199
|
-
|
203
|
+
|
200
204
|
def term_value_update(node_select,node_index,new_value,opts={})
|
201
205
|
ng_xml_will_change!
|
202
206
|
# template = opts.fetch(:template,nil)
|
203
|
-
|
207
|
+
|
204
208
|
node = find_by_terms_and_value(*node_select)[node_index]
|
205
209
|
if delete_on_update?(node, new_value)
|
206
210
|
node.remove
|
@@ -212,23 +216,23 @@ module OM::XML::TermValueOperators
|
|
212
216
|
def delete_on_update?(node, new_value)
|
213
217
|
new_value == "" || new_value == :delete
|
214
218
|
end
|
215
|
-
|
219
|
+
|
216
220
|
# def term_value_set(term_ref, query_opts, node_index, new_value)
|
217
221
|
# end
|
218
|
-
|
222
|
+
|
219
223
|
def term_value_delete(opts={})
|
220
224
|
ng_xml_will_change!
|
221
225
|
parent_select = Array( opts[:parent_select] )
|
222
226
|
parent_index = opts[:parent_index]
|
223
227
|
child_index = opts[:child_index]
|
224
228
|
xpath_select = opts[:select]
|
225
|
-
|
229
|
+
|
226
230
|
if !xpath_select.nil?
|
227
231
|
node = find_by_terms_and_value(xpath_select).first
|
228
232
|
else
|
229
233
|
# parent_nodeset = find_by_terms_and_value(parent_select, parent_select)
|
230
234
|
parent_nodeset = find_by_terms_and_value(*parent_select)
|
231
|
-
|
235
|
+
|
232
236
|
if parent_index.nil?
|
233
237
|
node = node_from_set(parent_nodeset, child_index)
|
234
238
|
else
|
@@ -237,24 +241,24 @@ module OM::XML::TermValueOperators
|
|
237
241
|
node = node_from_set(parent.xpath("*"), child_index)
|
238
242
|
end
|
239
243
|
end
|
240
|
-
|
244
|
+
|
241
245
|
node.remove
|
242
246
|
end
|
243
|
-
|
244
|
-
|
247
|
+
|
248
|
+
|
245
249
|
# Allows you to provide an array index _or_ a symbol representing the function to call on the nodeset in order to retrieve the node.
|
246
250
|
def node_from_set(nodeset, index)
|
247
251
|
if index.kind_of?(Integer)
|
248
252
|
node = nodeset[index]
|
249
|
-
elsif index.kind_of?(Symbol) && nodeset.respond_to?(index)
|
253
|
+
elsif index.kind_of?(Symbol) && nodeset.respond_to?(index)
|
250
254
|
node = nodeset.send(index)
|
251
255
|
else
|
252
256
|
raise "Could not retrieve node using index #{index}."
|
253
257
|
end
|
254
|
-
|
255
|
-
node
|
258
|
+
|
259
|
+
return node
|
256
260
|
end
|
257
|
-
|
261
|
+
|
258
262
|
private :node_from_set
|
259
|
-
|
263
|
+
|
260
264
|
end
|
@@ -1,27 +1,27 @@
|
|
1
1
|
require 'loggable'
|
2
2
|
module OM::XML::TermXpathGenerator
|
3
3
|
include Loggable
|
4
|
-
|
4
|
+
|
5
5
|
# Generate relative xpath for a term
|
6
6
|
# @param [OM::XML::Term] term that you want to generate relative xpath for
|
7
7
|
#
|
8
8
|
# In most cases, the resulting xpath will be the Term's path with the appropriate namespace appended to it.
|
9
|
-
# If the Term specifies any attributes,
|
9
|
+
# If the Term specifies any attributes,
|
10
10
|
# Special Case: attribute Terms
|
11
|
-
# If the Term's path is set to {:attribute=>attr_name}, the resulting xpath will points to a node attribute named attr_name
|
11
|
+
# If the Term's path is set to {:attribute=>attr_name}, the resulting xpath will points to a node attribute named attr_name
|
12
12
|
# ie. a path fo {:attribute=>"lang"} will result in a relative xpath of "@lang"
|
13
13
|
# Special Case: xpath functions
|
14
14
|
# If the Term's path variable is text(), it will be treated as an xpath function (no namespace) and turned into "text()[normalize-space(.)]"
|
15
15
|
def self.generate_relative_xpath(term)
|
16
16
|
template = ""
|
17
17
|
predicates = []
|
18
|
-
|
18
|
+
|
19
19
|
if term.namespace_prefix.nil?
|
20
20
|
complete_prefix = ""
|
21
21
|
else
|
22
22
|
complete_prefix = term.namespace_prefix + ":"
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
if term.path.kind_of?(Hash)
|
26
26
|
if term.path.has_key?(:attribute)
|
27
27
|
base_path = "@"+term.path[:attribute]
|
@@ -32,12 +32,14 @@ module OM::XML::TermXpathGenerator
|
|
32
32
|
if term.path == "text()"
|
33
33
|
base_path = "#{term.path}[normalize-space(.)]"
|
34
34
|
else
|
35
|
-
|
35
|
+
unless term.namespace_prefix.nil?
|
36
|
+
template << complete_prefix
|
37
|
+
end
|
36
38
|
base_path = term.path
|
37
39
|
end
|
38
40
|
end
|
39
41
|
template << base_path
|
40
|
-
|
42
|
+
|
41
43
|
unless term.attributes.nil?
|
42
44
|
term.attributes.each_pair do |attr_name, attr_value|
|
43
45
|
if attr_value == :none
|
@@ -47,14 +49,14 @@ module OM::XML::TermXpathGenerator
|
|
47
49
|
end
|
48
50
|
end
|
49
51
|
end
|
50
|
-
|
51
|
-
unless predicates.empty?
|
52
|
+
|
53
|
+
unless predicates.empty?
|
52
54
|
template << "["+ delimited_list(predicates, " and ")+"]"
|
53
55
|
end
|
54
|
-
|
55
|
-
template
|
56
|
+
|
57
|
+
return template
|
56
58
|
end
|
57
|
-
|
59
|
+
|
58
60
|
# Generate absolute xpath for a Term
|
59
61
|
# @param [OM::XML::Term] term that you want to generate absolute xpath for
|
60
62
|
#
|
@@ -67,36 +69,36 @@ module OM::XML::TermXpathGenerator
|
|
67
69
|
return term.parent.xpath_absolute + "/" + relative
|
68
70
|
end
|
69
71
|
end
|
70
|
-
|
72
|
+
|
71
73
|
def self.generate_constrained_xpath(term)
|
72
74
|
if term.namespace_prefix.nil?
|
73
75
|
complete_prefix = ""
|
74
76
|
else
|
75
77
|
complete_prefix = term.namespace_prefix + ":"
|
76
78
|
end
|
77
|
-
|
79
|
+
|
78
80
|
absolute = generate_absolute_xpath(term)
|
79
81
|
constraint_predicates = []
|
80
|
-
|
82
|
+
|
81
83
|
arguments_for_contains_function = []
|
82
84
|
|
83
|
-
|
85
|
+
if !term.default_content_path.nil?
|
84
86
|
arguments_for_contains_function << "#{complete_prefix}#{term.default_content_path}"
|
85
87
|
end
|
86
|
-
|
88
|
+
|
87
89
|
# If no subelements have been specified to search within, set contains function to search within the current node
|
88
90
|
if arguments_for_contains_function.empty?
|
89
91
|
arguments_for_contains_function << "."
|
90
92
|
end
|
91
|
-
|
93
|
+
|
92
94
|
arguments_for_contains_function << "\":::constraint_value:::\""
|
93
|
-
|
95
|
+
|
94
96
|
contains_function = "contains(#{delimited_list(arguments_for_contains_function)})"
|
95
97
|
|
96
98
|
template = add_predicate(absolute, contains_function)
|
97
|
-
template.gsub( /:::(.*?):::/ ) { '#{'+$1+'}' }.gsub('"', '\"')
|
99
|
+
return template.gsub( /:::(.*?):::/ ) { '#{'+$1+'}' }.gsub('"', '\"')
|
98
100
|
end
|
99
|
-
|
101
|
+
|
100
102
|
# Generate an xpath of the chosen +type+ for the given Term.
|
101
103
|
# @param [OM::XML::Term] term that you want to generate relative xpath for
|
102
104
|
# @param [Symbol] the type of xpath to generate, :relative, :abolute, or :constrained
|
@@ -110,9 +112,9 @@ module OM::XML::TermXpathGenerator
|
|
110
112
|
self.generate_constrained_xpath(term)
|
111
113
|
end
|
112
114
|
end
|
113
|
-
|
115
|
+
|
114
116
|
# Use the given +terminology+ to generate an xpath with (optional) node indexes for each of the term pointers.
|
115
|
-
# Ex. OM::XML::TermXpathGenerator.xpath_with_indexes(my_terminology, {:conference=>0}, {:role=>1}, :text )
|
117
|
+
# Ex. OM::XML::TermXpathGenerator.xpath_with_indexes(my_terminology, {:conference=>0}, {:role=>1}, :text )
|
116
118
|
# will yield an xpath similar to this: '//oxns:name[@type="conference"][1]/oxns:role[2]/oxns:roleTerm[@type="text"]'
|
117
119
|
# @param [OM::XML::Terminology] terminology to generate xpath based on
|
118
120
|
# @param [String -- OM term pointer] pointers identifying the node to generate xpath for
|
@@ -125,28 +127,30 @@ module OM::XML::TermXpathGenerator
|
|
125
127
|
return root_term.xpath
|
126
128
|
end
|
127
129
|
end
|
128
|
-
|
130
|
+
|
129
131
|
query_constraints = nil
|
130
|
-
|
132
|
+
|
131
133
|
if pointers.length > 1 && pointers.last.kind_of?(Hash)
|
132
134
|
constraints = pointers.pop
|
133
|
-
|
135
|
+
unless constraints.empty?
|
136
|
+
query_constraints = constraints
|
137
|
+
end
|
134
138
|
end
|
135
139
|
|
136
140
|
if pointers.length == 1 && pointers.first.instance_of?(String)
|
137
141
|
return xpath_query = pointers.first
|
138
142
|
end
|
139
|
-
|
143
|
+
|
140
144
|
# if pointers.first.kind_of?(String)
|
141
145
|
# return pointers.first
|
142
146
|
# end
|
143
|
-
|
147
|
+
|
144
148
|
keys = []
|
145
149
|
xpath = "//"
|
146
150
|
|
147
151
|
pointers = OM.destringify(pointers)
|
148
152
|
pointers.each_with_index do |pointer, pointer_index|
|
149
|
-
|
153
|
+
|
150
154
|
if pointer.kind_of?(Hash)
|
151
155
|
k = pointer.keys.first
|
152
156
|
index = pointer[k]
|
@@ -154,13 +158,13 @@ module OM::XML::TermXpathGenerator
|
|
154
158
|
k = pointer
|
155
159
|
index = nil
|
156
160
|
end
|
157
|
-
|
161
|
+
|
158
162
|
keys << k
|
159
|
-
|
160
|
-
term = terminology.retrieve_term(*keys)
|
163
|
+
|
164
|
+
term = terminology.retrieve_term(*keys)
|
161
165
|
# Return nil if there is no term to work with
|
162
166
|
return if term.nil?
|
163
|
-
|
167
|
+
|
164
168
|
# If we've encountered a NamedTermProxy, insert path sections corresponding to each entry in its proxy_pointer (rather than just the final term that it points to).
|
165
169
|
# TODO Looks like this only works if the last key is a NamedTermProxy, what if we cross proxies on the way there?
|
166
170
|
if term.kind_of? OM::XML::NamedTermProxy
|
@@ -183,20 +187,22 @@ module OM::XML::TermXpathGenerator
|
|
183
187
|
raise "There's a problem with the #{term.name} OM::XML::NamedTermProxy, whose proxy pointer is #{term.proxy_pointer}. The #{proxy_pointer} pointer is returning #{proxy_term.inspect}"
|
184
188
|
end
|
185
189
|
end
|
186
|
-
else
|
190
|
+
else
|
187
191
|
relative_path = term.xpath_relative
|
188
|
-
|
192
|
+
|
189
193
|
unless index.nil?
|
190
194
|
relative_path = add_node_index_predicate(relative_path, index)
|
191
195
|
end
|
192
196
|
end
|
193
|
-
|
194
|
-
|
195
|
-
|
197
|
+
|
198
|
+
if pointer_index > 0
|
199
|
+
relative_path = "/"+relative_path
|
200
|
+
end
|
201
|
+
xpath << relative_path
|
196
202
|
end
|
197
|
-
|
198
|
-
final_term = terminology.retrieve_term(*keys)
|
199
|
-
|
203
|
+
|
204
|
+
final_term = terminology.retrieve_term(*keys)
|
205
|
+
|
200
206
|
if query_constraints.kind_of?(Hash)
|
201
207
|
contains_functions = []
|
202
208
|
query_constraints.each_pair do |k,v|
|
@@ -207,20 +213,20 @@ module OM::XML::TermXpathGenerator
|
|
207
213
|
end
|
208
214
|
contains_functions << "contains(#{constraint_path}, \"#{v}\")"
|
209
215
|
end
|
210
|
-
|
216
|
+
|
211
217
|
xpath = add_predicate(xpath, delimited_list(contains_functions, " and ") )
|
212
218
|
end
|
213
|
-
|
214
|
-
xpath
|
219
|
+
|
220
|
+
return xpath
|
215
221
|
end
|
216
|
-
|
222
|
+
|
217
223
|
# @see OM::XML.delimited_list
|
218
224
|
def self.delimited_list(*args)
|
219
225
|
OM::XML.delimited_list(*args)
|
220
226
|
end
|
221
|
-
|
227
|
+
|
222
228
|
# Adds xpath xpath node index predicate to the end of your xpath query
|
223
|
-
# Example:
|
229
|
+
# Example:
|
224
230
|
# add_node_index_predicate("//oxns:titleInfo",0)
|
225
231
|
# => "//oxns:titleInfo[1]"
|
226
232
|
#
|
@@ -230,9 +236,9 @@ module OM::XML::TermXpathGenerator
|
|
230
236
|
modified_query = xpath_query.dup
|
231
237
|
modified_query << "[#{array_index_value + 1}]"
|
232
238
|
end
|
233
|
-
|
239
|
+
|
234
240
|
# Adds xpath:position() method call to the end of your xpath query
|
235
|
-
# Examples:
|
241
|
+
# Examples:
|
236
242
|
#
|
237
243
|
# add_position_predicate("//oxns:titleInfo",0)
|
238
244
|
# => "//oxns:titleInfo[position()=1]"
|
@@ -243,7 +249,7 @@ module OM::XML::TermXpathGenerator
|
|
243
249
|
position_function = "position()=#{array_index_value + 1}"
|
244
250
|
self.add_predicate(xpath_query, position_function)
|
245
251
|
end
|
246
|
-
|
252
|
+
|
247
253
|
def self.add_predicate(xpath_query, predicate)
|
248
254
|
modified_query = xpath_query.dup
|
249
255
|
# if xpath_query.include?("]")
|
@@ -252,7 +258,7 @@ module OM::XML::TermXpathGenerator
|
|
252
258
|
else
|
253
259
|
modified_query << "[#{predicate}]"
|
254
260
|
end
|
255
|
-
modified_query
|
261
|
+
return modified_query
|
256
262
|
end
|
257
263
|
|
258
264
|
end
|