提取大型LEI XML指定字段生成CSV时报AttributeError该如何解决
问题描述
我需要用Excel打开一份大型XML数据集,数据量未超出Excel工作簿上限。我尝试从XML中提取四列数据导出为CSV,代码如下:
cols = ["StartNodeID", "EndNodeID", "RelationshipType", "RelationshipDate_EndDate"] rows = [] xmlparse = Xet.parse('D:\Descargas\concatenated_lei2file_StartNodeID.xml') root = xmlparse.getroot() Relationships = tree.findall('./RelationshipRecord/Relationship') for elem in Relationships: StartNodeID = elem.find("./RelationshipRecord/Relationship/EndNode/EndNodeID").text EndNodeID = elem.find("EndNodeID").text RelationshipType = elem.find("RelationshipType").text RelationshipDate_EndDate = elem.find("RelationshipDate_EndDate").text rows.append({"StartNodeID": StartNodeID, "EndNodeID": EndNodeID, "RelationshipType": RelationshipType, "RelationshipDate_EndDate": RelationshipDate_EndDate}) df = pd.DataFrame(rows, columns=cols) df.to_csv('D:\Descargas\concatenated_lei2file_output.csv')
运行后报错如下:
----> 4 StartNodeID = elem.find("./RelationshipRecord/Relationship/EndNode/EndNodeID").text 5 EndNodeID = elem.find("EndNodeID").text 6 RelationshipType = elem.find("RelationshipType").text AttributeError: 'NoneType' object has no attribute 'text'
该数据集体量较大,我已通过firstobjectXML Editor查看过XML树结构。我已尝试以下操作:
- 用Sublime Text简化树结构,从"Relationship"层级开始解析
- 删除其余字段,仅保留StartNode.NodeID与EndNode.NodeID
但仍出现相同报错,请问该如何解决该问题?
解决方案
你出现报错是代码存在几个基础逻辑错误,逐一修正即可:
- 变量名未定义:你前面解析XML返回的对象是
xmlparse,但后面调用findall用的是未定义的tree变量,直接会导致异常。 - XML查找路径重复:
findall('./RelationshipRecord/Relationship')已经拿到了所有<Relationship>节点作为遍历对象elem,你在elem下再查找带RelationshipRecord/Relationship前缀的路径属于路径重复,必然返回空。 - 缩进错误:
rows.append写在for循环外面,只会追加最后一次遍历的结果,无法存储全量数据。 - 空值未处理:部分节点可能不存在目标子节点,直接调用
.text会触发AttributeError。
修正后可运行的代码如下:
import pandas as pd import xml.etree.ElementTree as Xet cols = ["StartNodeID", "EndNodeID", "RelationshipType", "RelationshipDate_EndDate"] rows = [] # 路径加r前缀避免转义字符出错 xmlparse = Xet.parse(r'D:\Descargas\concatenated_lei2file_StartNodeID.xml') root = xmlparse.getroot() # 修正变量名,从根节点查找目标节点 Relationships = root.findall('./RelationshipRecord/Relationship') for elem in Relationships: # 直接在当前Relationship节点下查找子节点,加判空逻辑 StartNodeID = elem.find("./StartNode/StartNodeID").text if elem.find("./StartNode/StartNodeID") is not None else "" EndNodeID = elem.find("./EndNode/EndNodeID").text if elem.find("./EndNode/EndNodeID") is not None else "" RelationshipType = elem.find("RelationshipType").text if elem.find("RelationshipType") is not None else "" RelationshipDate_EndDate = elem.find("RelationshipEndDate").text if elem.find("RelationshipEndDate") is not None else "" # 缩进放到循环内,每条数据都追加 rows.append({ "StartNodeID": StartNodeID, "EndNodeID": EndNodeID, "RelationshipType": RelationshipType, "RelationshipDate_EndDate": RelationshipDate_EndDate }) df = pd.DataFrame(rows, columns=cols) # 输出加utf-8-sig编码,保证Excel打开不会乱码 df.to_csv(r'D:\Descargas\concatenated_lei2file_output.csv', index=False, encoding='utf-8-sig')
如果运行后还是找不到节点,可以先打印前几条节点的子标签确认实际结构:
for elem in Relationships[:5]: print([child.tag for child in elem.iter()]) break
内容的提问来源于stack exchange,提问作者mara875
相关产品推荐
相关产品推荐

