Должен ли я удалить объявление XML из вывода suds перед анализом с помощью lxml? - PullRequest
2 голосов
/ 17 марта 2010

Я пытаюсь реализовать веб-сервис SOAP в Python 2.6 с использованием библиотеки suds . Это работает хорошо, но я столкнулся с проблемой при попытке проанализировать вывод с lxml .

Suds возвращает объект suds.sax.text.Text с ответом от службы SOAP. Класс suds.sax.text.Text является подклассом встроенного в Python класса Unicode . По сути, это было бы сравнимо с этим утверждением Python:

u'<?xml version="1.0" encoding="utf-8" ?><root><lotsofelements \></root>'

Что неуместно, поскольку, если декларация XML верна, содержимое кодируется в UTF-8, и, таким образом, не объект Python Unicode (потому что они хранятся в некоторой внутренней кодировке, такой как UCS4).

lxml откажется анализировать это, как задокументировано , поскольку нет четкого ответа на то, какую кодировку следует интерпретировать как.

На мой взгляд, есть два выхода из этой привязки:

  1. Снять декларацию <?xml>, включая кодировку.
  2. Преобразовать выходные данные из Suds в строку байтов, используя указанную кодировку.

В настоящее время данные, которые я получаю от веб-сервиса, находятся в пределах ASCII-диапазона, так что любой из этих способов будет работать, но оба эти варианта кажутся мне ужасными, и я не совсем уверен, что произойдет, если Я начинаю получать данные, для которых требуется более широкий диапазон символов Юникода.

Есть хорошие идеи? Я не могу себе представить, что я первый в этой позиции ...

Ответы [ 2 ]

2 голосов
/ 17 марта 2010

Вы и lxml правы;действительный документ XML должен быть потоком байтов, закодированных как объявлено в заголовке <?xml ..... (по умолчанию: UTF-8).

Я бы предложил третий вариант: оставить его в Unicode с заголовком XMLпропускает объявление кодировки, но оставляет версию там (будущая безопасность).Это сделает lxml счастливым и позволит вам не тратить время на его повторное кодирование.

Я бы также посоветовал провести небольшой опрос на сайте suds и покопаться в их источнике.

1 голос
/ 17 марта 2010

Хм, в настоящее время я внедряю свое первое решение на основе Suds и анализирую свои ответы с помощью lxml без проблем, но я думаю, что это может быть потому, что я делаю это довольно тупым и тупым способом. Вот как выглядит мой код:

try:
    result = self.client.service.ExportOwnersDetails(fAccess=self.access_id, fParams=params)
except URLError:
    # TODO: Log timeout here, handle
    return
response = str(result.fReturn)

if len(response) == 0 or response.find('<?xml ') == -1:
    # TODO: Log import error here, handle
    return
response = StringIO(response)
xml = etree.parse(response)

Как я уже сказал, не очень умный (и, очевидно, у меня еще есть какие-то записи), но это мой подход. Ерунда fAccess, fParams, fReturn - это соглашение об именах стороннего провайдера, с которым я интегрируюсь.

...