Как удалить обязательное поле wsdl, если оно пусто в Zeep - PullRequest
0 голосов
/ 15 января 2019

Я использую zeep для обработки некоторых запросов SOAP в Python, и я столкнулся с ситуацией, для которой я не смог найти никакой документации (ни здесь, ни на SO, ни на их официальные документы ).

Сначала я создал factory:

factory = client.type_factory('ns0')

Некоторые атрибуты этого factory выглядят так:

In [76]: factory.IctAdditionalInfos()
Out[76]: 
{
    'item': []
}

Внутри item У меня могут быть следующие данные:

In [79]: factory.IctAdditionalInfos(item={})
Out[79]: 
{
    'item': {
        'PersonId': None,
        'PersonIdExt': None,
        'Sex': None,
        'FirstName': None,
        'LastName': None,
        'Telephone': None,
        'MobilePhone': None,
        'Fax': None,
        'Email': None
    }
}

Теперь, что я хочу, и я не мог разобраться, это:

  • при попытке построить и вернуть XML вместо отправки его на сервер с помощью

    client.create_message(service, wsdl_interface_name, **self.data)

(self.data содержит IctAdditionalInfos) и когда factory.IctAdditionalInfos не содержит никаких данных в item, я хотел бы получить:

<IctAdditionalInfos></IctAdditionalInfos>

или

<IctAdditionalInfos/>

Вместо вышеупомянутого я получаю:

<IctAdditionalInfos>
    <item/>
</IctAdditionalInfos>

потому что item является обязательным.

Определение wsdl IctIncidentAdditionalInfos выглядит следующим образом:

<xsd:complexType name="IctIncidentAdditionalInfos">
  <xsd:sequence>
    <xsd:element name="item" type="IctIncidentAdditionalInfo" minOccurs="0" maxOccurs="unbounded"/>
  </xsd:sequence>
</xsd:complexType>

Как мне добиться этого, используя zeep?

1 Ответ

0 голосов
/ 15 января 2019

Если ответ службы всегда возвращает обязательный тег <item/>, вы можете передать ответ в качестве аргумента функции, которая удаляет пустой тег <item/> и возвращает желаемый xml. Здесь вы не можете ничего сделать с Zeep, поскольку их API не предоставляет никаких функций для изменения ответа.

Лучший способ достичь вышеуказанного - создать две функции. Первый возвращает строку xml из сообщения, а второй сканирует эту строку на наличие пустых тегов <item/>. Если последний находит пустые теги, он изменяет строку так, как требуется, иначе возвращает ту же самую строку XML снова. Я использовал библиотеку lxml для анализа xml.

import lxml.etree as et

#retrieve xml string
def create_message():
    #your code here#
    node = client.create_message(service, wsdl_interface_name, **self.data)     
    return node

#resolve empty <item/> xml tags
def resolve_empty_xml_tag(xml_string):   
    tree = et.fromstring(xml_string)
    #traverse DOM for <item/> tag
    for elem in tree.xpath("//item"):
        #check for empty tag
        if elem.text is None:
            elem.getparent().remove(elem)
            new_xml = et.tostring(tree, pretty_print=True,encoding='unicode')
            new_xml_splitted = new_xml.split('\n')
            final_xml = [i.strip(' ') for i in new_xml_splitted if i is not '']
            return ''.join(final_xml)
    xml_string = et.tostring(tree, pretty_print=True,encoding='unicode')
    return xml_string

#function calls
node = create_message()
resolved_xml_string = resolve_empty_xml_tag(node)

#print to verify xml string
print(resolved_xml_string)

Когда я передаю строку xml с пустым тегом <item/> в функцию resolve_empty_xml_tag(xml_string), я получаю желаемый результат:

xml = """<IctAdditionalInfos>
         <item/>
    </IctAdditionalInfos>"""
print(resolve_empty_xml_tag(xml))

#Output
<IctAdditionalInfos></IctAdditionalInfos>

Когда я передаю строку XML с тегом <item/>, который содержит некоторые данные, я получаю ту же строку XML:

xml = """<IctAdditionalInfos>
           <item>abc</item>
         </IctAdditionalInfos>"""
print(resolve_empty_xml_tag(xml))

#Output
<IctAdditionalInfos>
   <item>abc</item>
 </IctAdditionalInfos>
...