我正在调查SUDS作为python的SOAP客户端。我想检查指定服务中可用的方法,以及指定方法所需的类型。
目的是生成用户界面,允许用户选择方法,然后以动态生成的形式填写值。
我可以获得有关特定方法的一些信息,但我不确定如何解析它:
client = Client(url)
method = client.sd.service.methods['MyMethod']
我无法 programmaticaly 找出我需要创建哪种对象类型才能调用服务
obj = client.factory.create('?')
res = client.service.MyMethod(obj, soapheaders=authen)
有没有人有一些示例代码?
答案 0 :(得分:27)
好的,所以SUDS确实有点神奇。
suds.client.Client
是从WSDL文件构建的:
client = suds.client.Client("http://mssoapinterop.org/asmx/simple.asmx?WSDL")
下载WSDL并在client.wsdl
中创建定义。当你通过client.service.<method>
调用一个使用SUDS的方法时,它实际上在幕后针对该解释的WSDL执行了大量的递归解析魔法。要发现方法的参数和类型,您需要内省此对象。
例如:
for method in client.wsdl.services[0].ports[0].methods.values():
print '%s(%s)' % (method.name, ', '.join('%s: %s' % (part.type, part.name) for part in method.soap.input.body.parts))
这应该打印如下:
echoInteger((u'int', http://www.w3.org/2001/XMLSchema): inputInteger)
echoFloatArray((u'ArrayOfFloat', http://soapinterop.org/): inputFloatArray)
echoVoid()
echoDecimal((u'decimal', http://www.w3.org/2001/XMLSchema): inputDecimal)
echoStructArray((u'ArrayOfSOAPStruct', http://soapinterop.org/xsd): inputStructArray)
echoIntegerArray((u'ArrayOfInt', http://soapinterop.org/): inputIntegerArray)
echoBase64((u'base64Binary', http://www.w3.org/2001/XMLSchema): inputBase64)
echoHexBinary((u'hexBinary', http://www.w3.org/2001/XMLSchema): inputHexBinary)
echoBoolean((u'boolean', http://www.w3.org/2001/XMLSchema): inputBoolean)
echoStringArray((u'ArrayOfString', http://soapinterop.org/): inputStringArray)
echoStruct((u'SOAPStruct', http://soapinterop.org/xsd): inputStruct)
echoDate((u'dateTime', http://www.w3.org/2001/XMLSchema): inputDate)
echoFloat((u'float', http://www.w3.org/2001/XMLSchema): inputFloat)
echoString((u'string', http://www.w3.org/2001/XMLSchema): inputString)
因此,部件类型元组的第一个元素可能就是你所追求的:
>>> client.factory.create(u'ArrayOfInt')
(ArrayOfInt){
_arrayType = ""
_offset = ""
_id = ""
_href = ""
_arrayType = ""
}
更新
对于天气服务,“参数”似乎是element
而不是type
的一部分:
>>> client = suds.client.Client('http://www.webservicex.net/WeatherForecast.asmx?WSDL')
>>> client.wsdl.services[0].ports[0].methods.values()[0].soap.input.body.parts[0].element
(u'GetWeatherByZipCode', http://www.webservicex.net)
>>> client.factory.create(u'GetWeatherByZipCode')
(GetWeatherByZipCode){
ZipCode = None
}
但这对于方法调用的参数(la client.service.GetWeatherByZipCode("12345")
是神奇的.IIRC这是SOAP RPC绑定样式吗?我认为这里有足够的信息可以帮助你入门。提示:Python命令行界面是你的朋友!
答案 1 :(得分:19)
根据suds
documentation,您可以使用service
检查__str()__
对象。因此,以下内容列出了方法和复杂类型:
from suds.client import Client;
url = 'http://www.webservicex.net/WeatherForecast.asmx?WSDL'
client = Client(url)
temp = str(client);
上面的代码产生以下结果(temp
的内容):
Suds ( https://fedorahosted.org/suds/ ) version: 0.3.4 (beta) build: R418-20081208
Service ( WeatherForecast ) tns="http://www.webservicex.net"
Prefixes (1)
ns0 = "http://www.webservicex.net"
Ports (2):
(WeatherForecastSoap)
Methods (2):
GetWeatherByPlaceName(xs:string PlaceName, )
GetWeatherByZipCode(xs:string ZipCode, )
Types (3):
ArrayOfWeatherData
WeatherData
WeatherForecasts
(WeatherForecastSoap12)
Methods (2):
GetWeatherByPlaceName(xs:string PlaceName, )
GetWeatherByZipCode(xs:string ZipCode, )
Types (3):
ArrayOfWeatherData
WeatherData
WeatherForecasts
这将更容易解析。此外,还列出了每个方法及其参数及其类型。您可能甚至可以使用正则表达式来提取所需的信息。
答案 2 :(得分:8)
这是我根据上述信息编写的快速脚本,列出了WSDL上可用的输入方法suds报告。传入WSDL URL。适用于我目前正在进行的项目,我无法保证为您服务。
import suds
def list_all(url):
client = suds.client.Client(url)
for service in client.wsdl.services:
for port in service.ports:
methods = port.methods.values()
for method in methods:
print(method.name)
for part in method.soap.input.body.parts:
part_type = part.type
if(not part_type):
part_type = part.element[0]
print(' ' + str(part.name) + ': ' + str(part_type))
o = client.factory.create(part_type)
print(' ' + str(o))
答案 3 :(得分:3)
您可以访问suds的ServiceDefinition对象。这是一个快速的样本:
from suds.client import Client
c = Client('http://some/wsdl/link')
types = c.sd[0].types
现在,如果你想知道一个类型的前缀名称,它也很容易:
c.sd[0].xlate(c.sd[0].types[0][0])
这种双括号表示法是因为类型是一个列表(因此是第一个[0]),然后在此列表中的每个项目中可能有两个项目。然而,suds的__unicode__
的内部实现正是这样做的(即仅采用列表中的第一项):
s.append('Types (%d):' % len(self.types))
for t in self.types:
s.append(indent(4))
s.append(self.xlate(t[0]))
快乐的编码;)
答案 4 :(得分:0)
创建WSDL方法对象后,您可以从__metadata__
获取有关它的信息,包括它的参数列表&#39;名。
根据参数的名称,您可以在创建的方法中访问它的实际实例。该实例还在__metadata__
中包含了该信息,您可以在其中获取其类型名称
# creating method object
method = client.factory.create('YourMethod')
# getting list of arguments' names
arg_names = method.__metadata__.ordering
# getting types of those arguments
types = [method.__getitem__(arg).__metadata__.sxtype.name for arg in arg_names]
免责声明:这仅适用于复杂的WSDL类型。简单类型(如字符串和数字)默认为无
答案 5 :(得分:0)
from suds.client import Client
url = 'http://localhost:1234/sami/2009/08/reporting?wsdl'
client = Client(url)
functions = [m for m in client.wsdl.services[0].ports[0].methods]
count = 0
for function_name in functions:
print (function_name)
count+=1
print ("\nNumber of services exposed : " ,count)
答案 6 :(得分:0)
我需要一个对对象使用肥皂水的示例。 在这里找到答案的旁边,我发现了一个很好的article 进一步回答了我的问题。
这是一个简短的摘要:
首先,打印客户端以查看其内容概述。
from suds.client import Client client =
Client("https://wsvc.cdiscount.com/MarketplaceAPIService.svc?wsdl")
print client
然后,创建一个类型的实例(使用它的名称,包括它的前缀ns *。)并打印它,以查看其成员数据。
HeaderMessage = client.factory.create('ns0:HeaderMessage')
print HeaderMessage
要填充对象的数据成员,请为它们分配标量成员的标量值或字典给对象成员。
HeaderMessage.Context = {
"CatalogID": "XXXXX"
"CustomerID": 'XXXXX'
"SiteID": 123
}
其类型名称以ArrayOf开头的成员期望在该类型名称的其余部分中提及的该类型的对象的列表。
ArrayOfDomainRights = client.factory.create('ns0:ArrayOfDomainRights')
ArrayOfDomainRights.DomainRights = [XXXXXXXXXXXXX, XXXXXXXXXXXX]
答案 7 :(得分:0)
我需要一个对对象使用肥皂水的示例。 在这里找到答案的旁边,我发现了一个很好的article 进一步回答了我的问题。
这是一个简短的摘要:
首先,打印客户端以查看其内容概述。
from suds.client import Client client =
Client("https://wsvc.cdiscount.com/MarketplaceAPIService.svc?wsdl")
print client
然后,创建一个类型的实例(使用它的名称,包括它的前缀ns *。)并打印它,以查看其成员数据。
HeaderMessage = client.factory.create('ns0:HeaderMessage')
print HeaderMessage
要填充对象的数据成员,请为它们分配标量成员的标量值或字典给对象成员。
HeaderMessage.Context = {
"CatalogID": "XXXXX"
"CustomerID": 'XXXXX'
"SiteID": 123
}
其类型名称以ArrayOf开头的成员期望在该类型名称的其余部分中提及的该类型的对象的列表。
ArrayOfDomainRights = client.factory.create('ns0:ArrayOfDomainRights')
ArrayOfDomainRights.DomainRights = [XXXXXXXXXXXXX, XXXXXXXXXXXX]