You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

遍历XML目录合并数据至Pandas DataFrame后数据为空的问题排查

问题描述

需要解析一个嵌套XML文件目录,并将结果合并到单个Pandas DataFrame中。单个文件解析已成功,但遍历目录合并时,最终DataFrame始终为空。

示例XML文件

<annotation>
    <folder>VOC2007</folder>
    <filename>361_0_00020.jpg</filename>
    <size>
        <width>800</width>
        <height>800</height>
        <depth>3</depth>
    </size>
    <segmented>0</segmented>
    <object>
        <name>361</name>
        <pose>Unspecified</pose>
        <truncated>0</truncated>
        <difficult>0</difficult>
        <bndbox>
            <xmin>338</xmin>
            <ymin>361</ymin>
            <xmax>430</xmax>
            <ymax>430</ymax>
        </bndbox>
    </object>
    <object>
        <name>361</name>
        <pose>Unspecified</pose>
        <truncated>0</truncated>
        <difficult>0</difficult>
        <bndbox>
            <xmin>24</xmin>
            <ymin>16</ymin>
            <xmax>240</xmax>
            <ymax>156</ymax>
        </bndbox>
    </object>
</annotation>

单个文件解析代码(可正常运行)

import pandas as pd
import xml.etree.ElementTree as et

tree= et.parse("/content/drive/MyDrive/361_0_00020.xml")
root=tree.getroot()
filename = root.find('filename').text 
obj= root.find('object')
bnb = obj.find('bndbox') 
xmin = bnb.find('xmin').text 
ymin = bnb.find('ymin').text
xmax = bnb.find('xmax').text
ymax = bnb.find('ymax').text
list_1 = [filename, xmin, ymin, xmax, ymax]
df_cols= ['filename','xmin', 'ymin', 'xmax', 'ymax']
df= pd.DataFrame([list_1], columns=df_cols)
df

遍历目录的代码(执行后DataFrame为空)

import os 
import pandas as pd 
import xml.etree.ElementTree as et
df_cols= ['filename','xmin', 'ymin', 'xmax', 'ymax']
df= pd.DataFrame([], columns=df_cols)
path= '/content/drive/MyDrive/Annotations'
for filename in os.listdir(path):
    if not filename.endswith('.xml'): continue
    fullname = os.path.join(path, filename) 
    tree = et.parse(fullname)
    root=tree.getroot()
    for child in root: 
        fnm = root.find('filename').text
        obj= root.find('object')
        bnb = obj.find('bndbox')
        xmin = bnb.find('xmin').text
        ymin = bnb.find('ymin').text
        xmax = bnb.find('xmax').text
        ymax = bnb.find('ymax').text
        list_2 = [[fnm, xmin, ymin, xmax, ymax]]
        df.append(pd.DataFrame(list_2))

问题原因与解决方案

1. df.append() 不会修改原DataFrame

Pandas的append()方法返回新的DataFrame,不会直接修改原对象。你只调用了df.append(...)但没有把返回值赋值给df,所以原df始终是空的。

2. 遍历逻辑错误

  • 内层for child in root:完全没必要,这个循环会遍历annotation下的所有子节点(folder、filename、size等),导致同一个XML里的对象被重复处理多次。
  • root.find('object')只会找到第一个<object>节点,XML里的多个对象会被忽略。

修正后的代码

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

df_cols = ['filename','xmin', 'ymin', 'xmax', 'ymax']
# 用列表存储所有数据,最后一次性生成DataFrame,效率更高
data_list = []
path = '/content/drive/MyDrive/Annotations'

for filename in os.listdir(path):
    if not filename.endswith('.xml'):
        continue
    fullname = os.path.join(path, filename) 
    tree = et.parse(fullname)
    root = tree.getroot()
    fnm = root.find('filename').text
    # 遍历所有<object>节点
    for obj in root.findall('object'):
        bnb = obj.find('bndbox')
        xmin = bnb.find('xmin').text
        ymin = bnb.find('ymin').text
        xmax = bnb.find('xmax').text
        ymax = bnb.find('ymax').text
        data_list.append([fnm, xmin, ymin, xmax, ymax])

# 最后一次性生成DataFrame
df = pd.DataFrame(data_list, columns=df_cols)

额外优化说明

  • 避免在循环中反复调用df.append(),因为每次append都会创建新的DataFrame,效率极低。用列表收集所有数据,最后统一生成DataFrame是更高效的做法。
  • 使用root.findall('object')获取所有对象节点,确保XML里的多个object都被处理。

内容的提问来源于stack exchange,提问作者Jonathan Grenner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 23:31:06