Сценарий парсинга xml на основе экспатов не работает в Linux, работает в Windows - PullRequest
1 голос
/ 22 февраля 2011

Я пишу набор инструментов на python для извлечения данных из некоторых XML-файлов, которые генерируются программным обеспечением для моделирования трафика. Поскольку полученные файлы могут быть довольно большими, я использую xml.parsers.expat для их анализа.

Проблема в том, что когда я запускаю свои скрипты на работе на компьютере с Windows XP, он работает отлично, но дома, на Ubuntu 10.10, в том же файле я получаю следующую ошибку:
ExpatError: not well-formed (invalid token): line 1, column 0

Файл изначально был закодирован в utf-8, и кодировка, объявленная в теге, была ascii, поэтому попробуйте изменить его на utf-8 (или UTF8 или utf8) без успеха. Поскольку спецификация отсутствовала, я попытался написать ее, но безуспешно. Я также попытался заменить разрыв строки в Windows (CR / LF) на Unix (CR). Также без какого-либо успеха.

Также версия Python на работе - 2.7.1, на моем Ubuntu - 2.6.6, но не думаю, что моя проблема связана с тем, что: я без проблем обновил Python своего рабочего компьютера с 2.6 до 2.7 несколько недель назад .

Поскольку я здесь не эксперт, у меня заканчиваются идеи, есть подсказка?

Edit: После дальнейшего исследования (у меня сейчас болит голова, я ненавижу проблемы, связанные с Unicode), похоже, что проблема была решена путем правильной установки системных переменных среды LANG, LC_ALL и LANGUAGE в (в моем случае) "fr_FR.utf-8". Я не понимаю, почему они не были поначалу и почему сейчас, это работает ...

Благодарю вас, ребята, за руку!

Ответы [ 2 ]

3 голосов
/ 22 февраля 2011

Выдержки из документации:

xml.parsers.expat.XML_ERROR_INVALID_TOKEN
Возникает, когда входной байт не может быть правильно назначен символу;например, байт NUL (значение 0) во входном потоке UTF-8.

ExpatError.lineno
Номер строки, в которой была обнаружена ошибка.Первая строка пронумерована 1.

ExpatError.offset
Смещение символа в строке, где произошла ошибка.Первый столбец пронумерован 0.

Выше указано, что у вас есть проблема с самым первым байтом в вашем файле.

Начните с исходного файла, который работал в Windows,Отредактируйте свой вопрос, чтобы показать результаты этого:

python -c "print repr(open('win_ok_file.xml', 'rb').read(200))"

, который однозначно покажет, что находится в первых 200 байтах в вашем файле.

Также покажите нам сокращенную версиюВаш проверенный код будет работать в Windows, чтобы обойти первоначальную ошибку, но воспроизводит проблему в Linux.

Некоторые утверждения, для чего они стоят:

  • "Файл изначально был закодирован в utf-8, и кодировка, объявленная в теге, была ascii" ... Если кодировка в объявлении XML - "ascii", но в файле присутствуют символы, отличные от ASCII, то соответствующие парсеры должны вызыватьисключение.Вы уверены, что сообщаете?

  • Кодировка по умолчанию для документов XML - UTF-8.Другими словами, если кодировка не упоминается в объявлении XML или вообще отсутствует объявление XML, синтаксический анализатор должен декодировать, используя UTF-8.

  • Установка UTF-8 Спецификация в начале скорее препятствует, чем помогает.

  • Стандарт XML требует, чтобы синтаксические анализаторы принимали CR в качестве действительного байта в документе XML, а затем немедленно притворялись, что это не так.не существует (за исключением, может быть, элемента с xmlns:space="preserve").Замена CR LF на LF не очень хорошая идея.

И некоторые вопросы: Сколько байтов в «довольно большом» файле?Вы рассматривали возможность использования iterparse() из xml.etree.cElementTree или lxml?

2 голосов
/ 04 апреля 2014

У меня возникла та же проблема, и вместо того, чтобы пытаться выполнить синтаксический анализ файла следующим образом:

document = xmltodict.parse("myfile.xml") # Parse the read document string

Я проанализировал его косвенно, предварительно открыв документ xml через объект, например так:

document_file = open("myfile.xml", "r") # Open a file in read-only mode
original_doc = document_file.read() # read the file object
document = xmltodict.parse(original_doc) # Parse the read document string

и все заработало.

...