如何读取XML文件并转换为DataFrame表格?新手求助
XML转Pandas DataFrame实现方案
首次接触XML文件,需要读取指定结构的XML并转换为常规DataFrame表格,尝试了两种方法均未成功,现寻求解决办法。
目标XML结构
<?xml version="1.0" encoding='UTF-8'?> <LucroCliente xmlns:my='http://www.ms.com/pace' xmlns='http://www.ms.com/pace' Cab_Usuario='UsuI' Cab_DadosEmpresa='' Cab_RazaoEmpresa='CoLtda.' Cab_Aplicativo='Comercial' Cab_Data='25/07/2022 14:40:38' Cab_Titulo='Relatório Cab_Titulo' Selecao='Selecao' Periodo='Período: 01/01/2020 - 31/12/2020'> <Filial Filial=''> <Linha TotalLinha='TOA 21: 2.313.292,43'> <Produto Coluna1='21-851611' Coluna2='CAMIO VO' Coluna3='' Coluna4='' Coluna5=''> <AnaliseDiaria Coluna6='' Coluna7='' Coluna8='' Coluna9='' Coluna10='' Coluna11='' Coluna12='' Coluna13='' Coluna14='' Coluna15='' Coluna16=''/> </Produto> <Produto Coluna1='21-3667984' Coluna2='SCA4X2' Coluna3='-1' Coluna4='' Coluna5=''> <AnaliseDiaria Coluna6='' Coluna7='' Coluna8='' Coluna9='' Coluna10='' Coluna11='' Coluna12='' Coluna13='' Coluna14='' Coluna15='' Coluna16=''/> </Produto> <Produto Coluna1='21-3667994' Coluna2='SCA963' Coluna3='-1' Coluna4='' Coluna5=''> <AnaliseDiaria Coluna6='' Coluna7='' Coluna8='' Coluna9='' Coluna10='' Coluna11='' Coluna12='' Coluna13='' Coluna14='' Coluna15='' Coluna16=''/> </Produto> <Produto Coluna1='21-3676543' Coluna2='SCA713' Coluna3='-1' Coluna4='' Coluna5=''> <AnaliseDiaria Coluna6='' Coluna7='' Coluna8='' Coluna9='' Coluna10='' Coluna11='' Coluna12='' Coluna13='' Coluna14='' Coluna15='' Coluna16=''/> </Produto> <Produto Coluna1='21-3676601' Coluna2='SCA97' Coluna3='-1' Coluna4='' Coluna5=''> <AnaliseDiaria Coluna6='' Coluna7='' Coluna8='' Coluna9='' Coluna10='' Coluna11='' Coluna12='' Coluna13='' Coluna14='' Coluna15='' Coluna16=''/> </Produto> <Produto Coluna1='21-3814014' Coluna2='CAMIX2' Coluna3='' Coluna4='' Coluna5=''> <AnaliseDiaria Coluna6='' Coluna7='' Coluna8='' Coluna9='' Coluna10='' Coluna11='' Coluna12='' Coluna13='' Coluna14='' Coluna15='' Coluna16=''/> </Produto> <Produto Coluna1='21-3814087' Coluna2='SCA56' Coluna3='' Coluna4='' Coluna5=''> <AnaliseDiaria Coluna6='' Coluna7='' Coluna8='' Coluna9='' Coluna10='' Coluna11='' Coluna12='' Coluna13='' Coluna14='' Coluna15='' Coluna16=''/> <AnaliseDiaria Coluna6='19/06/20' Coluna7='01' Coluna8='EP 202022777' Coluna9='1 UN' Coluna10='195.000,00' Coluna11='195.000,00' Coluna12='1' Coluna13='195.000,00' Coluna14='195.000,00' Coluna15='NF9' Coluna16='10203910A'/> <AnaliseDiaria Coluna6='13/07/20' Coluna7='01' Coluna8='RCP G 41765' Coluna9='0 UN' Coluna10='' Coluna11='90,00' Coluna12='1' Coluna13='195.090,00' Coluna14='195.090,00' Coluna15='' Coluna16=''/> <AnaliseDiaria Coluna6='27/07/20' Coluna7='01' Coluna8='RCP G 41767' Coluna9='0 UN' Coluna10='' Coluna11='180,00' Coluna12='1' Coluna13='195.270,00' Coluna14='195.270,00' Coluna15='' Coluna16=''/> <AnaliseDiaria Coluna6='27/07/20' Coluna7='01' Coluna8='RCP G 41768' Coluna9='0 UN' Coluna10='' Coluna11='212,60' Coluna12='1' Coluna13='195.482,60' Coluna14='195.482,60' Coluna15='' Coluna16=''/> <AnaliseDiaria Coluna6='27/07/20' Coluna7='01' Coluna8='RCP G 41770' Coluna9='0 UN' Coluna10='' Coluna11='145,20' Coluna12='1' Coluna13='195.627,80' Coluna14='195.627,80' Coluna15='' Coluna16=''/> <AnaliseDiaria Coluna6='27/07/20' Coluna7='01' Coluna8='RCP G 41771' Coluna9='0 UN' Coluna10='' Coluna11='8.902,02' Coluna12='1' Coluna13='204.529,82' Coluna14='204.529,82' Coluna15='' Coluna16=''/> <AnaliseDiaria Coluna6='27/07/20' Coluna7='01' Coluna8='VP 323755' Coluna9='-1 UN' Coluna10='204.529,82' Coluna11='-204.529,82' Coluna12='0' Coluna13='' Coluna14='' Coluna15='' Coluna16='158PES'/> </Produto> </Linha> </Filial> </LucroCliente>
已尝试的无效方案
方案一
import xml.etree.ElementTree as et import pandas as pd xml_data = open('file.xml', 'r').read() root = et.XML(xml_data) # Parse XML data = [] cols = [] for i, child in enumerate(root): data.append([subchild.text for subchild in child]) cols.append(child.tag) df = pd.DataFrame(data).T df.columns = cols
方案二
from lxml import objectify import pandas as pd xml_data = objectify.parse('file.xml') root = xml_data.getroot() data = [] cols = [] for i in range(len(root.getchildren())): child = root.getchildren()[i] data.append([subchild.text for subchild in child.getchildren()]) cols.append(child.tag) df = pd.DataFrame(data).T df.columns = cols
期望的表格格式
| Coluna1 | Coluna2 | Coluna3 | Coluna4 | Coluna5 | Coluna6 | Coluna7 | Coluna8 | Coluna9 | Coluna10 | Coluna11 | Coluna12 | Coluna13 | Coluna14 | Coluna15 | Coluna16 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 21-851611 | CAMIO VO | ||||||||||||||
| 21-3814087 | SCA56 | 19/06/20 | 01 | EP 202022777 | 1 UN | 195.000,00 | 195.000,00 | 1 | 195.000,00 | 195.000,00 | NF9 | 10203910A | |||
| 21-3814087 | SCA56 | 13/07/20 | 01 | RCP G 41765 | 0 UN | 90,00 | 1 | 195.090,00 | 195.090,00 |
正确实现方案
问题核心在于你的XML包含命名空间,且目标数据都存在于节点的属性中(而非节点文本),同时每个Produto对应多个AnaliseDiaria,需要将两者的属性合并后生成行数据。
代码实现
import xml.etree.ElementTree as et import pandas as pd # 定义XML命名空间 ns = {'pace': 'http://www.ms.com/pace'} # 解析XML文件 tree = et.parse('file.xml') root = tree.getroot() # 存储所有行数据 rows = [] # 遍历所有Produto节点 for produto in root.findall('.//pace:Produto', ns): # 提取Produto的属性(Coluna1到Coluna5) produto_attrs = produto.attrib # 遍历当前Produto下的所有AnaliseDiaria节点 for analise in produto.findall('.//pace:AnaliseDiaria', ns): # 合并Produto和AnaliseDiaria的属性 row = {**produto_attrs, **analise.attrib} rows.append(row) # 转换为DataFrame df = pd.DataFrame(rows) # 按列名排序(可选,保持Coluna1到Coluna16的顺序) df = df[sorted(df.columns)] print(df)
代码说明
- 命名空间处理:XML根节点定义了默认命名空间
http://www.ms.com/pace,需要通过ns字典传递给findall方法才能正确定位节点。 - 属性提取:目标数据都存储在节点的属性中(如
Coluna1是Produto的属性),因此直接读取attrib字典而非text。 - 数据合并:每个
Produto对应多个AnaliseDiaria,将两者的属性合并成一行,确保每行数据包含完整的产品和每日分析信息。 - 列排序:最后对列名排序,保证输出表格的列顺序与期望一致。
内容的提问来源于stack exchange,提问作者Sam.H
相关产品推荐
相关产品推荐

