具有复杂类型的Python SUDS TypeNotFound,其名称以" __"开头。

时间:2015-11-18 19:54:45

标签: python soap suds

我在Python SUDS中遇到了另一个可怕的TypeNotFound错误(Python 2.7,suds-jurko == 0.6)

这些是XSD的相关部分:

 
<xs:complexType final="extension restriction" name="requestHeader">
    <xs:sequence>
        <xs:element minOccurs="0" name="type" type="tns:requestType"/>
        <xs:element minOccurs="0" name="userID" type="xs:string"/>
        <xs:element minOccurs="0" name="sessionID" type="xs:string"/>
    </xs:sequence>
</xs:complexType>
<xs:complexType final="extension restriction" name="requestType">
    <xs:sequence>
        <xs:element name="__value" type="xs:int"/>
    </xs:sequence>
</xs:complexType>

WSDL正确导入XSD,因此我不相信Doctor会提供帮助:

<wsdl:definitions 
    name="FooBarService" 
    targetNamespace="foo.bar.ns" 
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
    xmlns:tns="foo.bar.ns" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<schema xmlns="http://www.w3.org/2001/XMLSchema">
<import namespace="foo.bar.ns" schemaLocation="someschemafile.xsd"/>
<import namespace="http://jaxb.dev.java.net/array" schemaLocation="someschemafile2.xsd"/>

someschemafile.xsd

<xs:schema 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:ns1="http://jaxb.dev.java.net/array" 
    xmlns:tns="foo.bar.ns" 
    attributeFormDefault="unqualified" 
    elementFormDefault="unqualified" 
    targetNamespace="foo.bar.ns">

然后我创建requestHeaderrequestType

q = soap_client.factory.create('requestHeader')
print q

(requestHeader){
    type = 
    (requestType){
        __value = None
    }
    userID = None
    sessionID = None
}

然后:

q.type = soap_client.factory.create('requestType')
q.type.__value = 42
q.userID = "foo"
q.sessionID = "bar"
print q

(requestHeader){
    type = 
        (requestType){
            __value = 42
        }   
    userID = "foo"
    sessionID = "bar"
}

然后我尝试调用使用requestHeader的方法,之后我得到:

TypeNotFound(u"Type not found: '__value'",)

我也试过这个:

q = {
    'type': 42,
    'userID':  "foo",
    'sessionID':  "bar"
}

但这会导致错误的SOAP消息:

 
<header>
    <type>42</type>
    <userID>foo</userID>
    <sessionID>bar</sessionID>
</header>

而不是

 
<header>
    <type>
        <__value>42</__value>
    </type>
    <userID>foo</userID>
    <sessionID>bar</sessionID>
</header>

最终被服务拒绝了。

对不起,我无法提供完整的WSDL和XSD,它们受到限制。

如何使suds使用__value元素创建正确的SOAP XML?

我使用WSDL的本地副本,因此我可以更改它,只要它能够生成正确的SOAP XML。不过,我不知道该改变什么。

编辑:添加了一些清理后的回溯(在调用SUDS方法之前删除了东西)request是SUDS对象,其中一个属性属于requestHeader

---------------------------------------------------------------------------
FooClientClass                 Traceback (most recent call last)
<ipython-input-4-8ccf453fe073> in <module>()
----> 1 soap_client.service.someServiceMethod(request)

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/client.pyc in __call__(self, *args, **kwargs)
    519         client = clientclass(self.client, self.method)
    520         try:
--> 521             return client.invoke(args, kwargs)
    522         except WebFault, e:
    523             if self.faults():

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/client.pyc in invoke(self, args, kwargs)
    574         timer.start()
    575         binding = self.method.binding.input
--> 576         soapenv = binding.get_message(self.method, args, kwargs)
    577         timer.stop()
    578         metrics.log.debug("message for '%s' created: %s", self.method.name,

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/bindings/binding.pyc in get_message(self, method, args, kwargs)
    107         content = self.headercontent(method)
    108         header = self.header(content)
--> 109         content = self.bodycontent(method, args, kwargs)
    110         body = self.body(content)
    111         env = self.envelope(header, body)

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/bindings/document.pyc in bodycontent(self, method, args, kwargs)
     93 
     94         parse_args(method.name, self.param_defs(method), args, kwargs,
---> 95             add_param, self.options().extraArgumentErrors)
     96 
     97         return root

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/argparser.pyc in parse_args(method_name, param_defs, args, kwargs, external_param_processor, extra_parameter_errors)
     81     """
     82     arg_parser = _ArgParser(method_name, param_defs, external_param_processor)
---> 83     return arg_parser(args, kwargs, extra_parameter_errors)
     84 
     85 

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/argparser.pyc in __call__(self, args, kwargs, extra_parameter_errors)
    106         self.__init_run(args, kwargs, extra_parameter_errors)
    107         try:
--> 108             self.__process_parameters()
    109             return self.__all_parameters_processed()
    110         finally:

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/argparser.pyc in __process_parameters(self)
    297         """Collect values for given web service operation input parameters."""
    298         for pdef in self.__param_defs:
--> 299             self.__process_parameter(*pdef)
    300 
    301     def __push_frame(self, ancestry_item):

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/argparser.pyc in __process_parameter(self, param_name, param_type, ancestry)
    292         self.__stack[-1].process_parameter(param_optional, value is not None)
    293         self.__external_param_processor(param_name, param_type,
--> 294             self.__in_choice_context(), value)
    295 
    296     def __process_parameters(self):

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/bindings/document.pyc in add_param(param_name, param_type, in_choice_context, value)
     84             # Construct request data for the current input parameter.
     85             pdef = (param_name, param_type)
---> 86             p = self.mkparam(method, pdef, value)
     87             if p is None:
     88                 return

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/bindings/document.pyc in mkparam(self, method, pdef, object)
    128                 tags.append(self.mkparam(method, pdef, item))
    129             return tags
--> 130         return Binding.mkparam(self, method, pdef, object)
    131 
    132     def param_defs(self, method):

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/bindings/binding.pyc in mkparam(self, method, pdef, object)
    223         content = Content(tag=pdef[0], value=object, type=pdef[1],
    224             real=pdef[1].resolve())
--> 225         return marshaller.process(content)
    226 
    227     def mkheader(self, method, hdef, object):

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/core.pyc in process(self, content)
     57         if isinstance(content.value, Property):
     58             root = self.node(content)
---> 59         self.append(document, content)
     60         return document.root()
     61 

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/core.pyc in append(self, parent, content)
     70         log.debug('appending parent:\n%s\ncontent:\n%s', parent, content)
     71         if self.start(content):
---> 72             self.appender.append(parent, content)
     73             self.end(parent, content)
     74 

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/appender.pyc in append(self, parent, content)
     86                 appender = candidate_appender
     87                 break
---> 88         appender.append(parent, content)
     89 
     90 

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/appender.pyc in append(self, parent, content)
    227         for item in object:
    228             cont = Content(tag=item[0], value=item[1])
--> 229             Appender.append(self, child, cont)
    230 
    231 

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/appender.pyc in append(self, parent, content)
    166         @type content: L{Object}
    167         """
--> 168         self.marshaller.append(parent, content)
    169 
    170 

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/core.pyc in append(self, parent, content)
     70         log.debug('appending parent:\n%s\ncontent:\n%s', parent, content)
     71         if self.start(content):
---> 72             self.appender.append(parent, content)
     73             self.end(parent, content)
     74 

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/appender.pyc in append(self, parent, content)
     86                 appender = candidate_appender
     87                 break
---> 88         appender.append(parent, content)
     89 
     90 

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/appender.pyc in append(self, parent, content)
    227         for item in object:
    228             cont = Content(tag=item[0], value=item[1])
--> 229             Appender.append(self, child, cont)
    230 
    231 

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/appender.pyc in append(self, parent, content)
    166         @type content: L{Object}
    167         """
--> 168         self.marshaller.append(parent, content)
    169 
    170 

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/core.pyc in append(self, parent, content)
     70         log.debug('appending parent:\n%s\ncontent:\n%s', parent, content)
     71         if self.start(content):
---> 72             self.appender.append(parent, content)
     73             self.end(parent, content)
     74 

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/appender.pyc in append(self, parent, content)
     86                 appender = candidate_appender
     87                 break
---> 88         appender.append(parent, content)
     89 
     90 

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/appender.pyc in append(self, parent, content)
    227         for item in object:
    228             cont = Content(tag=item[0], value=item[1])
--> 229             Appender.append(self, child, cont)
    230 
    231 

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/appender.pyc in append(self, parent, content)
    166         @type content: L{Object}
    167         """
--> 168         self.marshaller.append(parent, content)
    169 
    170 

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/core.pyc in append(self, parent, content)
     69         """
     70         log.debug('appending parent:\n%s\ncontent:\n%s', parent, content)
---> 71         if self.start(content):
     72             self.appender.append(parent, content)
     73             self.end(parent, content)

/home/user/.virtualenvs/foo_project/local/lib/python2.7/site-packages/suds/mx/literal.pyc in start(self, content)
     84             content.type = self.resolver.find(name, content.value)
     85             if content.type is None:
---> 86                 raise TypeNotFound(content.tag)
     87         else:
     88             known = None

TypeNotFound(u"Type not found: '__value'",)

1 个答案:

答案 0 :(得分:0)

根据@dopstar评论,这是因为SUDS中的错误。由于我没有时间尝试在源代码上修复它,我设计了一些丑陋的解决方法

from lxml import etree

etree_object = build_XML_using_etree()

soap_client.service.someServiceMethod(
    __inject={'msg': etree.tostring(etree_object)}
)

丑陋的部分实际上在这里看不到它是编织隐藏在build_XML_using_etree方法后面的XML的逻辑,因为我们不能在这里依赖SUDS。

另一方面,一旦将原始XML注入SUDS堆栈,其他一切工作都很顺利,所以也许这不是那么糟糕......