Альтернативный синтаксический анализатор XML для ElementTree для упрощения горя UTF-8?

Jon Skeet корректен. Вот страница Nul Device Driver в документации Windows Embedded (я понятия не имею, почему это не где-то в другом месте...).

Вот другой:

9
задан Kekoa 16 July 2009 в 17:47
поделиться

4 ответа

Я начну с вопроса: «Могу ли я использовать альтернативный синтаксический анализатор, который может быть менее строгим и допускать символы utf-8?»

Все синтаксические анализаторы XML будут принимать данные в кодировке UTF-8. Фактически, UTF-8 является кодировкой по умолчанию.

XML-документ может начинаться с объявления, подобного этому:

`<?xml version="1.0" encoding="UTF-8"?>`

или подобного этому: или вообще не иметь декларации ... в каждом случае синтаксический анализатор будет декодировать документ с использованием UTF-8.

Однако ваши данные НЕ закодированы в UTF-8 ... это, вероятно, Windows-1252, также известный как cp1252.

Если кодировка не UTF-8, то либо создатель должен включить объявление (или получатель может добавить его), либо получатель может перекодировать данные в UTF-8. Ниже показано, что работает, а что нет:

>>> import xml.etree.ElementTree as ET
>>> from StringIO import StringIO as sio

>>> raw_text = '<root>can\x92t</root>' # text encoded in cp1252, no XML declaration

>>> t = ET.parse(sio(raw_text))
[tracebacks omitted]
xml.parsers.expat.ExpatError: not well-formed (invalid token): line 1, column 9
# parser is expecting UTF-8

>>> t = ET.parse(sio('<?xml version="1.0" encoding="UTF-8"?>' + raw_text))
xml.parsers.expat.ExpatError: not well-formed (invalid token): line 1, column 47
# parser is expecting UTF-8 again

>>> t = ET.parse(sio('<?xml version="1.0" encoding="cp1252"?>' + raw_text))
>>> t.getroot().text
u'can\u2019t'
# parser was told to expect cp1252; it works

>>> import unicodedata
>>> unicodedata.name(u'\u2019')
'RIGHT SINGLE QUOTATION MARK'
# not quite an apostrophe, but better than an exception

>>> fixed_text = raw_text.decode('cp1252').encode('utf8')
# alternative: we transcode the data to UTF-8

>>> t = ET.parse(sio(fixed_text))
>>> t.getroot().text
u'can\u2019t'
# UTF-8 is the default; no declaration needed
15
ответ дан 4 December 2019 в 10:05
поделиться

Байт 0x92 никогда не может быть первым байтом символа UTF-8. Однако он может быть действительным как следующий байт. См. это руководство по UTF-8 для получения таблицы допустимых последовательностей байтов.

Не могли бы вы дать нам представление о том, какие байты окружают 0x92? Включает ли объявление XML кодировку символов?

1
ответ дан 4 December 2019 в 10:05
поделиться

А. Очевидно, что это «не может», и действительно, 0x92 является апострофом во многих кодовых страницах Windows. Вместо этого ваш редактор предполагает, что это файл Mac. ;)

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

Я также рекомендую lxml как XML. библиотека на Python, но проблема не в этом.

1
ответ дан 4 December 2019 в 10:05
поделиться

Похоже, у вас есть текст CP1252. Если это так, это должно быть указано в верхней части файла, например :

<?xml version="1.0" encoding="CP1252" ?>

Это работает с ElementTree.

Если вы создаете эти файлы самостоятельно, не записывайте их в этой кодировке. Сохраните их как UTF-8 и внесите свой вклад в уничтожение устаревших текстовых кодировок.

Если вы получаете данные CP1252 без спецификации кодировки, и вы точно знаете, что это всегда будет CP1252, вы можете просто преобразовать их в UTF-8 перед отправкой парсеру:

s.decode("CP1252").encode("UTF-8")
4
ответ дан 4 December 2019 в 10:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: