lib/soaspec/exchange_handlers/rest_handler.rb in soaspec-0.0.79 vs lib/soaspec/exchange_handlers/rest_handler.rb in soaspec-0.0.80
- old
+ new
@@ -278,56 +278,72 @@
end
# Returns the value at the provided xpath
# @param [RestClient::Response] response
# @param [String] xpath
- # @return [String] Value inside element found through Xpath
- def xpath_value_for(response: nil, xpath: nil, attribute: nil)
+ # @return [Enumerable] Value inside element found through Xpath
+ def xpath_elements_for(response: nil, xpath: nil, attribute: nil)
raise ArgumentError unless response && xpath
raise "Can't perform XPATH if response is not XML" unless Interpreter.response_type_for(response) == :xml
- result =
- if Soaspec.strip_namespaces? && !xpath.include?(':')
- temp_doc = Nokogiri.parse response.body
- temp_doc.remove_namespaces!
- temp_doc.xpath(xpath).first
- else
- Nokogiri.parse(response.body).xpath(xpath).first
- end
- raise NoElementAtPath, "No value at Xpath '#{xpath}'" unless result
- return result.inner_text if attribute.nil?
- result.attributes[attribute].inner_text
+ xpath = "//*[@#{attribute}]" unless attribute.nil?
+ if xpath[0] != '/'
+ xpath = convert_to_pascal_case(xpath) if pascal_keys?
+ xpath = '//' + xpath
+ end
+ if Soaspec.strip_namespaces? && !xpath.include?(':')
+ temp_doc = Nokogiri.parse response.body
+ temp_doc.remove_namespaces!
+ temp_doc.xpath(xpath)
+ else
+ Nokogiri.parse(response.body).xpath(xpath)
+ end
end
+ # @return [Enumerable] List of values matching JSON path
+ def json_path_values_for(response, path, attribute: nil)
+ raise 'JSON does not support attributes' if attribute
+ if path[0] != '$'
+ path = convert_to_pascal_case(path) if pascal_keys?
+ path = '$..' + path
+ end
+ JsonPath.on(response.body, path)
+ end
+
# Based on a exchange, return the value at the provided xpath
# If the path does not begin with a '/', a '//' is added to it
# @param [Response] response
# @param [Object] path Xpath, JSONPath or other path identifying how to find element
# @param [String] attribute Generic attribute to find. Will override path
# @return [String] Value at Xpath
def value_from_path(response, path, attribute: nil)
path = path.to_s
-
case Interpreter.response_type_for(response)
when :xml
- path = "//*[@#{attribute}]" unless attribute.nil?
- if path[0] != '/'
- path = convert_to_pascal_case(path) if pascal_keys?
- path = '//' + path
- end
- xpath_value_for(response: response, xpath: path, attribute: attribute)
+ result = xpath_elements_for(response: response, xpath: path, attribute: attribute).first
+ raise NoElementAtPath, "No value at Xpath '#{path}'" unless result
+ return result.inner_text if attribute.nil?
+ return result.attributes[attribute].inner_text
when :json
- raise 'JSON does not support attributes' if attribute
- if path[0] != '$'
- path = convert_to_pascal_case(path) if pascal_keys?
- path = '$..' + path
- end
- matching_values = JsonPath.on(response.body, path)
+ matching_values = json_path_values_for(response, path, attribute: attribute)
raise NoElementAtPath, "Element in #{response.body} not found with path '#{path}'" if matching_values.empty?
matching_values.first
when :hash
response.dig(path.split('.')) # Use path as Hash dig expression separating params via '.' TODO: Unit test
else
response.to_s[/path/] # Perform regular expression using path if not XML nor JSON TODO: Unit test
+ end
+ end
+
+ # @return [Enumerable] List of values returned from path
+ def values_from_path(response, path, attribute: nil)
+ path = path.to_s
+ case Interpreter.response_type_for(response)
+ when :xml
+ xpath_elements_for(response: response, xpath: path, attribute: attribute).map(&:inner_text)
+ when :json
+ json_path_values_for(response, path, attribute: attribute)
+ else
+ raise "Unable to interpret type of #{response.body}"
end
end
# Convenience methods for once off usage of a REST request
class << self
\ No newline at end of file