Найти - Пользователи
Полная версия: Парсинг xml с кириллическими тегами
Начало » Python для новичков » Парсинг xml с кириллическими тегами
1
agaspher
Приветствую всех

Сталкивался кто-нибудь с парсингом xml с тегами, написанными кириллицей?
Почитал у php-шников (по скольку о python'е вообще ни слова не нашел), тоже проблемы, делают подобное только через различные костыли. Может кто предложит человеческий способ работы с подобными файлами, пока в голову приходит только создавать словарь соответствия тэгов и прогонять файл через замену на латиницу, но изменять исходный файл не хотелось бы.

использую python 2.7 и lxml 3.2.0x32
wiygn
В какой кодировке файл? Насколько я знаю, lxml с кириллицей в юникоде проблем не испытывает.
agaspher
кодировка win-1251,
а lxml просит unicode либо ascii
reclosedev
agaspher
а lxml просит unicode либо ascii
Не ascii.

Если переданы байты (не Юникод) и нет объявления XML с указанием кодировки
<?xml version="1.0" encoding="cp1251"?>
он считает, что кодировка utf-8. Если кодировка указана, то он считывает в этой кодировке.

Если передается Юникод, и нет объявления, все хорошо, если есть объявление
ValueError: Unicode strings with encoding declaration are not supported.

Получается несколько вариантов. Если нет объявления можно передавать Юникод, декодировав файл самому
import codecs
with codecs.open(filename, encoding='cp1251') as f:
    ...
или передавать байты, но добавить объявление с кодировкой.


from lxml import etree
 
def do_test(text):
    doc = etree.fromstring(text)
    assert doc[0].tag == u'тест2'
 
do_test(u'<тест><тест2></тест2></тест>')
do_test(u'<?xml version="1.0" encoding="cp1251"?><тест><тест2></тест2></тест>'.encode('cp1251'))

agaspher
После кучи скуренных манов и одного кальяна, выяснил следующее:
1. unicode это не utf-8
2. всегда делать на входе явный decode данных в тип unicode
3. в программе работать с типом unicode, и только потом… 4
4. на выходе делать encode в необходимую кодировку

микро кусочек того, что получилось:
файл r2.xml
<?xml version=“1.0” encoding=“windows-1251”?>
<Файл xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance“ xmlns:xsd=”http://www.w3.org/2001/XMLSchema“>
<ФормаОтч>
<Первичная />
</ФормаОтч>
<Справочники>
<ПроизводителиИмпортеры П000000000004=”&quot;ЗАО &quot;Роом&quot;&quot;" />
</Справочники>
</Файл>

declar.py
from lxml import etree
parser = etree.XMLParser(encoding='cp1251')
tree = etree.parse('r2.xml', parser)
nodes = tree.xpath(u'/Файл/Справочники/ПроизводителиИмпортеры')
for node in nodes:
    t = node.get(u'П000000000004')
    print t.encode('cp1251')

на выходе:
“ЗАО ”Роом“”

Всем спасибо!
wiygn
Простите, конечно, но разве в unicode не удобнее оставлять? Смысл обратно энкодить?
agaspher
энкодить или нет, как я понял, зависит от того, куда выводим, в консоль винды, например, вывод без encode часто спотыкается на ошибке типа:
UnicodeEncodeError: ‘charmap’ codec can't encode
с encode все гладко
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB