将 XML 转换为 CSV 文件时获取空文件 Pandas Python

Getting empty file while converting XML to CSV file Pandas Python

这是我的 XML 文件

<Lieferantenbestellungen>
  <Lieferantenbestellung>
    <Jahr>2021</Jahr>
    <Nummer>1</Nummer>
    <Datum>2021-01-07</Datum>
    <Lieferant_ID>459</Lieferant_ID>
    <Positionen>
      <Position Artikel="MCGPXO96" Bezeichnung="Refined Rubber Tuna" Menge="1" />
      <Position Artikel="IYTAFI28" Bezeichnung="Generic Cotton Chicken" Menge="8" />
    </Positionen>
  </Lieferantenbestellung>
</Lieferantenbestellungen>

我想从文件中提取 Lieferant_ID、Artikel、Bezeichnung、Bezeichnung 和 Menge。

我有这个 python 代码:

with open('Lieferantenbestellungen.xml', 'r') as f:
    soup = BeautifulSoup(f.read(), 'lxml')

# Get the data you want
df = pd.DataFrame(list(zip(
  [el.text for el in soup.find_all('Lieferant_ID')],
  [el.text for el in soup.find_all('Artikel')],
  [el.text for el in soup.find_all('Bezeichnung')],
  [el.text for el in soup.find_all('Menge')]
)), columns=['Lieferant_ID', 'Artikel', 'Bezeichnung', 'Menge'])

# Dump to csv
df.to_csv('out.csv', index=False)

当我 运行 代码生成 CSV 文件时,它是空的。有谁知道我做错了什么吗?

预期的 CSV 输出:

提前致谢

import xml.etree.ElementTree as ET
import csv
tree = ET.parse('your_file.xml')
root = tree.getroot()
returnitem = {}
for i in root.findall('Lieferantenbestellung'):
   id = i.get('Lieferant_ID')
   returnitem["Lieferant_ID"] = id
   num = 0
   for i2 in i.find("Positionen").findall("Position"):
      Artikel = i2.find("Artikel").text
      Bezeichnung = i2.find("Bezeichnung").text
      Menge = i2.find("Menge").text
      num += 1
      returnitem["Data",str(num)] = {"Artikel":Artikel,"Bezeichnung":Bezeichnung,"Menge":Menge}
with open('result.csv', 'w') as f:
    for key in returnitem.keys():
        f.write("%s, %s\n" % (key, returnitem[key]))

这个程序应该可以解决你的问题 但是可能有一些 json/dictonary 形式的数据

pandas 现在有 .read_xml() 可以直接使用。

>>> pd.read_xml('Lieferantenbestellungen.xml', xpath='.//Lieferant_ID | .//Position')
   Lieferant_ID   Artikel             Bezeichnung  Menge
0         459.0      None                    None    NaN
1           NaN  MCGPXO96     Refined Rubber Tuna    1.0
2           NaN  IYTAFI28  Generic Cotton Chicken    8.0

您可以 .ffill().dropna() 来“对齐”结果。

>>> df = pd.read_xml('Lieferantenbestellungen.xml', xpath='.//Lieferant_ID | .//Position')
>>> df['Lieferant_ID'] = df['Lieferant_ID'].ffill()
>>> df.dropna()
   Lieferant_ID   Artikel             Bezeichnung  Menge
1         459.0  MCGPXO96     Refined Rubber Tuna    1.0
2         459.0  IYTAFI28  Generic Cotton Chicken    8.0

要解析 xml,您需要执行 soup = BeautifulSoup(markup, "xml"),而不是 "lxml"

执行此操作时,soup.find_all('Lieferant_ID') returns ['459']

但是,多次执行 find_all() 并不是一个好主意,因为每个 Lieferantenbestellung 有多个 Positionen 标签。相反,我建议您 find_all("Lieferantenbestellung"),然后处理每个标签。

此外,为了调试,将代码分成多行而不是将所有内容都塞到一行中会更容易。

with open('Lieferantenbestellungen.xml', 'r') as f:
    soup = BeautifulSoup(f.read(), 'lxml')

rows = []
for tag in soup.find_all("Lieferantenbestellung")
    lief_id = tag.findChild("Lieferant_ID")
    if lief_id is None:
        continue
    for ptag in tag.findChild("Positionen").findChildren("Position"):
        row = dict() # Make a new row
        row["Lieferant_ID"] = lief_id.text
        row["Artikel"] = ptag.attrs["Artikel"]
        row["Bezeichnung"] = ptag.attrs["Bezeichnung"]
        row["Menge"] = ptag.attrs["Menge"]
        rows.append(row)

现在,您可以使用 pd.DataFrame.from_records()

创建数据框
pd.DataFrame.from_records(rows)

  Lieferant_ID   Artikel             Bezeichnung Menge
0          459  MCGPXO96     Refined Rubber Tuna     1
1          459  IYTAFI28  Generic Cotton Chicken     8