【问题标题】:How to convert dict to suds complex suds type如何将 dict 转换为 suds 复杂的 suds 类型
【发布时间】:2016-01-20 20:11:42
【问题描述】:

我正在尝试使用如下所示的 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>

有没有办法通过使用 only 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>

所以我们可以确定我的 StringMetada 中缺少 id 属性。我想使用 only 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>

如果您有解决方案,请随时将猴子补丁(即时)应用于 suds 类。

问候

【问题讨论】:

    标签: python dictionary soap xmltodict


    【解决方案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
    

    此块可以在您的 sud 实例化之前插入,也可以存储在单独的脚本文件中并导入您的脚本中。就个人而言,我使用了第二种解决方案。

    还请注意,关键字文本是我选择的,您可以改用“_value_”。应该在这一行更新:

         if item[0] == '_text_':
    

    请随意使用此补丁。我认为这个功能应该内置在 Suds 库中

    问候,

    【讨论】:

      猜你喜欢
      • 2013-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多