2016-11-14 2 views
0

Я разбираю XML-набор данных и сохраняю его в базе данных mysql для дальнейшей обработки с использованием модуля xml.etree в python. Существует один узел с переменным числом дочерних узлов. Например, позволяет сказать:Python: как анализировать XML с динамическим числом дочерних узлов?

<cars> 
    <car type="A" value=35 /> 
    <car type="B" value=42 /> 
    <car type="C" value=55 /> 
    <car type="D" value=23 /> 
</cars> 

Таким образом, в этом примере число car узлов будет варьироваться в каждом документе. Я знаю, что может быть максимум A - H, поэтому я создал столбцы из car_A в car_H в моей базе данных. Я обычно делаю петлю, как это, чтобы получить атрибут value для каждого автомобиля:

for car in root.findall("cars/car"): 
    if car.get("type") == "A": 
     car_A = car.get("value") 
    elif car.get("type") == "B": 
     car_B = car.get("value") 
    ... 

Но это выглядит немного неэффективно, и мне также нужно сделать типы автомобилей нет, как автомобиль type=E быть пустым. Как мне это сделать без использования всех операторов if..elif и сделать их более обобщаемыми и эффективными? Могут быть и другие такие узлы с гораздо большим количеством дочерних узлов, поэтому вручную писать if...elif не представляется возможным.

ответ

0

Я не использовал xml.etree, но это довольно просто, если вы используете BeautifulSoup

markup = '<cars><car type="A" value=35 /><car type="B" value=42 /><car type="C" value=55 /><car type="D" value=23 /></cars>' 
from bs4 import BeautifulSoup 
soup = BeautifulSoup(markup, 'lxml') 
car_dict = {'car_'+car.get('type'): car.get('value') for car in soup.find('cars').findAll('car')} 

Вот как dict выглядит следующим образом:

print car_dict 
4: {'car_A': '35', 'car_B': '42', 'car_C': '55', 'car_D': '23'} 

Я использую [BeautifulSoup][1] и служит лучшим для который он построил! + документация обширна!

Edit: Если вы хотите с помощью xml.etree только я предлагаю вам использовать аналогичный подход, т.е. с использованием словаря:

car_dict = {} 
for car in root.findall("cars/car"): 
    car_dict.update({'car_'+car.get("type"): car.get("value")}) 

или если вы хотите, чтобы обновить локальные переменные вместо создания отдельного словаря, попробуйте это (я предполагаю, что это именно то, что вы хотели в первую очередь):

car_dict = {} 
for car in root.findall("cars/car"): 
    locals().update({'car_'+car.get("type"): car.get("value")}) 
0

Может быть, вы хотели бы хранить все данные в Словаре, используя child.attrib метод?

xml_str = ''' 
<cars> 
    <car type="A" value="32"/> 
    <car type="B" value="42"/> 
    <car type="C" value="55"/> 
    <car type="D" value="23"/> 
</cars> 
''' 

import xml.etree.ElementTree as ET 
root = ET.fromstring(xml_str) 

cars = {} 
for child in root: 
    cars[child.attrib['type']] = child.attrib['value'] 

Выход { 'A': 32, 'B': 42, 'C': 55, 'D': 23 }

Тогда вы можете просто обработать Dict, что может быть проще

0
cars={} 
for car in root.findall("cars/car"): 
    car_type="car_"+car.get("type") 
    cars[car_type]=car.get("value") 

также, если у вас есть предопределенные переменные, которые используют их в других местах (в коде), вы можете использовать эту строку для преобразования переменных (или перезаписи значений) со словарных клавиш:

locals().update(cars)

затем

car_A 

является переменной, если не указано ранее (или имеет новое значение, если определено).

Смежные вопросы