问题
I am trying to hit a SOAP Service from Ruby on Rails - from SOAP UI I can hit it fine and the request XML is as below:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/" xmlns:mun="http://schemas.datacontract.org/2004/07/MyExternalService.Map" xmlns:mun1="http://schemas.datacontract.org/2004/07/MyExternalService.Common.Map">
<soapenv:Header/>
<soapenv:Body>
<tem:GetInformationsForCoordinates>
<!--Optional:-->
<tem:coordReq>
<!--Optional:-->
<mun:Coordinates>
<!--Zero or more repetitions:-->
<mun:Coordinate>
<!--Optional:-->
<mun:Id>1</mun:Id>
<!--Optional:-->
<mun:QualityIndex>90</mun:QualityIndex>
<!--Optional:-->
<mun:X>-110.5322</mun:X>
<!--Optional:-->
<mun:Y>35.2108</mun:Y>
</mun:Coordinate>
</mun:Coordinates>
</tem:coordReq>
<!--Optional:-->
<tem:analysisTypes>
<!--Zero or more repetitions:-->
<mun:AnalysisType>Additional</mun:AnalysisType>
</tem:analysisTypes>
</tem:GetInformationsForCoordinates>
</soapenv:Body>
</soapenv:Envelope>
If I copy that exact XML into a Ruby string with request = %q(XML STRING)
into savon and use the method and then in Savon call the following:
response = client.call(:get_info, xml: request)
It works as expected and I get my response - however in reality I want to be just passing the parameters to Savon. So far I have tried the following:
coordinate = { Id: '1', X: -110.5322, Y: 35.2108, QualityIndex: 90 }
coordinates = {Coordinates: [coordinate] }
coordinateReq = {coordReq: {coordinates: coordinates} }
response = client.call(:get_informations_for_coordinates, message: coordinateReq)
This fails and if I look at the XML I am sending it is below:
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tns="http://tempuri.org/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<env:Body>
<tns:GetInformationsForCoordinates>
<coordReq>
<coordinates>
<coordinates>
<Id>1</Id>
<X>-110.5322</X>
<Y>35.2108</Y>
<QualityIndex>90</QualityIndex>
</coordinates>
</coordinates>
</coordReq>
</tns:GetInformationsForCoordinates>
</env:Body>
</env:Envelope>
In comparison to what is sent from SOAP UI I am missing the xmlns:mum namespace - is there anyway I can add it my request so that it is added to each parameter i.e. X, Y QualityIndex - also the tem which is similar to tns in my Savon call is added to the coordReq in SOAPUI but not in my Savon call - is there anyway I can add it?
Also I am having some difficulty in working out how to Build the analysisTypes and AnalysisType part of my request?
回答1:
From the documentation:
Namespaces
If you don’t pass a namespace to
Savon::Client#request
, Savon will register the target namespace (“xmlns:wsdl”
) for you. If you did pass a namespace, Savon will use it instead of the default one. For example:client.request :v1, :get_user <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:v1="http://v1.example.com"> <env:Body> <v1:GetUser> </env:Body> </env:Envelope>
You can always set namespaces or overwrite namespaces set by Savon. Namespaces are stored as a simple Hash.
# setting a new namespace soap.namespaces["xmlns:g2"] = "http://g2.example.com" # overwriting the "xmlns:wsdl" namespace soap.namespaces["xmlns:wsdl"] = "http://ns.example.com"
Apparently, for Savon 2, setting multiple namespaces is impossible:
I found that is not possible (for now) to set multiple namespaces on version 2 of Savon.
For now i migrate my application on Savon version 1 and it worked =)
回答2:
To use multiple namespaces you put the following type of code in your client definition
...
:namespaces => {
"xmlns:v2" => "http://v2.example.com",
"xmlns:v1" => "http://v1.example.com" },
...
来源:https://stackoverflow.com/questions/22606875/trying-to-build-soap-request-with-savon