Переопределение типа из файла WSDL с Zeep - PullRequest
0 голосов
/ 08 января 2020

В файле WSDL для API-интерфейса ServiceNow SOAP request_payload определено как строка, если это фактически словарь. В результате каждый раз, когда я запрашиваю службу, я получаю сообщение об ошибке:

"ValueError: The String type doesn't accept collections as value".

Раздел файла WSDL:

<wsdl:definitions targetNamespace="http://www.service-now.com/ChangeOperation" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://www.service-now.com/ChangeOperation" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
   <wsdl:types>
      <xsd:schema elementFormDefault="qualified" targetNamespace="http://www.service-now.com/ChangeOperation">
         <xsd:element name="changeOperationRequest">
            <xsd:complexType>
               <xsd:sequence>
                  <xsd:element maxOccurs="1" minOccurs="0" name="source_system" type="xsd:string"/>
                  <xsd:element maxOccurs="1" minOccurs="0" name="source_uid" type="xsd:string"/>
                  <xsd:element maxOccurs="1" minOccurs="0" name="request_type" type="xsd:string"/>
                  <xsd:element maxOccurs="1" minOccurs="0" name="request_payload" type="xsd:string"/>
               </xsd:sequence>
            </xsd:complexType>

Успешный запрос SOAP с использованием SOAPUI:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns0="http://www.service-now.com/ChangeOperation">
   <soapenv:Header/>
   <soapenv:Body>
      <ns0:changeOperationRequest>
         <!--Optional:-->
         <ns0:source_system>Script</ns0:source_system>
         <!--Optional:-->
         <ns0:source_uid>131318</ns0:source_uid>
         <!--Optional:-->
         <ns0:request_type>getChangeRequests</ns0:request_type>
         <!--Optional:-->
         <ns0:request_payload>
            <start_date>2020-01-08T00:00:00</start_date>
            <status_list>Proposed</status_list>
            <owning_stream>IB IT</owning_stream>
            <full_details>no</full_details>
            <result_limit>100</result_limit>
         </ns0:request_payload>

      </ns0:changeOperationRequest>
   </soapenv:Body>
</soapenv:Envelope>

Возможно ли переопределить тип данных, считываемый из файла WSDL, или, альтернативно, есть ли другой способ заставить Zeep отправить поле в виде строки?

Я попытался распаковать словарь:

xml = client.service.changeOperationRequest(**request_dict)

и задать аргументы для ключевых слов и только request_payload в качестве словаря, но это приводит к той же ошибке:

xml = client.create_message(client.service, 'changeOperationRequest', source_system='Script',source_uid='131318',request_type='getChangeRequests',request_payload=dictionary)

Даже простая установка request_payload для результирующего xml не работает, так как теги xml расширяются. Хотя я бы предпочел не go идти по пути ручного создания xml, это, похоже, несколько лишает смысла использование Zeep.

xml = client.create_message(client.service, 'changeOperationRequest', source_system='EQ CAB Report Script',source_uid='131318',request_type='getChangeRequests',request_payload='<start_date>2020-01-07T00:00:00</start_date><status_list>Proposed</status_list><owning_stream>IB IT</owning_stream><full_details>no</full_details><result_limit>100</result_limit>')

XML output:

<sn0:request_payload>&lt;start_date&gt;2020-01-07T00:00:00&lt;/start_date&gt;&lt;status_list&gt;Proposed&lt;/status_list&gt;&lt;owning_stream&gt;IB IT&lt;/owning_stream&gt;&lt;full_details&gt;no&lt;/full_details&gt;&lt;result_limit&gt;100&lt;/result_limit&gt;</ubs:request_payload>

1 Ответ

0 голосов
/ 10 января 2020

Я пошел по пути отправки словаря в виде строкового типа. Чтобы не расширять экранирующие теги xml, я использовал вспомогательный модуль плагина Zeep.

Получено от: python zeep: отправлять неотбегированные xml в качестве содержимого

from zeep import Client, xsd, Plugin

class my_plugin(Plugin):

    def egress(self, envelope, http_headers, operation, binding_options):
        xmlString = ET.tostring(envelope, encoding='unicode')
        xmlString = xmlString.replace("&lt;", "<")
        xmlString = xmlString.replace("&gt;", ">")
        newenvelope = ET.XML(xmlString)
        return newenvelope, http_headers

# create the client:
client = Client(wsdl_url, transport=transport, plugins=[my_plugin()])

# call service as you would normally
client.service.changeOperationRequest()
...