我正在使用python suds(版本:0.3.9 GA build:R659-20100219)与具有以下结构的SOAP服务进行交互:
Service ( DPWSService ) tns="http://ejb.revitalization.services.ndg/" Prefixes (1) ns0 = "http://ejb.revitalization.services.ndg/" Ports (1): (DPWSPort) Methods (13): addTimer(request request, ) deleteProvider(request request, ) deleteTimer(request request, ) doHarvest(request request, ) doIngest(request request, ) doNewUpdateProvider(request request, ) getHarvestHistory(GetHistoryRequest request, ) getIngestHistory(GetHistoryRequest request, ) getList(GetListType request, ) getListNames() getProviderDetails(request request, ) getProviderStatistic(request request, ) getStatusProcess(request request, ) Types (63): AddTimerResponse CSWProviderDetailsType ConfirmationType ContactType DataRangeType DeleteProviderResponse DeleteTimerResponse DoHarvestResponse DoIngestResponse DoNewUpdateProviderResponse EmailContactType GetHarvestHistoryResponse GetHistoryRequest GetIngestHistoryResponse GetListNamesResponse GetListResponse GetListType GetProcessStatusResponse GetProviderDetailsResponse GetProviderStatisticResponse HarvestHistoryType HarvestProviderType HarvestType IngestHistoryType ListNames OAIProviderDetailsType ProcessIDType ProviderCommonType ProviderContactType ProviderDetail ProviderDetailsType ProviderIDType ProviderStatistic ResponseType TimerInfoCommonType TimerInfoDetail TimerInfoLogDetail addTimer addTimerResponse deleteProvider deleteProviderResponse deleteTimer deleteTimerResponse doHarvest doHarvestResponse doIngest doIngestResponse doNewUpdateProvider doNewUpdateProviderResponse getHarvestHistory getHarvestHistoryResponse getIngestHistory getIngestHistoryResponse getList getListNames getListNamesResponse getListResponse getProviderDetails getProviderDetailsResponse getProviderStatistic getProviderStatisticResponse getStatusProcess getStatusProcessResponse
我需要发送一个SOAP请求,结构如下:
<SOAP-ENV:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://
ejb.revitalization.services.ndg/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<ns0:Body>
<ns1:doIngest>
<request>
<ns1:ProcessID ns1:id="1430"/>
<ns1:EmailReportID>1031</ns1:EmailReportID>
</request>
</ns1:doIngest>
</ns0:Body>
</SOAP-ENV:Envelope>
也就是说,我需要在id属性前添加目标命名空间。如果我不这样做,请求失败:(
我已经尝试了几种方法来创建我的doIngest请求对象,但我只能创建如下的请求:
<SOAP-ENV:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://ejb.revitalization.services.ndg/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<ns0:Body>
<ns1:doIngest>
<request>
<ns1:ProcessID id="1441"/>
<ns1:EmailReportID>1031</ns1:EmailReportID>
</request>
</ns1:doIngest>
</ns0:Body>
</SOAP-ENV:Envelope>
也就是说,id属性上没有目标名称空间前缀。
我尝试了以下的变体:
request = wsClient.factory.create('doIngest.request')
request.EmailReportID = "1031"
request.ProcessID = wsClient.factory.create('ProcessIDType')
request.ProcessID._id= "1430"
result=wsClient.service.doIngest(request)
和
request = wsClient.factory.create('{http://ejb.revitalization.services.ndg/}doIngest.request')
request.EmailReportID = "1031"
request.ProcessID = wsClient.factory.create('{http://ejb.revitalization.services.ndg/}ProcessIDType')
request.ProcessID._id="1430"
result=wsClient.service.doIngest(request)
和
request = wsClient.factory.create('doIngest.request')
request.EmailReportID = emailIDs
request.ProcessID = wsClient.factory.create('ProcessIDType')
request.ProcessID._id = wsClient.factory.resolver.qualify('{http://ejb.revitalization.services.ndg/}_id')
request.ProcessID._id=procID
result=wsClient.service.doIngest(request)
但我得到了相同的SOAP请求
WSDL告诉我:
<xs:complexType name="doIngest">
<xs:sequence>
<xs:element form="unqualified" minOccurs="0" name="request">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="ProcessID" type="tns:ProcessIDType"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="EmailReportID" type="xs:int"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
和
<xs:complexType name="ProcessIDType">
<xs:sequence/>
<xs:attribute ref="tns:id" use="required"/>
<xs:attribute ref="tns:status"/>
</xs:complexType>
表明id确实需要名称空间前缀。
问题是,如何强制命名空间前缀到我的id attibute?
感谢Gandi
因此解决方案是:
将Suds更新为0.4(因为版本中没有MessagePlugin:0.3.9)
然后:
class MyPlugin(MessagePlugin):
def marshalled(self, context):
ProcIDnode = context.envelope.getChild('Body').getChild('doIngest').getChild('request')[0]
#Get the value of the id attribute
ProcIDattVal = ProcIDnode.get('id')
#Remove the errant id, used as a tidy-up stage
ProcIDnode.unset('id')
#Get the namespace prefix for the target namespace
ProcIDnspref = ProcIDnode.findPrefix('http://ejb.revitalization.services.ndg/')
#Create the new attribute name with namespace prefix applied
newProcIDattname = ProcIDnspref + ':id'
#Insert the new attribute.
ProcIDnode.set(newProcIDattname,ProcIDattVal)
答案 0 :(得分:4)
您正在寻找的是suds documentation,称为MessagePlugin。编组选项允许您在发送之前更改您的消息。您需要将其作为插件添加到客户端中:
self.client = Client(url, plugins=[MyPlugin()])
在编组方法中搜索context.envelope子项。 python的vars()函数在这个地方非常有用。我认为,它应该像你这样:
from suds.plugin import MessagePlugin
class MyPlugin(MessagePlugin):
def marshalled(self, context):
foo = context.envelope.getChild('Body').getChild...getChild(and so on)[0]
foo.nsprefix = # or something like this
对于这个“类似这部分的东西”,您需要调试您的请求(我建议客户端和传输调试)并查找您的实体的变量。我只是不记得它是怎么称呼的。
我上周坐在这里,所以可能会为你节省一些时间:)写下你有什么问题时,我会尝试在那里更具体。
答案 1 :(得分:0)
不确定最佳解决方案但我在通过haufe.sharepoint模块(在PyPI上)与Sharepoint交谈时遇到了类似的问题。我最后修补了suds的send(),以便根据我的需要修改名称空间。您可以检查模块的patches.py文件中的代码。