【问题标题】:python xml and csv extractpython xml和csv提取
【发布时间】:2021-01-16 23:00:47
【问题描述】:

我有 2 组文件 - (1) CSV 文件(主文件)(2) XML 文件。

CSV 文件 -

emp_id
1
2
3
4

XML 文件 -

<employee>
    <emp id="1" />
    <emp id="2" active="yes">
        <tag k="age" v="55" />
    </emp>
    <emp id="3" active="yes">
        <tag k="name" v="scott" />
    </emp>
    <emp id="4" active="no">
        <tag k="address" v="Texas" />
    </emp>
    <emp id="5" gender="male"/>
    <emp id="8" />
    <emp id="9" />
    <emp id="10" />
    <emp id="11" />
</employee>

我的目标是有一个 csv 文件,其中 csv 文件中的 emp_id 与 XML 文件匹配,并且仅在新的 csv 文件中创建匹配的 emp_id。我需要 2 个 csv 文件,如下所示 -

第一个文件。

emp_id,active,gender
1,,
2,yes,
3,yes,
4,no,
5,,male

第二个文件。

emp_id,key,value
2,age,55
3,name,scott
4,address,Texas

我可以在 pandas 中读取 CSV 文件,在 Python 中读取 XML 文件。但不知道如何组合它们并从 XML 中提取键和值

感谢任何帮助。

【问题讨论】:

  • 您当前的代码是什么?请分享并解释问题所在
  • 当前代码仅包括读取 csv 文件和 xml 文件。我对将 csv 文件数据与 xml 文件组合并提取信息的逻辑感到震惊

标签: python xml pandas csv


【解决方案1】:

让我们创建第一个数据框:

# this dataframe should be read from csv in your case
df = pd.DataFrame({
    'emp_id':[1, 2, 3, 4, 5]
})

比定义XML:

xml = '''<employee>
    <emp id="1" />
    <emp id="2" active="yes">
        <tag k="age" v="55" />
    </emp>
    <emp id="3" active="yes">
        <tag k="name" v="scott" />
    </emp>
    <emp id="4" active="no">
        <tag k="address" v="Texas" />
    </emp>
    <emp id="5" gender="male"/>
    <emp id="8" />
    <emp id="9" />
    <emp id="10" />
    <emp id="11" />
</employee>'''

从 XML 读取数据:

d = defaultdict(list)
# here we read XML from string, in your case it should be read from file
root = et.fromstring(xml)
emps = root.xpath('//employee/emp')
# iterate over elements "emp" and extract data
for emp in emps:
  # here we extract attributes id, active and gender
  d['id'].append(int(emp.get('id')))
  d['active'].append(None if emp.get('active') is None else emp.get('active'))
  d['gender'].append(None if emp.get('gender') is None else emp.get('gender'))
  # here we extract age
  age = emp.find('./tag[@k="age"]')
  d['age'].append(None if age is None else age.get('v'))
  # here we extract address
  address = emp.find('./tag[@k="address"]')
  d['address'].append(None if address is None else address.get('v'))

比从 dict 创建数据框:

df_xml = pd.DataFrame(d)

比使用 emp_id / id 列合并数据:

df_merged = pd.merge(df, df_xml, left_on = 'emp_id', right_on='id', how = 'inner')
del df_merged['id']

df_merged.head(10)

输出:

【讨论】:

  • 谢谢。但是有多个键值。我只展示了一个示例。我不希望输出有很多列。
  • 在这种情况下,您可以在循环中保留for emp in emps: 仅第一行:d['id'].append(int(emp.get('id')))。这将创建一个只有一列的数据框。
【解决方案2】:

First df:读取XML并创建DataFrame

import xmltodict
with open('XmlFile.xml') as fd:
    xmlfile = xmltodict.parse(fd.read())
df_xmlfile = pd.DataFrame(xmlfile["employee"]["emp"])
df_xmlfile.columns = [col.replace("@","") for col in df_xmlfile.columns]

将 CSV 读取为 DataFrame

df_csvfile = csvfile=pd.read_csv("CsvFile.txt")

加入两个dfs

df_first = df_csvfile.join(df_xmlfile[["active", "gender"]])

第二个df: 获取包含标签的行,解包这些行以获取键和值并创建第二个 df

df_temp = df_xmlfile[~df_xmlfile["tag"].isna()][["id", "tag"]]
df_second = pd.DataFrame({"emp_id": df_temp["id"],
              "key": [row["@k"] for row in df_temp["tag"]],
              "value": [row["@v"] for row in df_temp["tag"]]})

【讨论】:

    【解决方案3】:

    另一种方法。

    from simplified_scrapy import SimplifiedDoc, utils
    empIds = ['1', '2', '3', '4', '5']
    # empIds = [id.strip() for id in utils.getFileLines('your csv file path')[1:]]
    
    xml = '''<employee>
        <emp id="1" />
        <emp id="2" active="yes">
            <tag k="age" v="55" />
        </emp>
        <emp id="3" active="yes">
            <tag k="name" v="scott" />
        </emp>
        <emp id="4" active="no">
            <tag k="address" v="Texas" />
        </emp>
        <emp id="5" gender="male"/>
        <emp id="8" />
        <emp id="9" />
        <emp id="10" />
        <emp id="11" />
    </employee>
    '''
    # xml = utils.getFileContent('your xml file path')
    
    rows1 = [['emp_id', 'active', 'gender']]
    rows2 = [['emp_id', 'key', 'value']]
    doc = SimplifiedDoc(xml)
    for id in empIds:
        emp = doc.select('emp#' + id)
        if emp:
            rows1.append([id, emp.get('active'), emp.get('gender')])
            tags = emp.selects('tag')
            if tags:
                for tag in tags:
                    rows2.append([id, tag['k'], tag['v']])
    
    utils.save2csv('csv1.csv', rows1, newline='')
    utils.save2csv('csv2.csv', rows2, newline='')
    

    结果 csv1:

    emp_id,active,gender
    1,,
    2,yes,
    3,yes,
    4,no,
    5,,male
    

    结果 csv2:

    emp_id,key,value
    2,age,55
    3,name,scott
    4,address,Texas
    

    【讨论】:

      猜你喜欢
      • 2017-06-11
      • 1970-01-01
      • 2018-11-21
      • 2012-02-23
      • 1970-01-01
      • 1970-01-01
      • 2020-09-09
      • 1970-01-01
      • 2015-08-22
      相关资源
      最近更新 更多