pandas 如何在python中查找多个XML文件中的重复项并合并成一个XML文件?

lb3vh1jj  于 2023-03-16  发布在  Python
关注(0)|答案(1)|浏览(142)

我有3个XML文件需要相互比较。我需要通过这些应用程序标签中的部件ID找到每个文件中的重复项。然后,对于最大的文件(即数据最多),我需要将这些重复项合并到该大文件中,并将其他2个文件中的唯一数据附加到该XML文件中。
我对ElementTree模块有些熟悉,但是我很难理解如何让自己更容易地在所有3个文件中找到重复的数据并完成剩余的操作。
有没有人知道如何完成这一步,或者至少是第一步?我知道如何解析xml文件,并使用for循环遍历根中的所有元素,但我不确定如何获取重复的部件ID和唯一数据,以将其全部放入最大的文件中。

我的尝试:

  • 我想也许我可以用read_xml()函数把这些文件转换成panda Dataframe ,但是当我使用to_xml()函数时,它不能很好地保留标签/元素中的数据。我放弃了这个想法,因为我认为这不是正确的方法。
  • 我试着在ElementTree中搜索函数,看看是否有办法找到重复项,但我没有找到任何本地方法来完成此操作
  • 为了找到最大的文件,我发现操作系统模块具有

getsize(),我想我可以使用它作为合并到最大文件的标准
我尝试使用Pandas下面的代码:

import xml.etree.ElementTree as ET
import pandas as pd
import os

input_folder = r"C:\Users\me\OneDrive\Documents\Data Conversion\ACES & PIES conversion\Sample Files"

def merge_files(input_folder):
    xml_list = []
    for file in os.listdir(input_folder):
        df = pd.read_xml(f"{input_folder}/{file}")
        xml_list.append(df)
    
    pd.set_option('display.max_columns', None)
    xml_merged = pd.concat(xml_list, ignore_index=True)
    df2 = pd.DataFrame(xml_merged)
    print(df2.info())

merge_files(input_folder)

当我显示www.example.com()时,得到了以下结果df2.info:

Output exceeds the size limit. Open the full output data in a text editor
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 274460 entries, 0 to 274459
Data columns (total 48 columns):
 #   Column                   Non-Null Count   Dtype  
---  ------                   --------------   -----  
 0   Company                  3 non-null       object 
 1   SenderName               3 non-null       object 
 2   SenderPhone              3 non-null       object 
 3   TransferDate             3 non-null       object 
 4   BrandAAIAID              3 non-null       object 
 5   DocumentTitle            3 non-null       object 
 6   DocFormNumber            3 non-null       float64
 7   EffectiveDate            3 non-null       object 
 8   SubmissionType           3 non-null       object 
 9   MapperCompany            3 non-null       object 
 10  MapperContact            3 non-null       object 
 11  MapperPhone              3 non-null       object 
 12  MapperEmail              3 non-null       object 
 13  VcdbVersionDate          3 non-null       object 
 14  QdbVersionDate           3 non-null       object 
 15  PcdbVersionDate          3 non-null       object 
 16  action                   274454 non-null  object 
 17  id                       274454 non-null  float64
 18  BaseVehicle              0 non-null       float64
 19  EngineBase               0 non-null       float64
...
 47  FuelSystemDesign         0 non-null       float64
dtypes: float64(30), object(18)
memory usage: 100.5+ MB
None

下面是其中一个XML文件的内容示例。在整个文件中有许多重复的应用程序标记。

<?xml version="1.0" encoding="utf-8"?>
<ACES version="4.2">
     <Header>
          <Company>x</Company>
          <SenderName>y</SenderName>
          <SenderPhone>z</SenderPhone>
          <TransferDate>a</TransferDate>
          <BrandAAIAID>b</BrandAAIAID>
          <DocumentTitle>c</DocumentTitle>
          <DocFormNumber>2.0</DocFormNumber>
          <EffectiveDate>2023-02-22</EffectiveDate>
          <SubmissionType>FULL</SubmissionType>
          <MapperCompany>d</MapperCompany>
          <MapperContact>e</MapperContact>
          <MapperPhone>f</MapperPhone>
          <MapperEmail>g</MapperEmail>
          <VcdbVersionDate>2023-01-26</VcdbVersionDate>
          <QdbVersionDate>2023-01-26</QdbVersionDate>
          <PcdbVersionDate>2023-01-26</PcdbVersionDate>
     </Header>
     <App action="A" id="1">
          <BaseVehicle id="5911"/>
          <BodyType id="5"/>
          <EngineBase id="560"/>
          <Note>WITHOUT AUTO LEVELING SYSTEM</Note>
          <Qty>1</Qty>
          <PartType id="7600"/> 
          <Position id="104"/>
          <Part>701940</Part>
      </App>
daupos2t

daupos2t1#

这种方法从主(也许是最大的)XML文件创建一个字典,从第二个文件创建另一个字典,其中包含第一个字典中不存在的元素。然后将这些元素添加到第一个根元素并写入第一个文件。

from lxml import etree
doc = etree.parse('tmp.xml')
# parse first file
a = doc.xpath('/ACES/App')
# make a dict with Part value as keys
# {'701941': <Element App at 0x7f3f72e7f648>}
d = {app.xpath('Part/text()')[0]: app for app in a}

# parse second file
doc2 = etree.parse('tmp2.xml')
a2 = doc2.xpath('/ACES/App')
# make a dict with keys NOT present on first dict
d2 = {app.xpath('Part/text()')[0]: app for app in a2 if app.xpath('Part/text()')[0] not in d.keys()}

root = doc.getroot()

for k,v in d2.items():
  root.append(v)

print(etree.tostring(root, pretty_print=True).decode('utf8'))

et = etree.ElementTree(root)
et.write('tmp.xml', pretty_print=True)

相关问题