如何让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 = [一个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生成空元素;如何去掉它们? 不幸的是,去掉空元素要简单得多,而弄清楚哪些元素被去掉并重新添加它们就难多了。
谢谢!
2 个回答
如果有其他人遇到这个问题,找不到答案的话,我来分享一下我的经历。我当时在尝试发送一个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
这个选项,这样就不会去掉属性了。
在阅读了相关规范并与专家交流后,我没有发现任何说明说SOAP库可以去掉可选的、空的元素。
在github上有一个修复过的suds版本。