lib/savon/soap/xml.rb in savon-0.9.5 vs lib/savon/soap/xml.rb in savon-0.9.6

- old
+ new

@@ -73,10 +73,37 @@ key = env_namespace.blank? ? "xmlns" : "xmlns:#{env_namespace}" { key => SOAP::Namespace[version] } end end + def namespace_by_uri(uri) + namespaces.each do |candidate_identifier, candidate_uri| + return candidate_identifier.gsub(/^xmlns:/, '') if candidate_uri == uri + end + nil + end + + def used_namespaces + @used_namespaces ||= {} + end + + def use_namespace(path, uri) + @internal_namespace_count ||= 0 + + unless identifier = namespace_by_uri(uri) + identifier = "ins#{@internal_namespace_count}" + namespaces["xmlns:#{identifier}"] = uri + @internal_namespace_count += 1 + end + + used_namespaces[path] = identifier + end + + def types + @types ||= {} + end + # Sets the default namespace identifier. attr_writer :namespace_identifier # Returns the default namespace identifier. def namespace_identifier @@ -112,11 +139,16 @@ # Returns the XML for a SOAP request. def to_xml @xml ||= tag(builder, :Envelope, complete_namespaces) do |xml| tag(xml, :Header) { xml << header_for_xml } unless header_for_xml.empty? - input.nil? ? tag(xml, :Body) : tag(xml, :Body) { xml.tag!(*input) { xml << body_to_xml } } + + if input.nil? + tag(xml, :Body) + else + tag(xml, :Body) { xml.tag!(*add_namespace_to_input) { xml << body_to_xml } } + end end end private @@ -152,10 +184,34 @@ end # Returns the SOAP body as an XML String. def body_to_xml return body.to_s unless body.kind_of? Hash - Gyoku.xml body, :element_form_default => element_form_default, :namespace => namespace_identifier + Gyoku.xml add_namespaces_to_body(body), :element_form_default => element_form_default, :namespace => namespace_identifier + end + + def add_namespaces_to_body(hash, path = [input[1].to_s]) + return unless hash + return hash.to_s unless hash.kind_of? Hash + + hash.inject({}) do |newhash, (key, value)| + camelcased_key = Gyoku::XMLKey.create(key) + newpath = path + [camelcased_key] + + if used_namespaces[newpath] + newhash.merge( + "#{used_namespaces[newpath]}:#{camelcased_key}" => + add_namespaces_to_body(value, types[newpath] ? [types[newpath]] : newpath) + ) + else + newhash.merge(key => value) + end + end + end + + def add_namespace_to_input + return input.compact unless used_namespaces[[input[1].to_s]] + [used_namespaces[[input[1].to_s]], input[1], input[2]] end end end end