将 XML 结构展平为 pandas 数据框
Flatten XML structure to pandas dataframe
我无法将 xml 文件中的数据提取到 pandas 数据框中。有问题的 xml 文件具有以下结构:
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Beleg_Exchange>
<Beleg_List>
<Beleg_Rec>
<ID>16092</ID>
<Adresse_ID>3127</Adresse_ID>
<Belegzeile_List>
<Belegzeile_Rec>
<ID>59122</ID>
<Zeilennummer>1</Zeilennummer>
<Menge>1</Menge>
<Einheit>Stk</Einheit>
<Belegzeilentext>Importabwicklung</Belegzeilentext>
<Preis>100</Preis>
</Belegzeile_Rec>
<Belegzeile_Rec>
<ID>59123</ID>
<Zeilennummer>2</Zeilennummer>
<Menge>1</Menge>
<Einheit>Stk</Einheit>
<Belegzeilentext>Exportabwicklung</Belegzeilentext>
<Preis>200</Preis>
</Belegzeile_Rec>
</Belegzeile_List>
</Beleg_Rec>
<Beleg_Rec>
<ID>16093</ID>
<Adresse_ID>3128</Adresse_ID>
<Belegzeile_List>
<Belegzeile_Rec>
<ID>59125</ID>
<Zeilennummer>1</Zeilennummer>
<Menge>1</Menge>
<Einheit>Stk</Einheit>
<Belegzeilentext>Importabwicklung</Belegzeilentext>
<Preis>100</Preis>
</Belegzeile_Rec>
<Belegzeile_Rec>
<ID>59126</ID>
<Zeilennummer>2</Zeilennummer>
<Menge>1</Menge>
<Einheit>Stk</Einheit>
<Belegzeilentext>Exportabwicklung</Belegzeilentext>
<Preis>200</Preis>
</Belegzeile_Rec>
</Belegzeile_List>
</Beleg_Rec>
</Beleg_List>
</Beleg_Exchange>
我想将其作为平面 table 导入到 pandas 中,如下所示,为每个 <Belegzeile_Rec>
.[=19= 复制 <Beleg_Rec>
下的条目]
ID Adresse_ID ID_inner Zeilennummer Menge Einheit Belegzeilentext Preis
0 16092 3127 59122 1 1 Stk Importabwicklung 100
1 16092 3127 59123 2 1 Stk Exportabwicklung 200
2 16093 3128 59125 1 1 Stk Importabwicklung 100
3 16093 3128 59126 2 1 Stk Exportabwicklung 200
或者,两个可以合并的数据帧也可以很好地工作。为此,我需要 <Beleg_Rec>
的 ID 以某种方式连接到每个订单项。
我可以使用 pandas.read_xml 和特定的 xpath 阅读每个部分,但我无法找到连接两者的方法:
df_outer = pd.read_xml(f, xpath="//Beleg_Exchange/Beleg_List/Beleg_Rec")
ID Adresse_ID Belegzeile_List
0 16092 3127 NaN
1 16093 3128 NaN
df_inner = pd.read_xml(f, xpath="//Beleg_Exchange/Beleg_List/Beleg_Rec/Belegzeile_List/Belegzeile_Rec")
ID Zeilennummer Menge Einheit Belegzeilentext Preis
0 59122 1 1 Stk Importabwicklung 100
1 59123 2 1 Stk Exportabwicklung 200
2 59125 1 1 Stk Importabwicklung 100
3 59126 2 1 Stk Exportabwicklung 200
我认为前进的方向是使用 xml2dict
然后遍历字典,将其附加到数据框。有没有我不知道的更有效的方法?
试试下面的方法
import pandas as pd
import xml.etree.ElementTree as ET
xml = '''<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Beleg_Exchange>
<Beleg_List>
<Beleg_Rec>
<ID>16092</ID>
<Adresse_ID>3127</Adresse_ID>
<Belegzeile_List>
<Belegzeile_Rec>
<ID>59122</ID>
<Zeilennummer>1</Zeilennummer>
<Menge>1</Menge>
<Einheit>Stk</Einheit>
<Belegzeilentext>rtabwicklung1</Belegzeilentext>
<Preis>100</Preis>
</Belegzeile_Rec>
<Belegzeile_Rec>
<ID>59123</ID>
<Zeilennummer>2</Zeilennummer>
<Menge>1</Menge>
<Einheit>Stk</Einheit>
<Belegzeilentext>abwicklung2</Belegzeilentext>
<Preis>200</Preis>
</Belegzeile_Rec>
</Belegzeile_List>
</Beleg_Rec>
<Beleg_Rec>
<ID>16093</ID>
<Adresse_ID>3128</Adresse_ID>
<Belegzeile_List>
<Belegzeile_Rec>
<ID>59125</ID>
<Zeilennummer>1</Zeilennummer>
<Menge>1</Menge>
<Einheit>Stk</Einheit>
<Belegzeilentext>bwicklung3</Belegzeilentext>
<Preis>101</Preis>
</Belegzeile_Rec>
<Belegzeile_Rec>
<ID>59126</ID>
<Zeilennummer>2</Zeilennummer>
<Menge>1</Menge>
<Einheit>Stk</Einheit>
<Belegzeilentext>abwicklung4</Belegzeilentext>
<Preis>201</Preis>
</Belegzeile_Rec>
</Belegzeile_List>
</Beleg_Rec>
</Beleg_List>
</Beleg_Exchange>'''
data = []
root = ET.fromstring(xml)
records = root.findall('.//Beleg_Rec')
for record in records:
temp = {c.tag:c.text for c in record if not len(c)}
sub_records = record.findall('.//Belegzeile_Rec')
for sub in sub_records:
entry = {c.tag if c.tag != 'ID' else 'ID_inner':c.text for c in sub}
entry.update(temp)
data.append(entry)
df = pd.DataFrame(data)
print(df)
输出
ID_inner Zeilennummer Menge Einheit Belegzeilentext Preis ID Adresse_ID
0 59122 1 1 Stk rtabwicklung1 100 16092 3127
1 59123 2 1 Stk abwicklung2 200 16092 3127
2 59125 1 1 Stk bwicklung3 101 16093 3128
3 59126 2 1 Stk abwicklung4 201 16093 3128
我无法将 xml 文件中的数据提取到 pandas 数据框中。有问题的 xml 文件具有以下结构:
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Beleg_Exchange>
<Beleg_List>
<Beleg_Rec>
<ID>16092</ID>
<Adresse_ID>3127</Adresse_ID>
<Belegzeile_List>
<Belegzeile_Rec>
<ID>59122</ID>
<Zeilennummer>1</Zeilennummer>
<Menge>1</Menge>
<Einheit>Stk</Einheit>
<Belegzeilentext>Importabwicklung</Belegzeilentext>
<Preis>100</Preis>
</Belegzeile_Rec>
<Belegzeile_Rec>
<ID>59123</ID>
<Zeilennummer>2</Zeilennummer>
<Menge>1</Menge>
<Einheit>Stk</Einheit>
<Belegzeilentext>Exportabwicklung</Belegzeilentext>
<Preis>200</Preis>
</Belegzeile_Rec>
</Belegzeile_List>
</Beleg_Rec>
<Beleg_Rec>
<ID>16093</ID>
<Adresse_ID>3128</Adresse_ID>
<Belegzeile_List>
<Belegzeile_Rec>
<ID>59125</ID>
<Zeilennummer>1</Zeilennummer>
<Menge>1</Menge>
<Einheit>Stk</Einheit>
<Belegzeilentext>Importabwicklung</Belegzeilentext>
<Preis>100</Preis>
</Belegzeile_Rec>
<Belegzeile_Rec>
<ID>59126</ID>
<Zeilennummer>2</Zeilennummer>
<Menge>1</Menge>
<Einheit>Stk</Einheit>
<Belegzeilentext>Exportabwicklung</Belegzeilentext>
<Preis>200</Preis>
</Belegzeile_Rec>
</Belegzeile_List>
</Beleg_Rec>
</Beleg_List>
</Beleg_Exchange>
我想将其作为平面 table 导入到 pandas 中,如下所示,为每个 <Belegzeile_Rec>
.[=19= 复制 <Beleg_Rec>
下的条目]
ID Adresse_ID ID_inner Zeilennummer Menge Einheit Belegzeilentext Preis
0 16092 3127 59122 1 1 Stk Importabwicklung 100
1 16092 3127 59123 2 1 Stk Exportabwicklung 200
2 16093 3128 59125 1 1 Stk Importabwicklung 100
3 16093 3128 59126 2 1 Stk Exportabwicklung 200
或者,两个可以合并的数据帧也可以很好地工作。为此,我需要 <Beleg_Rec>
的 ID 以某种方式连接到每个订单项。
我可以使用 pandas.read_xml 和特定的 xpath 阅读每个部分,但我无法找到连接两者的方法:
df_outer = pd.read_xml(f, xpath="//Beleg_Exchange/Beleg_List/Beleg_Rec")
ID Adresse_ID Belegzeile_List
0 16092 3127 NaN
1 16093 3128 NaN
df_inner = pd.read_xml(f, xpath="//Beleg_Exchange/Beleg_List/Beleg_Rec/Belegzeile_List/Belegzeile_Rec")
ID Zeilennummer Menge Einheit Belegzeilentext Preis
0 59122 1 1 Stk Importabwicklung 100
1 59123 2 1 Stk Exportabwicklung 200
2 59125 1 1 Stk Importabwicklung 100
3 59126 2 1 Stk Exportabwicklung 200
我认为前进的方向是使用 xml2dict
然后遍历字典,将其附加到数据框。有没有我不知道的更有效的方法?
试试下面的方法
import pandas as pd
import xml.etree.ElementTree as ET
xml = '''<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<Beleg_Exchange>
<Beleg_List>
<Beleg_Rec>
<ID>16092</ID>
<Adresse_ID>3127</Adresse_ID>
<Belegzeile_List>
<Belegzeile_Rec>
<ID>59122</ID>
<Zeilennummer>1</Zeilennummer>
<Menge>1</Menge>
<Einheit>Stk</Einheit>
<Belegzeilentext>rtabwicklung1</Belegzeilentext>
<Preis>100</Preis>
</Belegzeile_Rec>
<Belegzeile_Rec>
<ID>59123</ID>
<Zeilennummer>2</Zeilennummer>
<Menge>1</Menge>
<Einheit>Stk</Einheit>
<Belegzeilentext>abwicklung2</Belegzeilentext>
<Preis>200</Preis>
</Belegzeile_Rec>
</Belegzeile_List>
</Beleg_Rec>
<Beleg_Rec>
<ID>16093</ID>
<Adresse_ID>3128</Adresse_ID>
<Belegzeile_List>
<Belegzeile_Rec>
<ID>59125</ID>
<Zeilennummer>1</Zeilennummer>
<Menge>1</Menge>
<Einheit>Stk</Einheit>
<Belegzeilentext>bwicklung3</Belegzeilentext>
<Preis>101</Preis>
</Belegzeile_Rec>
<Belegzeile_Rec>
<ID>59126</ID>
<Zeilennummer>2</Zeilennummer>
<Menge>1</Menge>
<Einheit>Stk</Einheit>
<Belegzeilentext>abwicklung4</Belegzeilentext>
<Preis>201</Preis>
</Belegzeile_Rec>
</Belegzeile_List>
</Beleg_Rec>
</Beleg_List>
</Beleg_Exchange>'''
data = []
root = ET.fromstring(xml)
records = root.findall('.//Beleg_Rec')
for record in records:
temp = {c.tag:c.text for c in record if not len(c)}
sub_records = record.findall('.//Belegzeile_Rec')
for sub in sub_records:
entry = {c.tag if c.tag != 'ID' else 'ID_inner':c.text for c in sub}
entry.update(temp)
data.append(entry)
df = pd.DataFrame(data)
print(df)
输出
ID_inner Zeilennummer Menge Einheit Belegzeilentext Preis ID Adresse_ID
0 59122 1 1 Stk rtabwicklung1 100 16092 3127
1 59123 2 1 Stk abwicklung2 200 16092 3127
2 59125 1 1 Stk bwicklung3 101 16093 3128
3 59126 2 1 Stk abwicklung4 201 16093 3128