class Hash

def find_soap_body

not be found.
Returns the values from the soap:Body element or an empty Hash in case the soap:Body tag could
def find_soap_body
  envelope = self[keys.first] || {}
  body_key = envelope.keys.find { |key| /.+:Body/ =~ key } rescue nil
  body_key ? envelope[body_key].map_soap_response : {}
end

def map_soap_response

Maps keys and values of a Hash created from SOAP response XML to more convenient Ruby Objects.
def map_soap_response
  inject({}) do |hash, (key, value)|
    value = case value
      when Hash   then value["xsi:nil"] ? nil : value.map_soap_response
      when Array  then value.map { |val| val.map_soap_response rescue val }
      when String then value.map_soap_response
    end
    hash.merge key.strip_namespace.snakecase.to_sym => value
  end
end

def order

Array does not match the Hash keys.
keys of this Hash if no :order! key could be found. Raises an ArgumentError in case the :order!
Deletes and returns an Array of keys stored under the :order! key. Defaults to return the actual
def order
  order = delete :order!
  order = keys unless order.kind_of? Array
  missing, spurious = keys - order, order - keys
  raise ArgumentError, "Missing elements in :order! #{missing.inspect}" unless missing.empty?
  raise ArgumentError, "Spurious elements in :order! #{spurious.inspect}" unless spurious.empty?
  order
end

def to_soap_xml

# => 'Eve'
{ :person => "Eve", :attributes! => { :person => { :id => 666 } } }.to_soap_xml

+:attributes!+ key.
If you need attributes, you could either go with an XML string or add another hash under the

==== XML attributes

# => "123Eve"
{ :name => "Eve", :id => 123, :order! => [:id, :name] }.to_soap_xml

through an additional array stored under the +:order!+ key.
options. The first is to specify your body as an XML string. The second is to specify the order
In case your service requires the tags to be in a specific order (parameterOrder), you have two

==== Fixed order of XML tags

By default, special characters in XML String values are escaped.

==== Escaped XML values


2012-06-11T10:42:21
true


}.to_soap_xml
}
"perform_at" => DateTime.new(2010, 11, 22, 11, 22, 33)
:perform_move => true,
{ :magic_request => {

An example:

* All other objects are expected to be converted to Strings using to_s
* TrueClass and FalseClass objects are converted to "true" and "false" Strings
* Objects responding to to_datetime (except Strings) are converted to xs:dateTime Strings
* DateTime values are converted to xs:dateTime Strings
* Hash keys specified as Strings are not converted and may contain namespaces
* Hash keys specified as Symbols are converted to lowerCamelCase Strings

==== Mapping

# => "123api"
{ :find_user => { :id => 123, "wsdl:Key" => "api" } }.to_soap_xml

Translates the Hash into SOAP request compatible XML.
def to_soap_xml
  xml = Builder::XmlMarkup.new
  attributes = delete(:attributes!) || {}
  order.each do |key|
    attrs = attributes[key] || {}
    value = self[key]
    escape_xml = key.to_s[-1, 1] != "!"
    key = key.to_soap_key
    case value
      when Array then xml << value.to_soap_xml(key, escape_xml, attrs)
      when Hash  then xml.tag!(key, attrs) { xml << value.to_soap_xml }
      else            xml.tag!(key, attrs) { xml << (escape_xml ? value.to_soap_value : value.to_soap_value!) }
    end
  end
  xml.target!
end