Есть ли простой способ преобразовать формат xml в csv с помощью python?
У меня есть приведенный ниже xml, который я хотел бы преобразовать в csv (разделитель, например '|' или восьмеричный), используя python. Я попытался преобразовать xml в dict, а затем в csv. Я ищу, есть ли какие-нибудь простые или эффективные методы для этого.
Проблемы с приведенным ниже кодом:
- Есть тег xyz, который не нужен в csv, так как его избежать или проигнорировать? Все, что мне нужно, это данные из тега abc.
- Хотел бы, чтобы вложенный тег был префиксом для базовых ключей
- Ожидаемый результат - это строка с ключами в качестве заголовка и значениями под ним.
Пример XML:
<?xml version="1.0" encoding="utf-8"?>
<xyz date="2019-07-01T09:00:29">
<abc>
<id>23</id>
<uniqueid>23_0</uniqueid>
<Name></Name>
<Rate>
<mrp>6.40000</mrp>
<discount>10.00%</discount>
<discountmonths>2</discountmonths>
</Rate>
<fee>
<type>off</type>
<minimumfee>£1,500.75</minimumfee>
<maxfee>£10K</maxfee>
</fee>
</abc>
<abc>
<id>35</id>
<uniqueid>35_0</uniqueid>
<Name></Name>
<Rate>
<mrp>7.90000</mrp>
<discount>5.00%</discount>
<discountmonths>5</discountmonths>
</Rate>
<fee>
<type>offer</type>
<minimumfee>£1k</minimumfee>
<maxfee>£22,000</maxfee>
</fee>
</abc>
</xyz>
Код: (не обращайте внимания на незрелость кода, просто новичок, в основном копирую пасту с нескольких сайтов... пытаясь понять, работает ли это, а потом подумал, что буду знать, с чего начать или изменить существующий)
import xml.etree.ElementTree as ET
import xmltodict
import csv
tree = ET.parse('myxml_1.xml')
xml_data = tree.getroot()
xmlstr = ET.tostring(xml_data, encoding='utf-8', method='xml')
data_dict = dict(xmltodict.parse(xmlstr))
with open('test1.csv','w') as f:
w = csv.writer(f)
w.writerow(data_dict.keys())
w.writerow(data_dict.values())
ожидаемый результат:
id|uniqueid|Name|rate_mrp|rate_discount|rate_discountmonths|fee_type|fee_minimumfee|fee_maxfee
23|23_0||6.40000|10.00%|2|off|£1,500.75|£10K
35|35_0||7.90000|5.00%|5|offer|£1k|£22,000
1 ответ
Я бы сделал это очень явным образом, вместо того, чтобы пытаться взломать xmltodict
чтобы соответствовать вашим потребностям.
Единственный недостаток этого подхода, который я вижу, - это небольшое повторение жестко запрограммированных заголовков и имен тегов.
Кроме того, я не знаю, насколько регулярным будет ваш ввод XML. Если возможно, что некоторые из тегов не будут присутствовать, вам нужно будет добавить некоторую обработку ошибок (потому чтоnode.find
вернусь None
, тогда .text
вызовет AttributeError
).
rows = []
for abc_node in tree.findall('abc'):
rate_node = abc_node.find('Rate')
fee_node = abc_node.find('fee')
row = {'id': abc_node.find('id').text,
'uniqueid': abc_node.find('uniqueid').text,
'Name': abc_node.find('Name').text,
'rate_mrp': rate_node.find('mrp').text,
'rate_discount': rate_node.find('discount').text,
'rate_discountmonths': rate_node.find('discountmonths').text,
'fee_type': fee_node.find('type').text,
'fee_minimumfee': fee_node.find('minimumfee').text,
'fee_maxfee': fee_node.find('maxfee').text}
rows.append(row)
with open('test.csv', 'w', encoding='utf8') as f:
headers = ['id', 'uniqueid', 'Name', 'rate_mrp', 'rate_discount', 'rate_discountmonths',
'fee_type', 'fee_minimumfee', 'fee_maxfee']
dict_writer = csv.DictWriter(f, fieldnames=headers, lineterminator='\n')
dict_writer.writeheader()
dict_writer.writerows(rows)
Выход
id,uniqueid,Name,rate_mrp,rate_discount,rate_discountmonths,fee_type,fee_minimumfee,fee_maxfee
23,23_0,,6.40000,10.00%,2,off,"£1,500.75",£10K
35,35_0,,7.90000,5.00%,5,offer,£1k,"£22,000"
Если ты хочешь |
в качестве разделителя просто добавьте delimiter='|'
к csv.DictWriter(f, fieldnames=headers, lineterminator='\n')
тогда вывод
id|uniqueid|Name|rate_mrp|rate_discount|rate_discountmonths|fee_type|fee_minimumfee|fee_maxfee
23|23_0||6.40000|10.00%|2|off|£1,500.75|£10K
35|35_0||7.90000|5.00%|5|offer|£1k|£22,000