Неверный XML, созданный SUDS - PullRequest
3 голосов
/ 10 мая 2010

Я пытаюсь общаться с веб-службой SOAP, используя SUDS и Python. После большого количества возни с изучением Python (да, я новичок в этом) и разработкой, как использовать SUDS, я столкнулся с проблемой.

Подпись веб-метода, который я вызываю, в соответствии с suds,

(FWTCaseCreate){
ClassificationEventCode = None
Priority = None
Title = None
Description = None
Queue = None
DueDate = None
AssociatedObject = 
  (FWTObjectBriefDetails){
     ObjectID = 
        (FWTObjectID){
           ObjectType = None
           ObjectReference[] = <empty>
        }
     ObjectDescription = None
     Details = None
     Category = None
  }
Form = 
  (FWTCaseForm){
     FormField[] = <empty>
     FormName = None
     FormKey = None
  }
Internal = None
InteractionID = None
XCoord = None
YCoord = None
}

Поэтому я использую SUDS для создания нужных мне классов и отправляю их в метод. Однако я получаю ошибку. Поэтому я включил вход в систему и вижу, что отправляемый XML-файл неверен, что вызывает ошибку десериализации. Пакет SOAP выглядит следующим образом

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns0="http://www.CRM.com/wsdl/FLTypes"    xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
   <wsse:Security>
      <wsse:BinarySecurityToken>eaadf1ddff99a8</wsse:BinarySecurityToken>
   </wsse:Security>
</SOAP-ENV:Header>
<ns1:Body>
   <ns0:FWTCaseCreate>
      <ClassificationEventCode>
         <ClassificationEventCode>2000023</ClassificationEventCode>
         <Priority>1</Priority>
         <Title>testing</Title>
         <Description>testing</Description>
         <Queue/>
         <Internal>True</Internal>
         <XCoord>356570</XCoord>
         <YCoord>168708</YCoord>
      </ClassificationEventCode>
   </ns0:FWTCaseCreate>
</ns1:Body>

Как видите, есть 'ClassificationEventCode' элемент вокруг всех других элементов, этого не должно быть. Если я вырезал и вставил этот XML-файл в SOAPUI и сначала удалил этот элемент, а затем опубликовал его непосредственно в веб-службе, он успешно работает.

Вот код, который я использую для звонка

client = Client(url)

#Add a header for the security
ssnns = ('wsse', 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd')

ssn = Element('BinarySecurityToken', ns=ssnns).setText(binaryKey)

ssn1 = Element('Security',ns=ssnns)

ssn1.append(ssn)

client.set_options(soapheaders=ssn1) 

newCase = client.factory.create('ns1:FWTCaseCreate')

classEventCode = client.factory.create('ns1:FWTEventCode')
classEventCode.value = 2000023

newCase.ClassificationEventCode = classEventCode
newCase.Priority = 1
#optional
newCase.AssociatedObject = None
#optional
newCase.Form = None
#optional
newCase.Internal = None
#optional
newCase.InteractionID =  None
#optional
newCase.DueDate = None
#optional
newCase.Queue = None

newCase.Title = 'Title'

newCase.Description = 'description'

newCase.XCoord = '356570'

newCase.YCoord = '168708'

caseID = client.service.createCase(newCase)

У кого-нибудь есть идеи, почему это происходит? Я думаю, что SUDS считает, что это должно быть там на основе WSDL.

Спасибо.

Ответы [ 5 ]

6 голосов
/ 12 августа 2010

I получил , получая точно такую ​​же проблему. Последовательность параметров в моем запросе SOAP заключена в элемент с тем же именем, что и первый параметр. например,

....
   <ns0:Body>
      <ns1:CreationReq>
         <ReqType>
            <ReqType>1</ReqType>
            <Title>Mr</Title>
            ....
         </ReqType>
      </ns1:CreationReq>
   </ns0:Body>
....

Я проверил WSDL, чтобы убедиться, что с ним нет проблем.

Кажется, проблема в том, что я создал объект CreationReq, используя метод client.factory.create. Проверка клиента путем печати показывает, что метод, который я вызываю, не принимает этот объект в качестве параметра. Скорее, он принимает список именованных аргументов.

Итак, мой код был:

req = client.factory.create('CreationReq')
req.ReqType = 1
req.Title = 'Mr'
resp = client.service.Create(req)

Теперь это:

req = {}
req['ReqType'] = 1
req['Title'] = 'Mr'
resp = client.service.Create(**req)
1 голос
/ 17 июля 2012

Если вы создаете клиента для своих служб suds, вы можете увидеть некоторые атрибуты, чтобы определить, какие объекты необходимы для передачи в вызов службы.

Например:

import suds
client = suds.Client(url)
for a in client.sd: #print the whole service definition
    print a

Это должно показать вам префиксы, порты с методами и типами. Для вашего кода вы должны видеть, что нужно передать в вызове сервиса для createCase. Несмотря на то, что WSDL может определять метод как требующий «FWTCaseCreate», suds может выбирать определение для createCase, чтобы ему требовались ClassificationEventCode, Priority, Title type и т. Д.

Поэтому вы не захотите делать: (который передается в newCase для первого аргумента, помещая все детали под этим тегом)

newCase = client.factory.create('ns1:FWTCaseCreate')
caseID = client.service.createCase(newCase)

Но вместо этого вызывайте сервис следующим образом: (на основе определения сервиса)

newCase = client.factory.create('ns1:FWTCaseCreate')
caseID = client.service.createCase(newCase.ClassificationEventCode, newCase.Priority, ...)

Или, может быть:

newCase = client.factory.create('ns1:FWTCaseCreate')
caseID = client.service.createCase(*[getattr(newCase,a) for a in newCase.__keylist__])

Передача списка аргументов, необходимых для вызова службы.

Я не знаю, почему определение вызова службы неправильно разрешено как то, чем оно является, но передача правильного объекта не расширяется автоматически до нужного списка нужных аргументов. Возможно, чтение источника suds (http://jortel.fedorapeople.org/suds/doc/) поможет обнародовать ответ.

0 голосов
/ 02 октября 2014

Я нашел эту тему в поисках решения той же проблемы. До сих пор я исследовал, что это происходит только тогда, когда вы передаете объект, созданный на заводе, непосредственно методу сервиса И только с типами данных wsdl, использующими расширение (наследование).

Есть еще решения, о которых я мог бы подумать.

  • вообще не использовать фабрику для типа верхнего уровня.
  • плагин записи suds, изменяющий xml после генерации
  • переписать wsdl, чтобы не использовать наследование (тег расширения)
  • изменить тип объекта перед переходом к методу обслуживания

Я выбрал последний, так как это самый простой способ. Итак, есть код.

def sudsToDict(data):
    return dict([(str(key),val) for key,val in data])

Используйте вот так.

data = client.factory.create('wsdl_data_type')
# now fill with values and then
data = sudsToDict(data)
client.service.some_method(**data)
0 голосов
/ 12 мая 2010

Вы создали элемент дважды. Удалить это:

classEventCode = client.factory.create('ns1:FWTEventCode') 
classEventCode.value = 2000023 

И измените это:

newcase.ClassificationEventCode = 2000023

Это должно удалить этот дополнительный тег.

0 голосов
/ 10 мая 2010

Вы собираетесь использовать это как Конфигурационный файл, или для хранения информации. Или это для отправки данных через Веб?

Хорошо, тогда, если это так, то почему бы не использовать json или json-rpc, они, как говорят, намного быстрее, легче разбираются и намного легче читаются. XML является гибким типом данных, и я лично не могу ждать, пока он умрет, если вы ищете отправку данных, то стоит использовать json.

...