Уведомления

Группа в Telegram: @pythonsu

#1 Май 6, 2013 14:38:26

agaspher
Зарегистрирован: 2013-03-21
Сообщения: 19
Репутация: +  0  -
Профиль   Отправить e-mail  

Парсинг xml с кириллическими тегами

Приветствую всех

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

использую python 2.7 и lxml 3.2.0x32

Офлайн

#2 Май 6, 2013 19:25:41

wiygn
Зарегистрирован: 2012-08-19
Сообщения: 52
Репутация: +  2  -
Профиль   Отправить e-mail  

Парсинг xml с кириллическими тегами

В какой кодировке файл? Насколько я знаю, lxml с кириллицей в юникоде проблем не испытывает.

Офлайн

#3 Май 6, 2013 20:05:58

agaspher
Зарегистрирован: 2013-03-21
Сообщения: 19
Репутация: +  0  -
Профиль   Отправить e-mail  

Парсинг xml с кириллическими тегами

кодировка win-1251,
а lxml просит unicode либо ascii

Офлайн

#4 Май 6, 2013 21:33:25

reclosedev
От: Н.Новгород
Зарегистрирован: 2012-03-29
Сообщения: 870
Репутация: +  173  -
Профиль   Отправить e-mail  

Парсинг xml с кириллическими тегами

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'))

Офлайн

#5 Май 7, 2013 13:39:53

agaspher
Зарегистрирован: 2013-03-21
Сообщения: 19
Репутация: +  0  -
Профиль   Отправить e-mail  

Парсинг xml с кириллическими тегами

После кучи скуренных манов и одного кальяна, выяснил следующее:
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')

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

Всем спасибо!

Отредактировано agaspher (Май 7, 2013 13:42:01)

Офлайн

#6 Май 10, 2013 05:18:40

wiygn
Зарегистрирован: 2012-08-19
Сообщения: 52
Репутация: +  2  -
Профиль   Отправить e-mail  

Парсинг xml с кириллическими тегами

Простите, конечно, но разве в unicode не удобнее оставлять? Смысл обратно энкодить?

Офлайн

#7 Май 20, 2013 16:38:49

agaspher
Зарегистрирован: 2013-03-21
Сообщения: 19
Репутация: +  0  -
Профиль   Отправить e-mail  

Парсинг xml с кириллическими тегами

энкодить или нет, как я понял, зависит от того, куда выводим, в консоль винды, например, вывод без encode часто спотыкается на ошибке типа:

UnicodeEncodeError: ‘charmap’ codec can't encode
с encode все гладко

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version