Преобразование данных XML с использованием Python - PullRequest
0 голосов
/ 13 марта 2012

У меня большие данные xml.Формат задан следующим образом:

  <person>
        <name>Tom</name>
        <age>18</age>
        <address> London, xxx street, xxx building</address>
  </person>
  <person>
        <name>John</name>
        <age>22</age>
        <address> Canberra, xxx street, xxx building, xxx floor, xxx room,
                 xxx  bed</address>
  </person>

будьте осторожны с адресом!

Я хочу получить следующий результат:

  Tom^18^London, xxx street, xxx building
  John^22^Canberra, xxx street, xxx building, xxx floor, xxx room,xxx  bed

Данные довольно большие, и я надеюсь, что я могу читать построчно, поэтому не будет проблемы с памятью.Спасибо.

Ответы [ 4 ]

6 голосов
/ 13 марта 2012

Не мучайте себя, анализируя строки, если есть доступная библиотека xml - lxml , например.Если вы хотите придерживаться батарей в питоне , то взгляните на dom.minidom .

2 голосов
/ 13 марта 2012

Прежде всего, ваш xml недействителен:

  • \ (обратная косая черта) в тегах xml
  • <person> теги не закрыты

После устранения вышеуказанных проблем.
Ваша проблема может быть решена с помощью xpath, предоставляемого модулем lxml.
Кстати, есть инструмент командной строки, который называется xmlstarlet:

$ xmlstarlet sel -t -m '//person' -v 'normalize-space(concat(name, "^", age, "^", address))' -n input.xml
Tom^18^ London, xxx street, xxx building
John^22^ Canberra, xxx street, xxx building, xxx floor, xxx room, xxx bed
1 голос
/ 13 марта 2012

Убедитесь, что ввод является правильно сформированным xml.

Для обработки большого XML-файла с ограниченной памятью вы можете использовать ElementTree.iterparse():

#!/usr/bin/env python
import xml.etree.cElementTree as etree

def getelements(source, tag):
    context = iter(etree.iterparse(source, events=('start', 'end')))
    _, root = next(context) # get root element
    for event, elem in context:
        if event == 'end' and elem.tag == tag:
            yield elem
            root.clear() # free memory

for elem in getelements('big.xml', 'person'):
    print '^'.join(elem.find(tag).text for tag in 'name age address'.split())

Вы можете добавить специальную обработку для многострочного текста внутри тега (как в вашем примере для address), например, вы можете использовать re.sub(r'\s+', ' ', text) для нормализации пробелов.

выход

Tom^18^London, xxx street, xxx building
John^22^Canberra, xxx street, xxx building, xxx floor, xxx room, xxx bed

Если входной xml может содержать '^', и вы хотите его избежать, тогда вы можете использовать csv module для вывода.

0 голосов
/ 13 марта 2012

Проверка Красивый суп , я всегда использую его для xml и html (хотя это немного медленно)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...