Python XML到CSV转换&将数据附加到主.csv文件

6jygbczu  于 2022-12-06  发布在  Python
关注(0)|答案(1)|浏览(134)

链接:


正在使用的工具:

  • 电源自动化桌面(PAD
  • PAD操作的命令提示符(CMD)会话
    *Python3.10(导入:Numpy、Pandas和使用元素树)
    *SQL读取数据并插入主数据库

方法:

*XMLCSV转换

  • 我正在使用Power Automate Desktop(PAD)来自动化所有这一切,因为这是我所知道的。
  • 转换方法使用Python,在CMD内部,导入numpy&Pandas,使用元素树

目标:

1.我希望避免将命名空间写入标头,以便SQL可以与csv数据交互
1.我想附加一个主csv文件与新的数据来自每个调用
1.这最后一个目标项目更像是一个愿望清单,我可能会把它带到PAD论坛上。只是在罕见的情况下,有人有一个解决方案:

  • (我希望避免同时使用CMD),但考虑到PAD的限制,使用IronPython时,我必须使用CMD会话来在CMS会话中使用常规Python。
  • 我正在使用Power Automate Desktop(PAD),它有一个Python模块。唯一的问题是它使用的是Iron Python 2.7,我不能访问库,也不知道如何在IronPython中编写下面的Python代码。如果我能解决这个问题,整个过程将更加高效。IronPython Module Operators(再次,这将是一个很好的拥有..其他目标是优先考虑的。

问题:

  • 将转换后的数据写入csv时,xmlns被添加到某些标头中
  • python代码在每个循环中生成一个新的.csv文件,我希望它只是将数据附加到一个公共的.csv文件中,以构建数据集。

详细信息(* 可能不必要 *):

首先,我不是PythonMaven,我也是SQL的新手。
目前,Python代码(见下文)将Web服务调用body格式化的XML转换为csv格式。然后将.csv数据导出为实际的csv文件。此操作效果很好,但每次都会覆盖该文件,这意味着我需要编写脚本来读取这些数据,然后才能删除文件或将其替换为新文件。(追加数据)。它还在一些头中打印XMLNS,这是我需要避免的。
如果您想知道我为什么要执行转换&而不是简单地解析xml数据,我的客户需要csv格式的数据集。否则,我会根据需要解析出XML数据。另一个原因是,此数据会以设定的间隔增量更新,从而构建审计跟踪。因此,由于以下原因,无法进行批量转换
1.我想做的是让Python代码执行转换&然后在csv文件中附加一个主数据集。
1.这里的另一个问题是XML中的XMLNS被拉入CSV表的一些(不是全部)头中,这使得使用SQL读取和插入主表成为一个问题。
1.* 此外,如果有人知道如何在IronPython 2.7中编写这些代码,那也很好,因为我可以使用CMD会话。*
因此,如果我可以使用Python将转换后的数据追加到主表中,同时转义名称空间,这将解决我所有(当前)的问题,并将在数据移动中获得100%更高效的额外好处。
此外,由于我拥有的工具集有限,我使用CMD中的Power Automate编写脚本,使用CMD会话。

Python代码(在CMD环境中):

cd\WORK\XML

python

import numpy as np 
import pandas as pd
from xml.etree import ElementTree

maintree = ElementTree.parse('FILE_XML.xml')
parentroot = maintree.getroot()

all_tags = list(set([elem.tag for elem in parentroot.iter()]))

rows = []

for child in parentroot:
    temp_dict = {}
    for i in all_tags:
        tag_values = {}
        for inners in child.iter(i):
            temp_tag_value = {}
            temp_dict.update(inners.attrib)
            temp_tag_value[i.rsplit("}", 1)[1]] = inners.text
            tag_values.update(temp_tag_value)
        temp_dict.update(tag_values)
    rows.append(temp_dict)

dataframe = pd.DataFrame.from_dict(rows, orient='columns')
dataframe = dataframe.replace({np.nan: None})
dataframe.to_csv('FILE_TABLE_CMD.csv', index=False)
7vux5j2d

7vux5j2d1#

如果不需要分析,请避免使用panda,并考虑使用**csv.DictWriter来构建CSV,在csv.DictWriter**中可以指定写入上下文的附加模式。下面将分析<ClinicalData>的所有底层后代,并将每个集移植到CSV行中。

from csv import DictWriter
from xml.etree import ElementTree

maintree = ElementTree.parse('FILE_XML.xml')
parentroot = maintree.getroot()
nmsp = {"doc": "http://www.cdisc.org/ns/odm/v1.3"}

# RETRIEVE ALL ELEMENT TAGS
all_tags = list(set([elem.tag for elem in parentroot.iter()]))

# RETRIEVE ALL ATTRIB KEYS
all_keys = [list(elem.attrib.keys()) for elem in maintree.iter()]
# UNNEST AND DE-DEDUPE
all_keys = set(sum([key for key in all_keys], []))

# COMBINE ELEM AND ATTRIB NAMES
all_tags = all_tags + list(all_keys)
all_tags = [(tag.split('}')[1] if '}' in tag else tag) for tag in all_tags]

# APPEND TO EXISTING DATA WIH 'a'
with open('FILE_TABLE_CMD.csv', 'a') as f:
    writer = DictWriter(f, fieldnames = all_tags)
    writer.writeheader()

    # ITERATE THROUGH ALL ClincalData ELEMENTS
    for cd in parentroot.findall('doc:ClinicalData', namespaces=nmsp):
        temp_dict = {}

        # ITERATE THROUGH ALL DESCENDANTS
        for elem in cd.iter():
            # UPDATE DICT FOR ELEMENT TAG/TEXT
            temp_dict[elem.tag.split("}", 1)[1]] = elem.text
            # MERGE ELEM DICT WITH ATTRIB DICT
            temp_dict = {**temp_dict, **elem.attrib}

            # REMOVE NAMESPACES IN KEYS
            temp_dict = {
                (k.split('}')[1] if '}' in k else k):v 
                for k,v
                in temp_dict.items()
             }

        # WRITE ROW TO CSV
        writer.writerow(temp_dict)

实际上,您可以使用最新v1.5中**pandas.read_xml**的 newiterparse特性。尽管该特性旨在用于非常大的XML,但它允许解析任何基础元素或属性,而不受XPath所需的关系限制。
您仍然需要找到所有元素和属性名称。CSV输出与上面的不同,因为方法会删除所有全空列,并保留XML中元素/属性的顺序。此外,pandas.DataFrame.csv确实支持附加模式,但可能需要条件逻辑来写入标题。

import os
from xml.etree import ElementTree
import pandas as pd  # VERSION 1.5+

maintree = ElementTree.parse('FILE_XML.xml')
parentroot = maintree.getroot()

# RETRIEVE ALL ELEMENT TAGS
all_tags = list(set([elem.tag for elem in parentroot.iter()]))

# RETRIEVE ALL ATTRIB KEYS
all_keys = [list(elem.attrib.keys()) for elem in maintree.iter()]
# UNNEST AND DE-DEDUPE
all_keys = set(sum([key for key in all_keys], []))

# COMBINE ELEM AND ATTRIB NAMES
all_tags = all_tags + list(all_keys)
all_tags = [(tag.split('}')[1] if '}' in tag else tag) for tag in all_tags]

clinical_data_df = pd.read_xml(
    "FILE_XML.xml", iterparse = {"ClinicalData": all_tags}, parser="etree"
)

if os.path.exists("FILE_TABLE_CMD.csv"):
    # CREATE CSV WITH HEADERS
    clinical_data_df.to_csv("FILE_TABLE_CMD.csv", index=False)
else:
    # APPEND TO CSV WITHOUT HEADERS
    clinical_data_df.to_csv("FILE_TABLE_CMD.csv", index=False, mode="a", header=False)

相关问题