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