如何获取suds来发送可选的空元素?

时间:2014-05-12 00:35:44

标签: python soap suds

我有一个SOAP API,我试图通过suds(python)调用一个方法:

DoSomething(ns1:DoSomethingRequest Input, )

DoSomethingRequest看起来像这样:

    (DoSomethingRequest){
   Person = 
      (Person){
         Name = "Joe"
         Age = 32
      }
   ActionOne = None
   ActionTwo = None
   ActionThree = None
 }

在类型定义中,动作参数都是可选的。要调用特定操作,请设置DoSomethingRequest.ActionOne = [an instance of ActionOneRequest]。这很好(我可以执行ActionOne),除了我试图调用ActionThree,而ActionThreeRequest是一个空的复杂元素。当我设置DoSomethingRequest.ActionThree = ActionThreeRequest时,DoSomethingRequest上的打印件会显示:

    (DoSomethingRequest){
   Person = 
      (Person){
         Name = "Joe"
         Age = 32
      }
   ActionOne = None
   ActionTwo = None
   ActionThree = <empty>
 }

并且发送到服务器的XML排除了ActionThree。如果我用pdb拦截代码并添加一个空元素<ActionThree></ActionThree>,它就可以工作。

查看代码,为suds:

class ObjectAppender(Appender):
    """
    An L{Object} appender.
    """

    def append(self, parent, content):
        object = content.value
        if self.optional(content) and footprint(object) == 0:
            return
        child = self.node(content)
        parent.append(child)
        for item in object:
            cont = Content(tag=item[0], value=item[1])
            Appender.append(self, child, cont)

def footprint(sobject):
    """
    Get the I{virtual footprint} of the object.
    This is really a count of the attributes in the branch with a significant value.
    @param sobject: A suds object.
    @type sobject: L{Object}
    @return: The branch footprint.
    @rtype: int
    """
    n = 0
    for a in sobject.__keylist__:
        v = getattr(sobject, a)
        if v is None: continue
        if isinstance(v, Object):
            n += footprint(v)
            continue
        if hasattr(v, '__len__'):
            if len(v): n += 1
            continue
        n +=1
    return n

我不经常使用SOAP,所以我假设我正在使用API​​不正确,或者使用的是不正确的suds。或者,服务API可能是非标准的。

你知道为什么会有问题以及如何最好地解决它?

奇怪的是,相反的问题是SO:Suds generates empty elements; how to remove them?不幸的是,删除空元素要比找出哪些元素被删除并重新添加它们要容易得多。

谢谢!

2 个答案:

答案 0 :(得分:2)

在阅读规范并与专家交谈后,我没有看到任何表明SOAP库可以删除可选的空元素的任何内容。

github上有一个补丁版的肥皂水。

答案 1 :(得分:1)

如果其他人遇到这个问题,并且没有找到答案。类似的情况发生在我身上。我试图在SOAP请求中发送以下正文,

<ns0:list><ns0:filter xsi:type="ns0:UserFilter"/></ns0:list>

我的第一次尝试,我使用suds.client.factory创建了元素,并在没有配置的情况下发送它。这导致了以下机构,

<ns0:list><filter/></ns0:list>

我接下来尝试手动创建Element并手动设置type属性。那让我有了同样的信封。

在深入研究源代码后,我发现SoapClient.send()方法正在sax.Document.plain()方法中剥离我的属性。

查看代码,我发现我可以在suds客户端设置prettyxml=True选项,并且不会剥离该属性。