om 1.8.1 → 1.9.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|