require "savon/soap/xml"
require "savon/soap/fault"
require "savon/soap/invalid_response_error"
require "savon/http/error"
module Savon
module SOAP
# = Savon::SOAP::Response
#
# Represents the SOAP response and contains the HTTP response.
class Response
# Expects an HTTPI::Response and handles errors.
def initialize(config, response)
self.config = config
self.http = response
raise_errors if config.raise_errors
end
attr_accessor :http, :config
# Returns whether the request was successful.
def success?
!soap_fault? && !http_error?
end
# Returns whether there was a SOAP fault.
def soap_fault?
soap_fault.present?
end
# Returns the Savon::SOAP::Fault.
def soap_fault
@soap_fault ||= Fault.new http
end
# Returns whether there was an HTTP error.
def http_error?
http_error.present?
end
# Returns the Savon::HTTP::Error.
def http_error
@http_error ||= HTTP::Error.new http
end
# Shortcut accessor for the SOAP response body Hash.
def [](key)
body[key]
end
# Returns the SOAP response header as a Hash.
def header
if !hash.has_key? :envelope
raise Savon::SOAP::InvalidResponseError, "Unable to parse response body '#{to_xml}'"
end
hash[:envelope][:header]
end
# Returns the SOAP response body as a Hash.
def body
if !hash.has_key? :envelope
raise Savon::SOAP::InvalidResponseError, "Unable to parse response body '#{to_xml}'"
end
hash[:envelope][:body]
end
alias to_hash body
# Traverses the SOAP response body Hash for a given +path+ of Hash keys and returns
# the value as an Array. Defaults to return an empty Array in case the path does not
# exist or returns nil.
def to_array(*path)
result = path.inject body do |memo, key|
return [] unless memo[key]
memo[key]
end
result.kind_of?(Array) ? result.compact : [result].compact
end
# Returns the complete SOAP response XML without normalization.
def hash
@hash ||= Nori.parse(to_xml)
end
# Returns the SOAP response XML.
def to_xml
http.body
end
# Returns a Nokogiri::XML::Document for the SOAP response XML.
def doc
@doc ||= Nokogiri::XML(to_xml)
end
# Returns an Array of Nokogiri::XML::Node objects retrieved with the given +path+.
# Automatically adds all of the document's namespaces unless a +namespaces+ hash is provided.
def xpath(path, namespaces = nil)
doc.xpath(path, namespaces || xml_namespaces)
end
private
def raise_errors
raise soap_fault if soap_fault?
raise http_error if http_error?
end
def xml_namespaces
@xml_namespaces ||= doc.collect_namespaces
end
end
end
end