soap reponse in wsdl does not match description
Hi, I have noticed that for functions that return complex types, the soap wsdl contents does not match the description or what I am expecting. All is fine in the soap11 description though. This is with Ladon 0.7.5 on red hat linux. eg:
Here is an example I added to calculator.py:
class Response1(
name = str
a = float
b = float
c = float
@ladonize(
def func1(self,s):
rv = Response1()
rv.name = "hello"
rv.a = 1.2
rv.b = 1.3
rv.c = 1.5
return rv
Here is description:
func1 ( string s )
None
Parameters
s: string
Return value
Response1
Here is soap wsdl:
<message name="func1">
<part name="s" type="xsd:string"/>
</message>
<message name="func1Resp
<part name="a" type="xsd:
<part name="b" type="xsd:
<part name="c" type="xsd:
<part name="name" type="xsd:string"/>
</message>
Here is soap11 wsdl:
<wsdl:message name="func1">
<wsdl:part name="s" type="xsd:string"/>
</wsdl:message>
<wsdl:message name="func1Resp
<wsdl:part name="result" type="ns1:
ie, it appears the soap wsdl declares that the method returns individual values rather than the 'response1' type as expected.
Thanks for any advice you can give,
Gary
Question information
- Language:
- English Edit question
- Status:
- Expired
- For:
- ladon Edit question
- Assignee:
- No assignee Edit question
- Last query:
- Last reply:
Revision history for this message
|
#1 |
This question was expired because it remained in the 'Open' state without activity for the last 15 days.
Revision history for this message
|
#3 |
I've also observed this. I don't know how suds manages to make one object out of the response, but C# SOAP client doesn't. Resulting a method signature with out parameters, see below:
public decimal func1(out decimal b, out decimal c, out string name, string s)
Revision history for this message
|
#4 |
I have developed a new interface which solves the problem - this seems to work with java-ws clients and .net clients I have tested it with. I called it soapws:
# -*- coding: utf-8 -*-
from ladon.interface
from ladon.interfaces import expose
from ladon.compat import PORTABLE_
from xml.sax.handler import ContentHandler,
from xml.sax import make_parser
from xml.sax.xmlreader import InputSource
import sys,re,traceback
import logging
LOG = logging.
rx_nil_attr = re.compile(
class SOAPWSServiceDe
xsd_type_map = type_to_xsd
_content_type = 'text/xml'
def generate(
"""
Generate WSDL file for SOAPWSInterface
"""
type_dict = typemanager.
type_order = typemanager.
def map_type(typ):
if typ in SOAPWSServiceDe
return SOAPWSServiceDe
else:
return typ.__name__
def map_type2(typ):
if typ in SOAPWSServiceDe
if tmpval == 'decimal':
tmpval = 'float'
return tmpval
import xml.dom.minidom as md
doc = md.Document()
# SERVICE DEFINITION
# Create the definitions element for the service
definitions = doc.createEleme
definitions.
definitions.
definitions.
definitions.
definitions.
definitions.
definitions.
definitions.
definitions.
definitions.
definitions.
doc.appendChi
# TYPES
# The types element
types = doc.createEleme
definitions.
# Service schema for types required by the target namespace we defined in the definition element
schema = doc.createEleme
schema.
schema.
schema.
schema.
types.
# Define types, the type_order variable holds all that need to be defined and in the
# correct order.
for m in methodlist:
basictype = doc.createEleme
basictype.
basictype.
schema.
basictypeR = doc.createEleme
schema.
for m in methodlist:
complextype = doc.createEleme
for arg in m.args():
v = arg['type']
complextype = doc.createEleme
else:
element.
#special types
for typ in type_order:
if not(isinstance(typ, list)):
complextype = doc.createEleme
complextype
schema.
sequence = doc.createEleme
complextype
for k,v,props in typ['attributes']:
element = doc.createEleme
element.
element.
element.
if props.get(
element.
element.
if isinstance(v, list):
inner = v[0]
#
if inner in type_dict:
#
element.
element.
element.
#
if not(isinstance(v, list)):
if v in type_dict:
else:
sequence.
#messages
for m in methodlist:
message = doc.createEleme
message.
definitions.
part = doc.createEleme
part.
part.
message.
message = doc.createEleme
message.
definitions.
part2 = doc.createEleme
part2.
part2.
message.
porttype = doc.createEleme
porttype.
definitions.
#operations
for m in methodlist:
operation = doc.createEleme
operation.
porttype.
if m.__doc__:
documentation = doc.createEleme
documentati
operation.
input_tag = doc.createEleme
input_
input_
operation.
output_tag = doc.createEleme
output_
output_
operation.
#binding
binding = doc.createEleme
binding.
binding.
transport = doc.createEleme
transport.
transport.
binding.
definitions.
for m in methodlist:
operation = doc.createEleme
operation.
binding.
soapaction = doc.createEleme
soapaction.
operation.
m._multipart
input_tag = doc.createEleme
body_parent = input_tag
if m._multipart_
multipart_
mime_body_part = doc.createEleme
body_parent = mime_body_part
mime_
mime_content = doc.createEleme
mime_
input_
multipart_
multipart_
mime_
input_soapbody = doc.createEleme
input_
body_
operation.
output_tag = doc.createEleme
body_parent = output_tag
if m._multipart_
multipart_
mime_body_part = doc.createEleme
body_parent = mime_body_part
mime_
mime_content = doc.createEleme
mime_
output_
multipart_
multipart_
mime_
output_soapbody = doc.createEleme
output_
body_
operation.
service = doc.createEleme
service.
documentation = doc.createEleme
documentation
service.
port = doc.createEleme
port.
port.
service.
address = doc.createEleme
address.
port.
definitions.
if sys.version_
return doc.toxml()
return doc.toxml(encoding)
def u(instring):
if sys.version_
return PORTABLE_
else:
return PORTABLE_
class ContainerSetRef
def __init_
self.c = c
self.refval = refval
def set(self,val):
self.
class SOAPWSRequestHa
def parse_request(
import xml.dom.minidom as md
self.sinfo = sinfo
doc = md.parseString(
soap_envelope = doc.getElements
soap_body = doc.getElements
EN = soap_body.
soap_method = (node for node in soap_body.
if node.nodeType == EN).next()
soap_methodprefix = soap_method.prefix
try:
m = re.match(
except:
m = None
servicenumber = None
if m: servicenumber = int(m.groups()[0])
self.
soap_args = {'methodname': self.soap_
#for typ in self.sinfo.
# if not(isinstance(typ, list)):
# self.appendToMy
TN = soap_method.
soap_args['args'] = self.getDictFor
#self.
return soap_args
def getDictForNode(
for n in node.childNodes:
if n.nodeType == n.ELEMENT_NODE and not n.hasAttribute(
elif n.nodeType=
elif n.nodeType=
return localDict
def isTagList(self, tagnm):
for typ in self.sinfo.
a=1
for m in self.sinfo.
#self.
#self.
for arg in m.args():
return True
#if isinstance(
# self.appendToMy
# return True
return False
def getListItems(self, node, parent):
for n in parent.childNodes:
if n.nodeName=
return tagList
def appendToMyLog(self, s):
class SOAPWSResponseH
_content_type = 'text/xml'
_stringify_
def dictToList(
#convert dictionary to list i fpossible, to ensure order in type_order is preserved to giev valid xml export format
retList=[]
for typ in self.sinfo.
if not(isinstance(typ, list)):
ld={}
for k,v,props in typ['attributes']:
ld[k]=None
if set(ld)==set(dd):
for k,v,props in typ['attributes']:
retList.
self.
return retList
for k,v in dd.items():
retList.
return retList
def value_to_
if isinstance(value, dict):
locList = self.dictToList
self.
for aname in locList:
#for attr_name,attr_val in value.items():
#self.
attr_name = aname
attr_val = value[aname]
xml_attr_name = attr_name.
for item in attr_val:
attr_elem = doc.createEleme
if is_toplevel:
parent.
self.
else:
attr_elem = doc.createEleme
if is_toplevel:
attr_elem = doc.createEleme
parent.
self.
else:
if is_toplevel:
value_parent = doc.createEleme
value_
parent.
else:
value_parent = parent
if isinstance(value, (list, tuple)):
if not len(value):
# Translate empty response arrays to SOAP Null (xsi:nil) value
value_
else:
for item in value:
item_element = doc.createEleme
self.
value_
else:
if value==None:
# Set xsi:nil to true if value is None
value_
else:
value_
def build_response(
import xml.dom.minidom as md
self.sinfo=sinfo
doc = md.Document()
envelope = doc.createEleme
envelope.
envelope.
envelope.
envelope.
envelope.
doc.appendChi
body_elem = doc.createEleme
body_
envelope.
method_elem = doc.createEleme
method_
#self.
if 'result' in res_dict['result']:
self.
else:
self.
body_
return doc.toxml(
def appendToMyLog(self, s):
class SOAPWSFaultHand
_content_type = 'text/xml'
_stringify_
soapfault_template = """<?xml version='1.0' encoding='UTF-8'?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://
xmlns:xsi="http://
xmlns:xsd="http://
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode xsi:type=
<faultstring xsi:type=
<detail>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-
def build_fault_
import xml.dom.minidom as md
if service_exc.detail:
detail = service_exc.detail
else:
detail = traceback.
d = md.parseString(
# Extract fault DOM elements
faultcode_elem = d.getElementsBy
faultstring_elem = d.getElementsBy
detail_elem = d.getElementsBy
# Set the fault values
faultcode_
faultstring_
detail_
# Return the SoapFault XML object
return d.toxml(
@expose
class SOAPWSInterface
def __init_
def_kw = {
'service_
'request_
'response_
'fault_handler': SOAPWSFaultHandler}
def_kw.update(kw)
BaseInterface
@staticmethod
def _interface_name():
return 'soapws'
@staticmethod
def _accept_
return pytype_
@staticmethod
def _accept_list():
return True
@staticmethod
def _accept_dict():
return False