基于SOURCE属性提取SOURCEFIELD子元素并生成字典的实现方法
解析XML生成SOURCE与SOURCEFIELD属性对应字典
需求描述
解析包含多个<SOURCE>元素的XML文件,每个<SOURCE>节点下包含多个带自有属性的<SOURCEFIELD>子元素,最终生成格式为{SOURCE_NAME: [SOURCEFIELD属性字典列表]}的字典结构,其中SOURCE_NAME为<SOURCE>元素的NAME属性值。
XML示例
<SOURCE BUSINESSNAME ="" DATABASETYPE ="Netezza" DBDNAME ="SHEDW_CORE" DESCRIPTION ="" NAME ="DIM_NRC_CUSTOMER_TMP" OBJECTVERSION ="1" OWNERNAME ="ADMIN" VERSIONNUMBER ="1"> <SOURCEFIELD BUSINESSNAME ="" DATATYPE ="numeric" DESCRIPTION ="" FIELDNUMBER ="1" FIELDPROPERTY ="0" FIELDTYPE ="ELEMITEM" HIDDEN ="NO" KEYTYPE ="NOT A KEY" LENGTH ="14" LEVEL ="0" NAME ="DIM_CUSTOMER_SQN" NULLABLE ="NULL" OCCURS ="0" OFFSET ="0" PHYSICALLENGTH ="12" PHYSICALOFFSET ="0" PICTURETEXT ="" PRECISION ="12" SCALE ="0" USAGE_FLAGS =""/> <SOURCEFIELD BUSINESSNAME ="" DATATYPE ="timestamp" DESCRIPTION ="" FIELDNUMBER ="2" FIELDPROPERTY ="0" FIELDTYPE ="ELEMITEM" HIDDEN ="NO" KEYTYPE ="NOT A KEY" LENGTH ="19" LEVEL ="0" NAME ="LOAD_END_DATE" NULLABLE ="NULL" OCCURS ="0" OFFSET ="14" PHYSICALLENGTH ="26" PHYSICALOFFSET ="12" PICTURETEXT ="" PRECISION ="26" SCALE ="6" USAGE_FLAGS =""/> </SOURCE> <SOURCE BUSINESSNAME ="" DATABASETYPE ="Netezza" DBDNAME ="SHEDW_CORE" DESCRIPTION ="" NAME ="SAT_CONTACT" OBJECTVERSION ="1" OWNERNAME ="ADMIN" VERSIONNUMBER ="1"> <SOURCEFIELD BUSINESSNAME ="" DATATYPE ="numeric" DESCRIPTION ="" FIELDNUMBER ="1" FIELDPROPERTY ="0" FIELDTYPE ="ELEMITEM" HIDDEN ="NO" KEYTYPE ="PRIMARY KEY" LENGTH ="14" LEVEL ="0" NAME ="SAT_CONTACT_SQN" NULLABLE ="NOTNULL" OCCURS ="0" OFFSET ="0" PHYSICALLENGTH ="12" PHYSICALOFFSET ="0" PICTURETEXT ="" PRECISION ="12" SCALE ="0" USAGE_FLAGS =""/> <SOURCEFIELD BUSINESSNAME ="" DATATYPE ="numeric" DESCRIPTION ="" FIELDNUMBER ="2" FIELDPROPERTY ="0" FIELDTYPE ="ELEMITEM" HIDDEN ="NO" KEYTYPE ="NOT A KEY" LENGTH ="14" LEVEL ="0" NAME ="CONTACT_SQN" NULLABLE ="NOTNULL" OCCURS ="0" OFFSET ="14" PHYSICALLENGTH ="12" PHYSICALOFFSET ="12" PICTURETEXT ="" PRECISION ="12" SCALE ="0" USAGE_FLAGS =""/> <SOURCEFIELD BUSINESSNAME ="" DATATYPE ="timestamp" DESCRIPTION ="" FIELDNUMBER ="3" FIELDPROPERTY ="0" FIELDTYPE ="ELEMITEM" HIDDEN ="NO" KEYTYPE ="NOT A KEY" LENGTH ="19" LEVEL ="0" NAME ="LOAD_DATE" NULLABLE ="NOTNULL" OCCURS ="0" OFFSET ="28" PHYSICALLENGTH ="26" PHYSICALOFFSET ="24" PICTURETEXT ="" PRECISION ="26" SCALE ="6" USAGE_FLAGS =""/> <SOURCEFIELD BUSINESSNAME ="" DATATYPE ="timestamp" DESCRIPTION ="" FIELDNUMBER ="4" FIELDPROPERTY ="0" FIELDTYPE ="ELEMITEM" HIDDEN ="NO" KEYTYPE ="NOT A KEY" LENGTH ="19" LEVEL ="0" NAME ="LOAD_END_DATE" NULLABLE ="NULL" OCCURS ="0" OFFSET ="47" PHYSICALLENGTH ="26" PHYSICALOFFSET ="50" PICTURETEXT ="" PRECISION ="26" SCALE ="6" USAGE_FLAGS =""/> <SOURCEFIELD BUSINESSNAME ="" DATATYPE ="varchar" DESCRIPTION ="" FIELDNUMBER ="5" FIELDPROPERTY ="0" FIELDTYPE ="ELEMITEM" HIDDEN ="NO" KEYTYPE ="NOT A KEY" LENGTH ="0" LEVEL ="0" NAME ="REC_SOURCE" NULLABLE ="NULL" OCCURS ="0" OFFSET ="66" PHYSICALLENGTH ="30" PHYSICALOFFSET ="76" PICTURETEXT ="" PRECISION ="30" SCALE ="0" USAGE_FLAGS =""/> </SOURCE>
现有问题代码
import xml.etree.ElementTree as ET if not ET.parse('C:\\Desktop\\xml\\m_DM_DIM_NRC_CUSTOMER.xml'): raise SyntaxError else: print("The XML is valid") tree = ET.parse('C:\\Desktop\\xml\\m_DM_DIM_NRC_CUSTOMER.xml') root = tree.getroot()][1]][1] # 语法错误 dd = [] for source in root.iter('SOURCE'): print("\n") sourcename = source.attrib['NAME'] print("*********** The DETAILS of SOURCE: %s: : ***********" %sourcename) print(source.attrib) print("*********** The COLUMN NAMES of SOURCE: %s ***********" % sourcename) for sourcefields in source.iter("SOURCEFIELD"): print(sourcefields.attrib) dd.append(sourcefields.attrib) dict[sourcename] = dd # 复用全局列表+误用内置类型名
问题分析
- 语法错误:
root = tree.getroot()][1]][1存在多余的括号和索引,应直接写root = tree.getroot() - 全局列表复用:
dd是全局列表,每次遍历<SOURCE>时未重置,导致所有<SOURCEFIELD>属性都被累积到同一个列表,最终所有SOURCE_NAME对应相同的字段集合 - 误用内置类型名:
dict是Python内置字典类型,不能用作自定义变量名,需替换为自定义变量(如result)
正确实现代码
import xml.etree.ElementTree as ET # 解析XML文件 try: tree = ET.parse('C:\\Desktop\\xml\\m_DM_DIM_NRC_CUSTOMER.xml') print("The XML is valid") except ET.ParseError: raise SyntaxError("Invalid XML file") root = tree.getroot() result = {} # 初始化结果字典 for source in root.iter('SOURCE'): sourcename = source.attrib['NAME'] # 为当前SOURCE创建单独的字段列表,避免跨SOURCE污染 field_list = [] for sourcefield in source.iter("SOURCEFIELD"): # 将SOURCEFIELD的属性字典加入列表 field_list.append(sourcefield.attrib) # 将当前SOURCE的字段列表映射到结果字典 result[sourcename] = field_list # 打印或使用结果 import pprint pprint.pprint(result)
预期输出格式
{ "DIM_NRC_CUSTOMER_TMP": [ {"BUSINESSNAME": "", "DATATYPE": "numeric", ...}, {"BUSINESSNAME": "", "DATATYPE": "timestamp", ...} ], "SAT_CONTACT": [ {"BUSINESSNAME": "", "DATATYPE": "numeric", ...}, {"BUSINESSNAME": "", "DATATYPE": "numeric", ...}, ... ] }
内容的提问来源于stack exchange,提问作者Debashish Das
相关产品推荐
相关产品推荐

