Ну, map()
всегда будет возвращать список, поэтому простой ответ - "не использовать map()
".Вместо этого создайте словарь, как вы уже делаете, зациклившись на children
и присвоив результат xml_to_dict(child)
ключу словаря, который вы хотите использовать.Похоже, что вы хотите использовать тег в качестве ключа и иметь значение в виде списка элементов с этим тегом, поэтому он будет выглядеть примерно так:
import collections
from lxml import etree
tree = etree.parse('file.xml')
root = tree.getroot()
def xml_to_dict(el):
d={}
if el.text:
print '***write tag as string'
d[el.tag] = el.text
child_dicts = collections.defaultdict(list)
for child in el.getchildren():
child_dicts[child.tag].append(xml_to_dict(child))
if child_dicts:
d[el.tag] = child_dicts
return d
xml_to_dict(root)
Это оставляет запись тега в dict какдефолтный приговор;если по какой-то причине вам нужен нормальный dict, используйте d[el.tag] = dict(child_dicts)
.Обратите внимание, что, как и раньше, если у тега есть и текст, и дочерние элементы, текст не будет отображаться в dict.Возможно, вы захотите придумать другой макет, чтобы ваш диктант справился с этим.
РЕДАКТИРОВАТЬ:
Код, который будет выводить результат в вашем перефразированном вопросе, не будетrecurse in xml_to_dict
- потому что вам нужен только dict для внешнего элемента, а не для всех дочерних тегов.Таким образом, вы бы использовали что-то вроде:
import collections
from lxml import etree
tree = etree.parse('file.xml')
root = tree.getroot()
def xml_to_item(el):
if el.text:
print '***write tag as string'
item = el.text
child_dicts = collections.defaultdict(list)
for child in el.getchildren():
child_dicts[child.tag].append(xml_to_item(child))
return dict(child_dicts) or item
def xml_to_dict(el):
return {el.tag: xml_to_item(el)}
print xml_to_dict(root)
Это все еще не обрабатывает тэги как с текстом, так и с дочерями разумно, и это превращает collections.defaultdict(list)
в нормальный dict, так что вывод (почти)как вы ожидаете:
***write tag as string
***write tag as string
***write tag as string
***write tag as string
***write tag as string
***write tag as string
{'root': {'a': ['1', {'b': ['2', '2']}], 'aa': ['1a']}}
(Если вам действительно нужны целые числа вместо строк для текстовых данных в тегах b
, вам придется каким-то образом явно превратить их в целые числа.)