Загрузка разных типов данных из XML в словарь в Python - PullRequest
2 голосов
/ 12 января 2012

Я использую cElementTree для извлечения тегов и значений XML в цикле, а затем сохраняю их в словарь.

Файл XML содержит:

<root>
    <tag1>['item1', 'item2']</tag1>
    <tag2>a normal string</tag2>
</root>

Код Python (примерно):

import xml.etree.cElementTree as xml

xmldata = {}
xmlfile = xml.parse(XMLFile.xml)
for xmltag in xmlfile.iter():
    xmldata[xmltag.tag] = xmltag.text

Проблема, с которой я столкнулся, состоит в том, что файл xml содержит разные типы данных, включая string и list.К сожалению, Element.text сохраняет все значения XML как string (включая списки).

Поэтому, когда я загружаю из файла XML, у меня есть:

{'tag1':"['item1', 'item2']", 'tag2':'a normal string'}

Когда я предпочитаюиметь:

{'tag1':['item1', 'item2'], 'tag2':'a normal string'}

Есть ли простой способ сделать это?
например, команда, которая сохраняет в словарь в исходном формате

Или мне нужно настроить, еслиинструкции для определения типа значения и его отдельного сохранения с использованием альтернативы Element.text?

Ответы [ 3 ]

1 голос
/ 12 января 2012

Вы можете использовать literal_eval, чтобы попытаться проанализировать сложные литералы Python.Поскольку ваши стриги без кавычек, они вызовут SyntaxError в lteral eval, но это просто для обхода:

import xml.etree.cElementTree as xml
from ast import literal_eval

xmldata = {}
xmlfile = xml.parse(XMLFile.xml)
for xmltag in xmlfile.iter():
    try:
        xmldata[xmltag.tag] = literal_eval(xmltag.text)
    except SyntaxError:
        xmldata[xmltag.tag] = xmltag.text

В отличие от встроенного в Python «eval», ast.literal_eval не позволяет выполнять выраженияи, следовательно, является безопасным, даже если данные XML поступают из ненадежного источника.

1 голос
/ 12 января 2012

Я думаю, что вы не используете xml во всей его могущественной силе!

Почему бы вам не организовать .xml вроде:

<root>
    <tag1>
        <item>item1</item>
        <item>item2</item>
    </tag1>
    <tag2>a normal string<tag2>
</root>

Таким образом, ваш код Python будет обрабатывать каждый <tag1> как контейнер <item>, и я думаю, что лучше.

Примечание: Вы также можете посмотреть здесь . (Согласен с «Любимым путем» автора)

1 голос
/ 12 января 2012

Вот предлагаемое решение: проверьте наличие [, затем проанализируйте список.Это не отказоустойчиво (не будет работать, если разделитель не будет точно , с пробелом), но я думаю, что вам будет легко его улучшить.

import xml.etree.cElementTree as xml

xmldata = {}
xmlfile = xml.parse("data.xml")
for xmltag in xmlfile.iter():
    # it's a list
    if "[" in xmltag.text:
        d = xmltag.text.lstrip("[").rstrip("]")
        l = [item.lstrip("'").rstrip("'") for item in d.split(", ")]
        xmldata[xmltag.tag] = l
    else:
        xmldata[xmltag.tag] = xmltag.text

print xmldata

Печать: {'root': '\n', 'tag1': ['item1', 'item2'], 'tag2': 'a normal string'}

...