【问题标题】:SUDS and Namespaces in XML AttributesXML 属性中的 SUDS 和命名空间
【发布时间】:2015-02-05 00:57:10
【问题描述】:

我在让 SUDS 与 NetSuite SOAP API 很好地配合使用时遇到了一些麻烦。我已经使用 SoapUI 来发送适用于我想要的调用的 NetSuite XML,但我无法让它与 Python 一起使用。这是工作的 XML:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:urn="urn:messages_2015_1.platform.webservices.netsuite.com" 
xmlns:urn1="urn:core_2015_1.platform.webservices.netsuite.com"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>
   <soapenv:Header>
      <urn:preferences>
      </urn:preferences>
      <urn:partnerInfo>
      </urn:partnerInfo>
      <urn:applicationInfo>

      </urn:applicationInfo>
      <urn:passport>
         <urn1:email>*****</urn1:email>
         <urn1:password>*****</urn1:password>
         <urn1:account>*****</urn1:account>
         <!--Optional:-->
         <urn1:role internalId=*****>
         </urn1:role>
      </urn:passport>
   </soapenv:Header>
   <soapenv:Body>
      <urn:get>
        <urn1:baseRef internalId="2026" type="customer" xsi:type="urn1:RecordRef"/>
      </urn:get>
   </soapenv:Body>
</soapenv:Envelope>

在 Python 中,我生成了一个 RecordRef 对象并填充了它,但它不关心我的输入:

>>> recordRef = client.factory.create('ns4:RecordRef')
>>> recordRef
(RecordRef){
   name = None
   _internalId = ""
   _externalId = ""
   _type = ""
 }
>>> recordRef._internalId = 2026
>>> recordRef._type = 'customer'
>>> recordRef
(RecordRef){
   name = None
   _internalId = 2026
   _externalId = ""
   _type = "customer"
 }
>>> client.service.get(recordRef)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/suds/client.py", line 521, in __call__
    return client.invoke(args, kwargs)
  File "/usr/local/lib/python2.7/dist-packages/suds/client.py", line 581, in invoke
    result = self.send(soapenv)
  File "/usr/local/lib/python2.7/dist-packages/suds/client.py", line 619, in send
    description=tostr(e), original_soapenv=original_soapenv)
  File "/usr/local/lib/python2.7/dist-packages/suds/client.py", line 670, in process_reply
    raise WebFault(fault, replyroot)
suds.WebFault: Server raised fault: 'org.xml.sax.SAXException: Invalid type: customer'
>>> 

当我查看正在发送的 XML 时,我注意到 xsi:type 已设置,但 type 未设置。

如果我将客户(实际上是 xsi:customer)设置为在 SoapUI 中有效的相同值,我会收到关于客户未设置的错误:

(ReadResponse){
   status = 
      (Status){
         _isSuccess = False
         statusDetail[] = 
            (StatusDetail){
               _type = "ERROR"
               code = "RCRD_TYPE_REQD"
               message = "The record type is required."
            },
      }
 }
>>> recordRef
(RecordRef){
   name = None
   _internalId = 2026
   _externalId = ""
   _type = "ns1:RecordRef"
 }

大约五年来,我没有用 SOAP 做过任何事情,在此之前,我从来没有用过 Python。任何建议将不胜感激。

【问题讨论】:

  • 看来我需要写一个插件,在出路时重写东西:

标签: python soap suds


【解决方案1】:

想通了,我需要写一个插件来调用 marshalled() 方法:

class FixXML(suds.plugin.MessagePlugin):
        def __init__(self):
                pass

        def marshalled(self, context):
                #the attribute type is really xsi:type, which we need to set but is being handled wrong
                #get the Netsuite data type
                wsdlDataType = context.envelope.getChild('Body').getChild('get').getChild('baseRef').getAttribute('type').getValue()
                #now rewrite xsi:type so its something namespacey
                context.envelope.getChild('Body').getChild('get').getChild('baseRef').getAttribute('type').setValue('ns0:RecordRef')
                #next we need to add a type attribute without a namespace that contains the data type from the wsdl
                typeAttr = suds.sax.attribute.Attribute('type')
                typeAttr.setValue(wsdlDataType)
                context.envelope.getChild('Body').getChild('get').getChild('baseRef').append(typeAttr)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-27
    • 2019-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多