Как заставить префикс пространства имен для attibute в запросе SOAP, созданном с помощью suds - PullRequest
1 голос
/ 04 апреля 2011

Я использую 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>

, который показывает, что для идентификатора нужен префикс пространства имен.

Таким образом, вопрос заключается в том, как заставить префикс пространства имен указать мой идентификатор attibute?

Благодаря Ганди

Решение было поэтому:

Обновление 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)

Ответы [ 2 ]

4 голосов
/ 20 апреля 2011

То, что вы ищете, находится в документации 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

Для этой «что-то вроде этой части» вам нужно отладить ваш запрос (я рекомендую отладку клиента и транспорта) и искать различныеваша сущность.Я просто не помню, как он называется.

Я сидел в этом на прошлой неделе, так что, возможно, это сэкономит вам время :) Пишите, когда у вас возникнут вопросы, я постараюсьчтобы быть более конкретным там.

0 голосов
/ 04 апреля 2011

Не уверен насчет лучшего решения, но я сталкивался с подобными проблемами во время разговора с Sharepoint через мой модуль haufe.sharepoint (в PyPI).Я закончил тем, что стал патчем send () suds, чтобы изменить пространства имен в соответствии с моими потребностями.Вы можете проверить код в файле patches.py модуля.

...