Python将CSV数据转换为分层XML

时间:2017-10-26 22:09:52

标签: python xml pandas csv transformation

我在CSV中有父子数据,我需要使用Python将层次结构转换为XML文件。我到处搜索过,但大多数解决方案都涉及JSON或JavaScript,并且与我的问题没有直接关系。如果您知道我错过的答案,请链接我!

CSV数据示例:

species,species_code,group,group_code
哺乳动物,00,动物,0,
熊,01,哺乳动物,00
马,02,哺乳动物,00,
猫,03,哺乳动物,00,
北极熊,011,熊,01,
灰熊,012,熊,01,
帕洛米诺,021,马匹,02,
孟加拉虎,031,猫,03,
美洲狮,032,猫,03,
lynx,033,cats,03
canada_lynx,0331,lynx,033

此数据应转换为XML,父组和子组的排列方式如下:

  <group>
            animals
            <group_code> 0 </group_code>
            <species>
                mammals
                <species_code > 00 </species_code>
            </species >
        </group>
        <group>
            mammals
            <group_code > 00 </group_code>
            <species>
                bears
                <species_code> 01 </species_code>
            </species>
            <species>
                horses
                <species_code> 02 </species_code>
            </species>
            <species>
                cats
                <species_code> 03 </species_code>
            </species>
        </group>
        <group>
            bears
            <group_code > 01 </group_code>
            <species>
                polar_bear
                <species_code> 011 </species_code>
            </species>
            <species>
                grizzly bear
                <species_code> 012 </species_code>
            </species>  

对于数据集中的父子关系,模式应保持一致。非常感谢您提供的任何帮助。我仍然很擅长这一点,并欣赏你能提供的任何新知识。

1 个答案:

答案 0 :(得分:1)

这提供了pandas所需的输出,使用的事实是您可以迭代pandas.groupby()的结果,返回类似(group, df[df['grouped_column'] == group])元组列表的内容。

我还将groupby的结果按group_code排序为字符串,以便按字典顺序排序,从而根据您的示例输出实现所需的“层次结构”(我不确定是否需要,也许你可以简单地将列排序为整数。)

import pandas as pd
import io
import csv
from xml.etree.ElementTree import Element, SubElement, tostring, ElementTree

sample_csv = io.StringIO("""
species, species_code, group, group_code
mammals, 00, animals, 0
bears, 01, mammals, 00
horses, 02, mammals,00
cats, 03, mammals, 00
polar bear, 011, bears, 01
grizzly bear, 012, bears, 01
palomino, 021, horses, 02
bengal tiger, 031, cats, 03
cougar, 032, cats, 03
lynx, 033, cats, 03
canada_lynx, 0331, lynx, 033""")

df = pd.read_csv(sample_csv, dtype=str)
df.columns = [col.strip() for col in df.columns]
for col in df.columns:
    df[col] = df[col].str.strip()

groups = Element('groups')
xml_tree = ElementTree(groups)

for group_group_code, df in sorted(df.groupby(['group', 'group_code']), key=lambda grp: grp[0][1]):
    group, group_code = group_group_code
    xml_group = Element('group')
    xml_group.text = group.strip()
    xml_group_code = SubElement(xml_group, 'group_code')
    xml_group_code.text = group_code.strip()
    for row in df[['species', 'species_code']].itertuples():
        xml_species = SubElement(xml_group, 'species')
        xml_species.text = row.species
        xml_species_code = SubElement(xml_species, 'species_code')
        xml_species_code.text = row.species_code
    groups.append(xml_group)

print(b''.join(tostring(gr) for gr in groups))
xml_tree.write('groups_test.xml')

print(...)行会准确打印您在问题中提出的内容(至少在结构上,没有缩进和换行),而xml_tree....行会创建包含所有群组的xml文件,但已包装在<groups>根元素中。它仍然写入文件没有任何缩进/换行。

如果您的xml输出应包含缩进/换行符based on this solution

from xml.dom import minidom

print(xml.dom.minidom.parseString(tostring(groups)).toprettyxml(indent="    "))

据我所知,这正是你所问的(包裹在<groups>根标签中)。