Как преобразовать dict в сложный тип suds
Я пытаюсь отправить запрос на мыльный сервер, используя suds, который должен выглядеть следующим образом:
<SOAP-ENV:Envelope xmlns:ns0="http://example.com/wsdl/abc/model/v1" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns2="http://example.com/xsd/abc/common/v1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<ns1:Body>
<ns0:myMethod>
<unique_id>5211c04b-9cf5-4368-a393-ed96d7b5489d</unique_id>
<metadata>
<ns2:StringMetadata id="user">test_user</ns2:StringMetadata>
<ns2:StringMetadata id="filename">myfile.zip</ns2:StringMetadata>
<ns2:StringMetadata id="unique_id">5211c04b-9cf5-4368-a393-ed96d7b5489d</ns2:StringMetadata>
</metadata>
</ns0:myMethod>
</ns1:Body>
Есть ли способ сделать это, используя только dict?
Я пытаюсь это:
params = {
'unique_id' : uid,
"metadata": {
'StringMetadata' : ['test_user', 'myfile.zip']
}
}
caller.myMethod(**params)
который генерирует этот запрос:
<SOAP-ENV:Envelope xmlns:ns0="http://example.com/wsdl/abc/model/v1" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns2="http://example.com/xsd/abc/common/v1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<ns1:Body>
<ns0:myMethod>
<unique_id>2ae5a60e-7928-4d4f-9e53-bafe2a003b8a</unique_id>
<metadata>
<ns2:StringMetadata>test_user</ns2:StringMetadata>
<ns2:StringMetadata>myfile.zip</ns2:StringMetadata>
</metadata>
</ns0:myMethod>
</ns1:Body>
</SOAP-ENV:Envelope>
Таким образом, мы можем видеть, что атрибуты id отсутствуют в моей StringMetada. Я хочу сделать это, используя только dict, потому что я пишу своего рода прокси Rest to Soap, который получает неподтвержденный Json (или dict) от другого абонента. Так что это должно быть как можно более динамичным.
Я пытался создавать на лету элементы (с factory.create), но, похоже, это головная боль... Я был бы признателен за решение путем передачи специального ключевого слова для атрибутов элемента ('_id', '@id' или '#id ")...
Я также попытался объявить свои StringMetadata следующим образом:
"metadata": {
'StringMetadata' : [{'_id': 'user'}, 'myfile.zip']
}
но это дало мне:
<ns2:StringMetadata id="user"/>
<ns2:StringMetadata>myfile.zip</ns2:StringMetadata>
Если у вас есть решение, примените monkey-patch (на лету) к классам suds, пожалуйста, не стесняйтесь.
С уважением
1 ответ
Мне, наконец, удалось заставить его работать после нескольких часов понимания и отладки пены. Я написал решение на основе патча suds monkey-patch. Таким образом, мой дикт должен быть:
params = {
'unique_id' : uid,
"metadata": {
'StringMetadata' : [{'_id': 'user', '_text_':'test_user'},{'_id': 'filename', '_text_': 'myfile.zip'}]
}
}
caller.myMethod(**params)
"_text_" - это магия, которая будет обнаружена патчем и использована в качестве значения узла. '_Id' будет использоваться suds в качестве атрибута, каждый элемент, начинающийся с _, интерпретируется как атрибут узла, поэтому мой патч не обрабатывает атрибуты.
Это патч:
import functools
from suds.mx.appender import *
legacy_append = suds.mx.appender.ObjectAppender.append
@functools.wraps(legacy_append)
def _patch_object_append(self, parent, content):
object = content.value
if self.optional(content) and footprint(object) == 0:
return
child = self.node(content)
for item in object:
cont = Content(tag=item[0], value=item[1])
if item[0] == '_text_':
child.setText(item[1])
continue
Appender.append(self, child, cont)
parent.append(child)
suds.mx.appender.ObjectAppender.append= _patch_object_append
Этот блок может быть вставлен перед созданием экземпляра suds или сохранен в отдельном файле сценария и импортирован в ваш сценарий. Лично я использовал второе решение.
Также обратите внимание, что текст ключевого слова был моим выбором, вместо этого вы можете использовать_value_. Это должно быть обновлено в этой строке:
if item[0] == '_text_':
Пожалуйста, не стесняйтесь использовать этот патч. Я думаю, что эта функция должна быть встроена в библиотеку Suds
С Уважением,