nmt*_*ken 2 python attributes soap namespaces suds
我正在使用 python suds(版本:0.3.9 GA build:R659-20100219)与具有以下结构的 SOAP 服务交互:
服务 (DPWSService) tns="http://ejb.revitalization.services.ndg/" 前缀 (1) ns0 = "http://ejb.revitalization.services.ndg/" 端口 (1): (DPWS端口) 方法(13): addTimer(请求请求,) deleteProvider(请求请求,) deleteTimer(请求请求,) doHarvest(请求请求,) doIngest(请求请求,) doNewUpdateProvider(请求请求,) getHarvestHistory(GetHistoryRequest 请求, ) getIngestHistory(GetHistoryRequest 请求,) getList(GetListType 请求,) 获取列表名称() getProviderDetails(请求请求,) getProviderStatistic(请求请求,) getStatusProcess(请求请求,) 类型 (63): 添加定时器响应 CSWProviderDetailsType 确认类型 联系人类型 数据范围类型 删除提供者响应 删除定时器响应 收获响应 摄取响应 DoNewUpdateProviderResponse 电子邮件联系人类型 获取HarvestHistoryResponse 获取历史请求 获取摄取历史响应 获取列表名称响应 获取列表响应 获取列表类型 获取进程状态响应 获取提供者详细信息响应 获取提供者统计响应 收获历史类型 HarvestProvider 类型 收获类型 摄取历史类型 列表名称 OAI提供者详细信息类型 进程ID类型 ProviderCommonType ProviderContactType 提供者详细信息 提供者详细信息类型 提供者ID类型 提供者统计 响应类型 定时器信息通用类型 定时器信息详细信息 定时器信息日志详细信息 添加定时器 添加定时器响应 删除提供者 删除提供者响应 删除定时器 删除定时器响应 doHarvest doHarvestResponse 做摄取 做摄取响应 doNewUpdateProvider doNewUpdateProviderResponse 获取收获历史 getHarvestHistoryResponse 获取历史记录 getIngestHistoryResponse 获取列表 获取列表名称 获取列表名称响应 获取列表响应 获取提供者详细信息 获取提供者详细信息响应 获取提供者统计信息 获取提供者统计响应 获取状态进程 获取状态处理响应
我需要发送一个结构如下的 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>
Run Code Online (Sandbox Code Playgroud)
也就是说,我需要在 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>
Run Code Online (Sandbox Code Playgroud)
也就是说,在 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)
Run Code Online (Sandbox Code Playgroud)
和:
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)
Run Code Online (Sandbox Code Playgroud)
和:
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)
Run Code Online (Sandbox Code Playgroud)
但我收到了相同的 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>
Run Code Online (Sandbox Code Playgroud)
和
<xs:complexType name="ProcessIDType">
<xs:sequence/>
<xs:attribute ref="tns:id" use="required"/>
<xs:attribute ref="tns:status"/>
</xs:complexType>
Run Code Online (Sandbox Code Playgroud)
这表明 id 确实需要命名空间前缀。
因此,问题是,如何将命名空间前缀强制添加到我的 id 属性上?
感谢甘地
因此,解决方案是:
将 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)
Run Code Online (Sandbox Code Playgroud)
您要查找的内容在suds 文档中,称为 MessagePlugin。marshalled 选项允许您在发送之前更改您的消息。您需要将它作为插件添加到您的客户端中:
self.client = Client(url, plugins=[MyPlugin()])
Run Code Online (Sandbox Code Playgroud)
在编组方法中搜索 context.envelope childs。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
Run Code Online (Sandbox Code Playgroud)
对于这个“类似这部分的东西”,您需要调试您的请求(我推荐客户端和传输调试)并查找您的实体的变量。我只是不记得它是怎么称呼的。
我上周坐在这里,所以它可能会为你节省一些时间:) 当你有任何问题时写信,我会尽量在那里更具体。