我正在尝试使用 suds 向远程 SOAP 服务发出请求。我需要在参数上设置命名空间,因此:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns0="http://myemployer.com/" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<AuthHeader xmlns="http://myemployer.com/">
<Token>blah</Token>
</AuthHeader>
</SOAP-ENV:Header>
<ns1:Body>
<ns0:AwardBadgesBatch>
<ns0:badgeAwards>
<AwardBadge>
<EnterpriseID>jhoov11</EnterpriseID>
...
</AwardBadge>
</ns0:badgeAwards>
<ns0:includeSuccessStatus>false</ns0:includeSuccessStatus>
</ns0:AwardBadgesBatch>
</ns1:Body>
</SOAP-ENV:Envelope>
请注意 badgeAwards 和 includeSuccessStatus 元素上的“ns0”。我也不需要在徽章奖里面的东西上加上前缀。
我正在使用此代码提出请求:
from suds.client import Client
from suds.sax.element import Element
from suds.sax.attribute import Attribute
from suds.plugin import MessagePlugin
import logging
logging.getLogger('suds.client').setLevel(logging.DEBUG)
logging.getLogger('suds.transport').setLevel(logging.DEBUG)
logging.basicConfig(level=logging.DEBUG)
url='https://myemployer.com/BadgingServices.asmx?wsdl'
c = Client(url)
t = c.service.Authenticate('blah')
t = t.Authenticate.Status.Token
header_root = Element('AuthHeader')
header_token = Element('Token').setText(t)
header_attribute = Attribute('xmlns', "http://myemployer.com/")
soap_header = header_root.insert(header_token)
soap_header.append(header_attribute)
class NamespaceFixer(MessagePlugin):
''' must add namespace prefix to all parameters '''
def marshalled(self, context):
body = context.envelope[1]
for i in body[0]:
i.setPrefix('ns0')
print "******* element after setting prefix: %s ********" % i.plain()
nsf = NamespaceFixer()
c.set_options(soapheaders=soap_header, plugins=[nsf])
from suds.sax.element import Element
ba2 = Element('badgeAwards')
ba = Element('AwardBadge')
ba2.append(ba)
entid = Element('EnterpriseID').setText('jhoov11')
ba.append(entid)
...
includeSuccess = Element('includeSuccessStatus').setText('false')
c.service.AwardBadgesBatch(badgeAwards= ba2, includeSuccessStatus=includeSuccess)
现在,当我这样做时,我看到了 marshall() 调用之前的 xml 文本输出,并且我看到了该调用的输出:
******* element after setting prefix: <ns0:badgeAwards/> ********
******* element after setting prefix: <ns0:includeSuccessStatus/> ********
但是另一端的人坚持(坚持!)当他们收到前缀时,没有在这些元素上设置前缀。
想到两个问题:
- 我在 MessagePlugin 中做错了吗?
- 有没有办法在发送之前显示最终修改的 XML 文本?我想我正在设置它,但是当我看不到我发送的最终全文时,我只能对他们说这么多。
编辑:
c.last_sent().plain()
u'<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:ns0="http://pebble.searshc.com/" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header><AuthHeader xmlns="http://myemployer.com/"><Token>blah</Token></AuthHeader></SOAP-ENV:Header>
<ns1:Body><ns0:AwardBadgesBatch><ns0:badgeAwards/><ns0:includeSuccessStatus/></ns0:AwardBadgesBatch></ns1:Body></SOAP-ENV:Envelope>'
所以badgeAwards 和includeSuccessStatus 被发送为空。???
编辑:尝试工厂。这个 wsdl 很奇怪(对我来说)——它将调用本身定义为一种类型,因此:
<s:element name="AwardBadgesBatch">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="badgeAwards">
<s:complexType mixed="true">
<s:sequence>
<s:any/>
</s:sequence>
</s:complexType>
</s:element>
<s:element minOccurs="1" maxOccurs="1" name="includeSuccessStatus" type="s:boolean"/>
</s:sequence>
</s:complexType>
</s:element>
...
<wsdl:operation name="AwardBadgesBatch">
<soap:operation soapAction="http://pebble.searshc.com/AwardBadgesBatch" style="document"/>
<wsdl:input>
<soap:body use="literal"/>
<soap:header message="tns:AwardBadgesBatchAuthHeader" part="AuthHeader" use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
<soap:header message="tns:AwardBadgesBatchAuthHeader" part="AuthHeader" use="literal"/>
</wsdl:output>
</wsdl:operation>
它没有定义 AwardBadge 类型。所以我只是这样制作我的 AwardBadge:
ba = Element('AwardBadge')
entid = Element('EnterpriseID').setText('jhoov11')
ba.append(entid)
btype = Element('badgeTypeID').setText('30')
ba.append(btype)
startdate = Element('startDate').setText('2013-8-22')
ba.append(startdate)
enddate = Element('endDate').setText('9999-12-31')
ba.append(enddate)
isdeleted = Element('isDeleted').setText('0')
ba.append(isdeleted)
我在通话中设置了值
call = c.factory.create('AwardBadgesBatch')
call.badgeAwards= [ba]
call.includeSuccessStatus= False
我打电话给服务
c.service.AwardBadgesBatch(call)
并得到一些错误。当我查看我发送的内容时,我看到了
c.last_sent().plain()
u'<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:ns0="http://myemployer.com/" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<AuthHeader xmlns="http://myemployer.com/"><Token>blah</Token></AuthHeader>
</SOAP-ENV:Header>
<ns1:Body>
<ns0:AwardBadgesBatch>
<ns0:badgeAwards>
<AwardBadge/>
<ns0:includeSuccessStatus>false</ns0:includeSuccessStatus>
</ns0:badgeAwards>
<ns0:includeSuccessStatus/>
</ns0:AwardBadgesBatch>
</ns1:Body>
</SOAP-ENV:Envelope>'
所以,三个问题:
- 奖章为空。
- includeSuccessStatus 是重复的,一个在 badgeAwards 中,它不属于它。
- 正确位置的 includeSuccessStatus 是空的。
我是否将 badgeAwards 设置为 ba 或 [ba] 都没有区别。
还有更多见解吗?