2

我正在使用 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
获取历史请求
获取摄取历史响应
获取列表名称响应
获取列表响应
获取列表类型
获取进程状态响应
GetProviderDetailsResponse
GetProviderStatisticResponse
收获历史类型
HarvestProviderType
收获类型
摄取历史类型
列表名称
OAIProviderDetailsType
进程ID类型
ProviderCommonType
提供者联系类型
提供者详情
ProviderDetailsType
提供者IDType
提供者统计
响应类型
TimerInfoCommonType
定时器信息详情
TimerInfoLogDetail
添加定时器
addTimerResponse
删除提供者
删除提供者响应
删除定时器
删除定时器响应
收获
收获回应
摄取
摄取响应
doNewUpdateProvider
doNewUpdateProviderResponse
获取收获历史
getHarvestHistoryResponse
获取摄取历史
获取摄取历史响应
获取列表
获取列表名称
获取列表名称响应
获取列表响应
获取提供者详细信息
getProviderDetailsResponse
获取提供者统计
getProviderStatisticResponse
获取状态进程
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 属性上?

感谢甘地

因此解决方案是:

将 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)
4

2 回答 2

5

您正在寻找的是suds 文档中的内容,称为 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

对于这个“类似这部分的东西”,您需要调试您的请求(我推荐客户端和传输调试)并查找您的实体的变量。我只是不记得它是怎么称呼的。

上周我坐在这里,所以它可能会为你节省一些时间:) 当你有任何问题时写,我会在那里更具体。

于 2011-04-20T13:11:21.533 回答
0

不确定最佳解决方案,但我在通过我的 haufe.sharepoint 模块(在 PyPI 上)与 Sharepoint 交谈时遇到了类似的问题。我最终对 suds 的 send() 进行了猴子修补,以便根据我的需要修改命名空间。您可以查看模块的 patch.py​​ 文件中的代码。

于 2011-04-04T14:35:59.420 回答