анализировать xml с помощью elementtree, пользовательской сортировки

Я хочу разобрать xml-файл в utf-8 и отсортировать его по какому-то полю. Соринг производится по пользовательскому алфавиту (s1 из исходников). История вопроса здесь: сортировка списка, содержащего символы utf-8 . Я нашел, как сортировать xml здесь. Сортировка работает корректно, проблема с elementtree, надо признать, что на python3 не работает

Вот исходный код:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#import xml.etree.ElementTree as ET   # Python 2.5
import elementtree.ElementTree as ET
s1='aáàAâÂbBcCçÇdDeéEfFgGğĞhHiİîÎíīıIjJkKlLmMnNóoOöÖpPqQrRsSşŞtTuUûúÛüÜvVwWxXyYzZ'
s2='11111122334455666aabbccddeeeeeeffgghhiijjkklllllmmnnooppqqrrsssssttuuvvwwxxyy'
trans = str.maketrans(s1, s2)
def unikey(seq):
    return seq[0].translate(trans)
tree = ET.parse("tosort.xml")
container = tree.find("entries")
data = []
for elem in container:
    keyd = elem.findtext("k")
    data.append((keyd, elem))
print (data)
data.sort(key=unikey)
print (data)
container[:] = [item[-1] for item in data]
tree.write("sorted.xml", encoding="utf-8")

Вот инструкции по импорту модуля elementtree. Когда я импортирую модуль таким образом :import xml.etree.ElementTree as ET, я получаю сообщение:

Traceback (most recent call last):
File "pcs.py", line 19, in <module>
container[:] = [item[-1] for item in data]
File "/usr/lib/python3.1/xml/etree/ElementTree.py", line 210, in __setitem__
assert iselement(element)
AssertionError

Когда я использую этот метод для импорта: import elementtree.ElementTree as ET, я получаю это сообщение:

Traceback (most recent call last):
File "pcs.py", line 4, in <module>
import elementtree.ElementTree as ET
File "/usr/local/lib/python3.1/dist-packages/elementtree/ElementTree.py", line 794, in <module>
_escape = re.compile(eval(r'u"[&<>\"\u0080-\uffff]+"'))
File "<string>", line 1
u"[&<>\"\u0080-\uffff]+"
                       ^
SyntaxError: invalid syntax

Я использую Python 3.1.3 (r313:86834, 28 ноября 2010 г., 11:28:10). В python2.6 elementtree работает без проблем.

Содержимое tosort.xml:

<xdxf>
<entries>
<ar><k>zaaaa</k>definition1</ar>
<ar><k>şaaaa</k>definition2</ar>
...
...
</entries>
</xdxf>

person microspace    schedule 21.06.2012    source источник
comment
В первом блоке кода есть проблемы с отступом внутри for. Не могли бы вы исправить это, чтобы он соответствовал фактическому коду, который вы запускаете?   -  person Lev Levitsky    schedule 22.06.2012
comment
Кроме того, я думаю, что проблема может заключаться в том, что s2 все еще содержит символы, отличные от ASCII, и они портят сортировку.   -  person Lev Levitsky    schedule 22.06.2012
comment
Ой, извини. Я исправил это. второй код с символами, отличными от ASCII, работает хорошо. Я думаю, что что-то не так с кодировкой файла inout, но я не могу понять.   -  person microspace    schedule 23.06.2012
comment
Мне удалось решить проблему сортировки. Спасибо, @Лев Левицкий. Я удалил все символы, отличные от ASCII, из строки s2.   -  person microspace    schedule 24.06.2012


Ответы (2)


Похоже, вы импортируете разные модули, один в /usr/lib/python3.1 с именем xml.etree, а другой в /usr/local/lib/python3.1/dist-packages с именем elementtree. Последнее мне кажется сломанным, что касается первого, попробуйте удалить [:] в строке

 container[:] = [item[-1] for item in data]
person Lev Levitsky    schedule 24.06.2012
comment
удаление [:] не помогло. Эта строка кода взята из example. Модуль AssertionError, похоже, работает на python2.6. Может быть, кто-нибудь подскажет, как сделать перевод моей строки в python 2.6? Спасибо! - person microspace; 24.06.2012
comment
@microspace Если не помогло, можете показать, как выглядит трассировка без [:]? - person Lev Levitsky; 24.06.2012
comment
Я отредактировал вопрос. Я сделал трассировку с помощью следующей команды print (traceback.format_exc()). Это правильно? Я никогда раньше не печатал трассировку... Без [:] сортировки данные просто не записывались в файл... - person microspace; 24.06.2012
comment
@microspace Вы сказали, что удаление [:] не помогло. С [:] в этой строке была ошибка, и интерпретатор напечатал трассировку (заканчивающуюся на AsertionError). Что произойдет, если вы удалите [:]? Вам не нужно печатать трассировку вручную. - person Lev Levitsky; 24.06.2012
comment
без [:] программа завершилась без ошибок, сортировка прошла, но в выходной файл были записаны несортированные данные. - person microspace; 24.06.2012
comment
@microspace Это потому, что ваш код ничего не изменил в tree. - person Lev Levitsky; 24.06.2012
comment
на самом деле я не очень понимаю, как работает код управления деревом с effbot.com (я просто добавил к нему функцию сортировки), но код работал с python2.6. Действительно решение вопроса найдено, спасибо за помощь, @Lev Levitsky. Я пойду изучать, как работает elementtree. )) - person microspace; 24.06.2012
comment
@microspace Хорошо, [:] был важен для работы этого кода (с ним вы, по-видимому, должны изменить дерево, хотя мне это кажется странным). Теперь вы создаете новый список, поэтому с tree ничего не происходит. Однако в Python3 элементы, возвращаемые find, каким-то образом не проходят утверждение iselement, я точно не знаю, почему. - person Lev Levitsky; 24.06.2012

Не бейте меня сильно, но вот мой вариант решения:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import xml.etree.ElementTree as ET # Python 2.5
from xml.etree.ElementTree import Element
s1="áàaAâÂbBcCçÇdDeéEfFgGğĞhHiİîÎíīıIjJkKlLmMnNóoOöÖpPqQrRsSşŞtTuUûúÛüÜvVwWxXyYzZ"
s2="AAAAAABBCCCCDDEEEFFGGHHddeeeeeeffgghhiijjkklllllmmnnooppqqrrsssssttuuvvwwxxyy"
trans = str.maketrans(s1, s2)
def unikey(seq):
    return seq[0].translate(trans)
tree = ET.parse("tosort.xml")
container = tree.find("entries")
data = []
for elem in container:
    keyd = elem.findtext("k")
    data.append([keyd, elem])
data.sort(key=unikey)
root = tree.getroot()
i=0
for item in data:
    root.append(data[i][1]) # appends sorted Element objects to tree
    i=i+1
#container = [item[-1] for item in data]
root.remove(tree.find("entries")) # removes unsorted Element objects
tree.write("sorted.xml", encoding="utf-8")

Решение немного уродливое, но оно работает... Я не знаю, сколько времени потребуется, чтобы отсортировать ~ 50 МБ данных xml, но в моем случае время не имеет значения. Также я немного изменил шаблон сортировки, потому что он сортировался неправильно, если в словах были числа. На Acer extensa 5210 сортировка заняла не более 2 мин.

person microspace    schedule 26.06.2012