Dear list,
I've been using R for a while, but am new to web services. I'm a
relatively
novice programmer; advance apologies for incorrect terminology.
I'm trying to send queries and get results back from a SOAP server, using
the SSOAP package. My code contains sensitive API keys and URLs, and
unfortunately I'm unable to share it uncensored. I have not been able to
reproduce the errors with servers used in the SSOAP documentation.
Apologies in advance for not being able to provide reproducible examples.
I am using SSOAP v 0.9-1 (R version 2.15.0 (2012-03-30))
My problem:
The structure of the statement I'm trying to generate and send is:
POST XXXXX
Host: XXXXX
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="
http://www.w3.org/2001/XMLSchema" xmlns:soap12="
http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<FunctionName xmlns="http://tempuri.org/">
<client>XXXXX</client>
<apiKey>XXXXX</apiKey>
<batchMessage>
<BatchMessage Message="XXXXX"
MessageID="XXXXX"
LocaleCode="XXXXX" MessageType="XXXXX" />
<BatchMessage Message="XXXXX"
MessageID="XXXXX"
LocaleCode="XXXXX" MessageType="XXXXX" />
</batchMessage>
</FunctionName>
</soap12:Body>
</soap12:Envelope>
The R code I'm using to generate and send such a statement (albeit with one
row in batchMessage) and get a response is:
library(SSOAP)
library(XML)
library(RCurl)
# download the file needed for authentication
download.file(url="http://curl.haxx.se/ca/cacert.pem",
destfile="cacert.pem")
# set the curl options
curl <- getCurlHandle()
options(RCurlOptions = list(capath = system.file("CurlSSL",
"cacert.pem",
package = "RCurl"),
ssl.verifypeer = FALSE))
curlSetOpt(.opts = list(proxy = 'proxyserver:port'), curl =
curl)
wsdl <- getURL("XXXXXX.asmx?wsdl",
ssl.verifypeer = FALSE)
doc <- xmlInternalTreeParse(wsdl)
def <- processWSDL(doc)
ff <- genSOAPClientInterface(def = def)
# Create the BatchMessage Array above
bm <- new("BatchMessage",
Message = "XXXX",
MessageID = "XXXX",
LocaleCode = "XXXX",
MessageType = "XXXX"
)
abm <- new("ArrayOfBatchMessage", list(bm))
# An object of combined paramters
cab <- new("client.apiKey.batchMessage",
client = "XXXXX",
apiKey = "XXXXX",
batchMessage = abm
)
ff@functions$FunctionName(parameters = cab)
# Call the WSDLGeneratedSOAPFunction with the above parameters
ff@functions$FunctionName(parameters = cab)
WSDLGeneratedSOAPFunction (here 'FunctionName') call returns a correctly
structured result from the server, with a note in it's exception slot about
an invalid parameter. Others using Java have found the same parameters to
be valid. The call generates the following warning:
Warning message:
In toSOAP(x, con = newXMLNode(type@elType@name, parent = con), type
= type@elType, :
Converting value to primitive SOAP type results in vector with
more than one element. Ignoring remainder.
The parameter arguments are quite complex, and require single value string
parameters (client, and apiKey), and an array/list of strings
(batchMessage), combined in one object, used as the parameters in the
function call (abm, of class "client.apiKey.batchMessage"). This
object is
(as I understand it) of the correct class, and parameters are in the
appropriate slots.
I get the impression from the message above that this complicated parameter
structure may have been simplified, problematically, at some point.
Does this seem like a reasonable diagnosis?
Can anyone see how I might work around this?
ff@functions$FunctionName itself looks like this:
An object of class "WSDLGeneratedSOAPFunction"
function (parameters = list(...), ..., server = .defaultServer,
.convert = .operation@returnValue, .opts = list(), nameSpaces
"1.2",
.soapHeader = NULL)
{
.SOAP(server, .operation@name, parameters = as(parameters,
"client.apiKey.batchMessage"), action =
.operation@action,
xmlns = .operation@namespace, .types = .operation@parameters
,
.convert = .convert, .header = .header, .opts = .opts,
.literal = TRUE, nameSpaces = nameSpaces,
.elementFormQualified = TRUE,
.returnNodeName = "GetTagsResponse", .soapHeader
.soapHeader)
}
More general/useful questions:
1. Is there a function which would allow me to see the SOAP query which I'm
sending, in raw text form, without sending it?
As I know the desired structure of the statement, but can't 'see'
what I'm
sending from the R functions generated from SSOAP, I'm having trouble
pin-pointing where I'm going wrong. toSOAP does not appear to work for me
in this case.
2. Is it possible to send a predefined 'raw' text SOAP statement to a
server, without this being compiled from various R objects (apart from
perhaps, one long character string of pre-defined SOAP)? If so, could I
still make use of the XML parsing and WSDL interpreting capabilities of the
SSOAP package to help me make sense of the result?
Apologies for the code dump, and unreproducible examples. And thanks to DTL
for the package and epic amounts of other excellent work!
BR
[[alternative HTML version deleted]]