23

我正在调查 SUDS 作为 python 的 SOAP 客户端。我想检查指定服务中可用的方法,以及指定方法所需的类型。

目的是生成用户界面,允许用户选择方法,然后在动态生成的表单中填写值。

我可以获得有关特定方法的一些信息,但不确定如何解析它:

client = Client(url)
method = client.sd.service.methods['MyMethod']

我无法以编程 方式确定需要创建什么对象类型才能调用服务

obj = client.factory.create('?')

res = client.service.MyMethod(obj, soapheaders=authen)

有人有一些示例代码吗?

4

8 回答 8

29

好的,所以 SUDS 确实很神奇。

A suds.client.Client, 是从 WSDL 文件构建的:

client = suds.client.Client("http://mssoapinterop.org/asmx/simple.asmx?WSDL")

它下载 WSDL 并在client.wsdl. 当您通过使用 SUDS 调用方法时,client.service.<method>它实际上是在幕后针对该解释的 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 = ""
 }

更新:

对于 Weather 服务,“参数”似乎是一个elementnot a的一部分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
 }

但这对方法调用的参数很神奇(a la client.service.GetWeatherByZipCode("12345"). IIRC,这是 SOAP RPC 绑定样式?我认为这里有足够的信息可以帮助您入门。提示:Python 命令行界面是您的朋友!

于 2009-12-07T06:12:25.547 回答
20

根据suds 文档,您可以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

这将更容易解析。还列出了每个方法及其参数及其类型。您甚至可以只使用正则表达式来提取您需要的信息。

于 2009-12-03T20:46:55.580 回答
9

这是我根据上述信息编写的快速脚本,用于列出 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))
于 2013-05-17T19:25:56.857 回答
4

您可以访问 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]))

快乐编码;)

于 2013-07-24T09:43:44.203 回答
1

一旦您创建了 WSDL 方法对象,您就可以从它获取有关它的信息__metadata__,包括它的参数名称列表。

给定参数的名称,您可以在创建的方法中访问它的实际实例。该实例还包含它的信息,在__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 类型。简单类型,如字符串和数字,默认为 None

于 2015-12-23T20:01:30.083 回答
1
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)
于 2016-11-23T10:42:42.387 回答
0

我需要一个将泡沫与对象一起使用的示例。除了在这里找到的答案之外,我还发现了一篇非常好的文章 ,可以进一步回答我的问题。

这是一个简短的总结:

首先,打印客户端以查看其内容的概述。

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

要填充对象的数据成员,可以将标量成员的标量值或 dict 分配给对象成员。

HeaderMessage.Context =  {
     "CatalogID": "XXXXX"
     "CustomerID": 'XXXXX'
     "SiteID": 123
 }

类型名称以 ArrayOf 开头的成员需要一个类型名称其余部分中提到的类型的对象列表。

ArrayOfDomainRights = client.factory.create('ns0:ArrayOfDomainRights')
ArrayOfDomainRights.DomainRights = [XXXXXXXXXXXXX, XXXXXXXXXXXX]
于 2020-05-13T06:07:05.980 回答
0

我需要一个将泡沫与对象一起使用的示例。除了在这里找到的答案之外,我还发现了一篇非常好的文章 ,可以进一步回答我的问题。

这是一个简短的总结:

首先,打印客户端以查看其内容的概述。

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

要填充对象的数据成员,可以将标量成员的标量值或 dict 分配给对象成员。

HeaderMessage.Context =  {
     "CatalogID": "XXXXX"
     "CustomerID": 'XXXXX'
     "SiteID": 123
 }

类型名称以 ArrayOf 开头的成员需要一个类型名称其余部分中提到的类型的对象列表。

ArrayOfDomainRights = client.factory.create('ns0:ArrayOfDomainRights')
ArrayOfDomainRights.DomainRights = [XXXXXXXXXXXXX, XXXXXXXXXXXX]
于 2020-05-16T20:04:55.567 回答