Module: OM::XML::TermXpathGenerator
- Defined in:
- lib/om/xml/term_xpath_generator.rb
Class Method Summary collapse
-
.add_node_index_predicate(xpath_query, array_index_value) ⇒ Object
Adds xpath xpath node index predicate to the end of your xpath query Example: add_node_index_predicate(“//oxns:titleInfo”,0) => “//oxns:titleInfo”.
-
.add_position_predicate(xpath_query, array_index_value) ⇒ Object
Adds xpath:position() method call to the end of your xpath query Examples: .
- .add_predicate(xpath_query, predicate) ⇒ Object
- .delimited_list(*args) ⇒ Object
-
.generate_absolute_xpath(term) ⇒ Object
Generate absolute xpath for a Term Absolute xpaths always begin with “//”.
- .generate_constrained_xpath(term) ⇒ Object
-
.generate_relative_xpath(term) ⇒ Object
Generate relative xpath for a term In most cases, the resulting xpath will be the Term’s path with the appropriate namespace appended to it.
-
.generate_xpath(term, type) ⇒ Object
Generate an xpath of the chosen
type
for the given Term. -
.generate_xpath_with_indexes(terminology, *pointers) ⇒ Object
Use the given
terminology
to generate an xpath with (optional) node indexes for each of the term pointers.
Class Method Details
.add_node_index_predicate(xpath_query, array_index_value) ⇒ Object
Adds xpath xpath node index predicate to the end of your xpath query Example: add_node_index_predicate(“//oxns:titleInfo”,0)
=> "//oxns:titleInfo[1]"
add_node_index_predicate(“//oxns:titleInfo”,0)
=> "//oxns:titleInfo[@lang=\"finnish\"][1]"
240 241 242 243 |
# File 'lib/om/xml/term_xpath_generator.rb', line 240 def self.add_node_index_predicate(xpath_query, array_index_value) modified_query = xpath_query.dup modified_query << "[#{array_index_value + 1}]" end |
.add_position_predicate(xpath_query, array_index_value) ⇒ Object
Adds xpath:position() method call to the end of your xpath query Examples:
add_position_predicate(“//oxns:titleInfo”,0)
> “//oxns:titleInfo”
add_position_predicate(“//oxns:titleInfo”,0)
> “//oxns:titleInfo[@lang="finnish" and position()=1]”
253 254 255 256 |
# File 'lib/om/xml/term_xpath_generator.rb', line 253 def self.add_position_predicate(xpath_query, array_index_value) position_function = "position()=#{array_index_value + 1}" self.add_predicate(xpath_query, position_function) end |
.add_predicate(xpath_query, predicate) ⇒ Object
258 259 260 261 262 263 264 265 266 267 |
# File 'lib/om/xml/term_xpath_generator.rb', line 258 def self.add_predicate(xpath_query, predicate) modified_query = xpath_query.dup # if xpath_query.include?("]") if xpath_query[xpath_query.length-1..xpath_query.length] == "]" modified_query.insert(xpath_query.rindex("]"), " and #{predicate}") else modified_query << "[#{predicate}]" end return modified_query end |
.delimited_list(*args) ⇒ Object
229 230 231 |
# File 'lib/om/xml/term_xpath_generator.rb', line 229 def self.delimited_list(*args) OM::XML.delimited_list(*args) end |
.generate_absolute_xpath(term) ⇒ Object
Generate absolute xpath for a Term Absolute xpaths always begin with “//”. They are generated by relying on the Term’s relative xpath and the absolute xpath of its parent node.
62 63 64 65 66 67 68 69 |
# File 'lib/om/xml/term_xpath_generator.rb', line 62 def self.generate_absolute_xpath(term) relative = generate_relative_xpath(term) if term.parent.nil? return "//#{relative}" else return term.parent.xpath_absolute + "/" + relative end end |
.generate_constrained_xpath(term) ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/om/xml/term_xpath_generator.rb', line 71 def self.generate_constrained_xpath(term) if term.namespace_prefix.nil? complete_prefix = "" else complete_prefix = term.namespace_prefix + ":" end absolute = generate_absolute_xpath(term) constraint_predicates = [] arguments_for_contains_function = [] if !term.default_content_path.nil? arguments_for_contains_function << "#{complete_prefix}#{term.default_content_path}" end # If no subelements have been specified to search within, set contains function to search within the current node if arguments_for_contains_function.empty? arguments_for_contains_function << "." end arguments_for_contains_function << "\":::constraint_value:::\"" contains_function = "contains(#{delimited_list(arguments_for_contains_function)})" template = add_predicate(absolute, contains_function) return template.gsub( /:::(.*?):::/ ) { '#{'+$1+'}' }.gsub('"', '\"') end |
.generate_relative_xpath(term) ⇒ Object
Generate relative xpath for a term In most cases, the resulting xpath will be the Term’s path with the appropriate namespace appended to it. If the Term specifies any attributes, Special Case: attribute Terms If the Term’s path is set to :attribute=>attr_name, the resulting xpath will points to a node attribute named attr_name ie. a path fo :attribute=>“lang” will result in a relative xpath of “@lang” Special Case: xpath functions If the Term’s path variable is text(), it will be treated as an xpath function (no namespace) and turned into “text()”
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/om/xml/term_xpath_generator.rb', line 13 def self.generate_relative_xpath(term) template = "" predicates = [] if term.namespace_prefix.nil? complete_prefix = "" else complete_prefix = term.namespace_prefix + ":" end if term.path.kind_of?(Hash) if term.path.has_key?(:attribute) base_path = "@"+term.path[:attribute] else raise "#{term.path} is an invalid path for an OM::XML::Term. You should provide either a string or {:attributes=>XXX}" end else if term.path == "text()" base_path = "#{term.path}[normalize-space(.)]" else unless term.namespace_prefix.nil? template << complete_prefix end base_path = term.path end end template << base_path unless term.attributes.nil? term.attributes.each_pair do |attr_name, attr_value| if attr_value == :none predicates << "not(@#{attr_name})" else predicates << "@#{attr_name}=\"#{attr_value}\"" end end end unless predicates.empty? template << "["+ delimited_list(predicates, " and ")+"]" end return template end |
.generate_xpath(term, type) ⇒ Object
Generate an xpath of the chosen type
for the given Term.
103 104 105 106 107 108 109 110 111 112 |
# File 'lib/om/xml/term_xpath_generator.rb', line 103 def self.generate_xpath(term, type) case type when :relative self.generate_relative_xpath(term) when :absolute self.generate_absolute_xpath(term) when :constrained self.generate_constrained_xpath(term) end end |
.generate_xpath_with_indexes(terminology, *pointers) ⇒ Object
Use the given terminology
to generate an xpath with (optional) node indexes for each of the term pointers. Ex. OM::XML::TermXpathGenerator.xpath_with_indexes(my_terminology, :conference=>0, :role=>1, :text )
will yield an xpath similar to this: '//oxns:name[@type="conference"][1]/oxns:role[2]/oxns:roleTerm[@type="text"]'
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/om/xml/term_xpath_generator.rb', line 119 def self.generate_xpath_with_indexes(terminology, *pointers) if pointers.first.nil? root_term = terminology.root_terms.first if root_term.nil? return "/" else return root_term.xpath end end query_constraints = nil if pointers.length > 1 && pointers.last.kind_of?(Hash) constraints = pointers.pop unless constraints.empty? query_constraints = constraints end end if pointers.length == 1 && pointers.first.instance_of?(String) return xpath_query = pointers.first end # if pointers.first.kind_of?(String) # return pointers.first # end keys = [] xpath = "//" pointers = OM.destringify(pointers) pointers.each_with_index do |pointer, pointer_index| if pointer.kind_of?(Hash) k = pointer.keys.first index = pointer[k] else k = pointer index = nil end keys << k term = terminology.retrieve_term(*keys) # Return nil if there is no term to work with return if term.nil? # 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). # TODO Looks like this only works if the last key is a NamedTermProxy, what if we cross proxies on the way there? if term.kind_of? OM::XML::NamedTermProxy OM.logger.warn "You attempted to call an index value of #{index} on the term \"#{k.inspect}\". However \"#{k.inspect}\" is a proxy so we are ignoring the index. See https://jira.duraspace.org/browse/HYDRA-643" if index && OM.logger current_location = term.parent.nil? ? term.terminology : term.parent relative_path = "" term.proxy_pointer.each_with_index do |proxy_pointer, proxy_pointer_index| begin proxy_term = current_location.retrieve_term(proxy_pointer) if proxy_term.nil? proxy_term = terminology.retrieve_term(proxy_pointer) end proxy_relative_path = proxy_term.xpath_relative if proxy_pointer_index > 0 proxy_relative_path = "/"+proxy_relative_path end relative_path << proxy_relative_path current_location = proxy_term rescue Exception => e 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}" end end else relative_path = term.xpath_relative unless index.nil? relative_path = add_node_index_predicate(relative_path, index) end end if pointer_index > 0 relative_path = "/"+relative_path end xpath << relative_path end final_term = terminology.retrieve_term(*keys) if query_constraints.kind_of?(Hash) contains_functions = [] query_constraints.each_pair do |k,v| if v.is_a?(Integer) || v == "0" || v.to_i != 0 # lookup sub element xpath = '(' + xpath + '/' + final_term.children[query_constraints.keys.first].xpath_relative + ")[#{v.to_i + 1}]" else if k.instance_of?(Symbol) constraint_path = final_term.children[k].xpath_relative else constraint_path = k end # match for text contains_functions << "#{constraint_path}[text()=\"#{v}\"]" xpath = add_predicate(xpath, delimited_list(contains_functions, " and ") ) end end end # return xpath end |