如何使用wsdl2py生成的复杂类型从Python网络服务发送响应

1 投票
2 回答
2050 浏览
提问于 2025-04-17 02:19

我正在使用 ZSI 2.1,并且是从一个 WSDL 文件开始的,这个文件里定义了一个叫做 'postAppStatusResponse' 的消息,它的类型是 'appStatusResponse',具体定义如下:

<xsd:complexType name="appStatusResponse">
    <xsd:sequence>
        <xsd:element name="response" type="tns:webServiceResponse" minOccurs="1" maxOccurs="1" />
    </xsd:sequence>
</xsd:complexType>

而 "webServiceResponse" 的结构如下:

<xsd:complexType name="webServiceResponse">
    <xsd:sequence>
        <xsd:element name="responseCode" type="xsd:long"/>
        <xsd:element name="responseMessage" type="xsd:string"/>
        <xsd:element name="exceptionCode" type="xsd:long"/>
        <xsd:element name="exceptionMessage" type="xsd:string" nillable="true" />
        <xsd:element name="transactionIdentifier" type="xsd:long"/>
        <xsd:element name="traceIdentifier" type="xsd:string"/>
        <xsd:element name="transactionTimestamp" type="xsd:dateTime" nillable="true" />
    </xsd:sequence>
</xsd:complexType>

为了发送 postAppStatusResponse 消息,我显然需要用 webServiceResponse 和 appStatusResponse 这两个结构来填充它。然而,为 postAppStatusResponse 消息生成的类并没有提供支持这一点的内容。wsdl2py 生成的类型文件里包含了 appStatusResponse_Def 和 webServiceResponse_Def 类,但我一直搞不清楚怎么用它们来生成我需要的东西。

生成的 postAppStatusResponse 消息看起来是这样的:

_postAppStatusResponseTypecode = Struct(pname=("http://cig.jpmchase.net/20110218/card/acq/","postAppStatusResponse"), ofwhat=[ns0.appStatusResponse_Def(pname="postAppStatusResponse", aname="_postAppStatusResponse", typed=False, encoded=None, minOccurs=1, maxOccurs=1, nillable=True)], pyclass=None, encoded="http://cig.jpmchase.net/20110218/card/acq/")
class postAppStatusResponse:
    typecode = _postAppStatusResponseTypecode
    __metaclass__ = pyclass_type
    def __init__(self, **kw):
        """Keyword parameters:
        postAppStatusResponse -- part postAppStatusResponse
        """
        self._postAppStatusResponse =  kw.get("postAppStatusResponse")
postAppStatusResponse.typecode.pyclass = postAppStatusResponse

postAppStatusResponse 的 dir() 是:

['PostAppStatusResponse', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__metaclass__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_postAppStatusResponse', 'get_element_postAppStatusResponse', 'new_postAppStatusResponse', 'set_element_postAppStatusResponse', 'typecode']

而 postAppStatusResponse._postAppStatusResponse 的 dir() 是:

['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']

我使用 "wsdl2py --complexType" 生成了这些文件,并且能够顺利使用里面的 "get_element_..." 函数来提取请求消息的数据。我也写过其他 ZSI 网络服务,返回的消息比较简单,也没有遇到问题。但是这个... 我尝试了很多不同的方法来发送这个消息,但都没有找到有效的办法。

难道 ZSI 的存在就是为了让这些事情变得简单吗?有没有人能帮我解决我在这里遗漏的部分?(我尽量省略了长 XML 文件和代码列表中的多余数据,但当然可以根据需要提供。)

2 个回答

0

我想我明白了;其实就是要创建一个和响应消息结构相匹配的Python类,然后把值写入这个类的成员,最后把response._postAppStatusResponse设置为myMsg,其中myMsg就是刚刚创建的新类结构。

1

我这里有一些代码可以帮你。我之前也遇到过类似的问题,想从WSDL生成Python代码,并联系Outlook OMS SMS网关。对于那些涉及复杂类型的消息,会生成一个新的构造函数new_complexType,你需要调用它。不过,如果WSDL出于某种原因没有提到这个,比如在调用时被序列化成了字符串,那么就不会自动生成新的构造函数。不过,复杂类型还是可以被实例化的。你可以看看下面的代码示例,完整的源代码在Phonero SMS

import sys
import uuid
from OMSService_client import *

loc = OMSServiceLocator()
kw = { 'tracefile' : sys.stdout }
port = loc.getOMSServiceSoap(**kw)

deliverXmsMsg = DeliverXmsSoapIn()

xmsData = ns0.xmsData_Dec().pyclass()
xmsData.set_attribute_client('Python SMS Client 1.0')

user = xmsData.new_user()
user.UserId = ''
user.Password = ''
user.ReplyPhone = ''
user.CustomData = ''
xmsData.User = user

xmsHead = xmsData.new_xmsHead()
xmsHead.To = xmsHead.new_to()
xmsHead.To.Recipient = ['']
xmsHead.SourceType = 'other'
xmsHead.RequiredService = xmsHead.new_requiredService('SMS_SENDER')
xmsData.XmsHead = xmsHead

xmsBody = xmsData.new_xmsBody()
xmsBody.set_attribute_format('SMS')
content = xmsBody.new_content('Hello, World!')
content.set_attribute_contentType('text/plain')
content.set_attribute_contentId(str(uuid.uuid4()))
content.set_attribute_contentLocation('1.txt')
xmsBody.Content.append(content)
xmsData.XmsBody = xmsBody

writer = ZSI.SoapWriter(envelope=0)
deliverXmsMsg.XmsData = writer.serialize(xmsData)

rsp = port.DeliverXms(deliverXmsMsg)

所以你可以看到,在这一行中,我可以这样构造一个xmsData Holder:

xmsData = ns0.xmsData_Dec().pyclass()

撰写回答