如何用Python生成器将XML数据转为结构合理的字典?
XML转字典优化:避免索引访问子容器内容
我有一段XML数据,希望用生成器将其整理为字典,且仅保留指定子容器。原代码如下:
import xml.etree.ElementTree as Etree xml_file = '\ <Container>\ <Main Type="main1" var1="var1"/>\ <SubContainer1>\ <Sub Type="sub1" var1="var1" var2="var2"/>\ <Sub Type="sub2" var1="var1" var2="var2"/>\ </SubContainer1>\ <SubContainer2>\ <Var ObjectId="0000000001" Name="Name1" Value="1" />\ <Var ObjectId="0000000001" Name="Name2" Value="2" />\ <Var ObjectId="0000000001" Name="Name3" Value="3" />\ <Var ObjectId="0000000001" Name="Name4" Value="4" />\ <Var ObjectId="0000000001" Name="Name5" Value="5" />\ <Var ObjectId="0000000001" Name="Name6" Value="6" />\ </SubContainer2>\ </Container>' xml_tree = Etree.fromstring(xml_file) xml_dict = {} sub_containers = ['SubContainer1','SubContainer2'] for c in sub_containers: xml_dict[c] = [{x.tag : x.attrib} for x in xml_tree.findall(f'.//{c}/*')] print(xml_dict)
原代码生成的字典结构中,每个子容器对应一个列表,访问元素必须通过xml_dict['SubContainer1'][0]这样的索引,操作繁琐。以下是两种优化方案:
方案1:按子元素标签分组
将同一子容器下的同标签元素整合到对应键的列表中,结构更清晰,无需通过外层索引访问标签组:
import xml.etree.ElementTree as Etree xml_file = '\ <Container>\ <Main Type="main1" var1="var1"/>\ <SubContainer1>\ <Sub Type="sub1" var1="var1" var2="var2"/>\ <Sub Type="sub2" var1="var1" var2="var2"/>\ </SubContainer1>\ <SubContainer2>\ <Var ObjectId="0000000001" Name="Name1" Value="1" />\ <Var ObjectId="0000000001" Name="Name2" Value="2" />\ <Var ObjectId="0000000001" Name="Name3" Value="3" />\ <Var ObjectId="0000000001" Name="Name4" Value="4" />\ <Var ObjectId="0000000001" Name="Name5" Value="5" />\ <Var ObjectId="0000000001" Name="Name6" Value="6" />\ </SubContainer2>\ </Container>' xml_tree = Etree.fromstring(xml_file) xml_dict = {} sub_containers = ['SubContainer1','SubContainer2'] for c in sub_containers: container_data = {} for elem in xml_tree.findall(f'.//{c}/*'): if elem.tag not in container_data: container_data[elem.tag] = [] container_data[elem.tag].append(elem.attrib) xml_dict[c] = container_data print(xml_dict)
输出结构:
{ 'SubContainer1': { 'Sub': [ {'Type': 'sub1', 'var1': 'var1', 'var2': 'var2'}, {'Type': 'sub2', 'var1': 'var1', 'var2': 'var2'} ] }, 'SubContainer2': { 'Var': [ {'ObjectId': '0000000001', 'Name': 'Name1', 'Value': '1'}, {'ObjectId': '0000000001', 'Name': 'Name2', 'Value': '2'}, {'ObjectId': '0000000001', 'Name': 'Name3', 'Value': '3'}, {'ObjectId': '0000000001', 'Name': 'Name4', 'Value': '4'}, {'ObjectId': '0000000001', 'Name': 'Name5', 'Value': '5'}, {'ObjectId': '0000000001', 'Name': 'Name6', 'Value': '6'} ] } }
访问方式:直接通过标签键获取所有同类型元素,比如xml_dict['SubContainer1']['Sub'];若需单个元素,再用索引定位(如xml_dict['SubContainer1']['Sub'][0])。
方案2:用元素唯一属性作为键
如果子元素存在唯一标识属性(如Sub的Type、Var的Name),可直接将该属性值作为键,实现无索引直接访问目标元素:
import xml.etree.ElementTree as Etree xml_file = '\ <Container>\ <Main Type="main1" var1="var1"/>\ <SubContainer1>\ <Sub Type="sub1" var1="var1" var2="var2"/>\ <Sub Type="sub2" var1="var1" var2="var2"/>\ </SubContainer1>\ <SubContainer2>\ <Var ObjectId="0000000001" Name="Name1" Value="1" />\ <Var ObjectId="0000000001" Name="Name2" Value="2" />\ <Var ObjectId="0000000001" Name="Name3" Value="3" />\ <Var ObjectId="0000000001" Name="Name4" Value="4" />\ <Var ObjectId="0000000001" Name="Name5" Value="5" />\ <Var ObjectId="0000000001" Name="Name6" Value="6" />\ </SubContainer2>\ </Container>' xml_tree = Etree.fromstring(xml_file) xml_dict = {} # 定义每个子容器对应的唯一属性键 container_key_map = { 'SubContainer1': 'Type', 'SubContainer2': 'Name' } for c, key_attr in container_key_map.items(): container_data = {} for elem in xml_tree.findall(f'.//{c}/*'): container_data[elem.attrib[key_attr]] = elem.attrib xml_dict[c] = container_data print(xml_dict)
输出结构:
{ 'SubContainer1': { 'sub1': {'Type': 'sub1', 'var1': 'var1', 'var2': 'var2'}, 'sub2': {'Type': 'sub2', 'var1': 'var1', 'var2': 'var2'} }, 'SubContainer2': { 'Name1': {'ObjectId': '0000000001', 'Name': 'Name1', 'Value': '1'}, 'Name2': {'ObjectId': '0000000001', 'Name': 'Name2', 'Value': '2'}, 'Name3': {'ObjectId': '0000000001', 'Name': 'Name3', 'Value': '3'}, 'Name4': {'ObjectId': '0000000001', 'Name': 'Name4', 'Value': '4'}, 'Name5': {'ObjectId': '0000000001', 'Name': 'Name5', 'Value': '5'}, 'Name6': {'ObjectId': '0000000001', 'Name': 'Name6', 'Value': '6'} } }
访问方式:直接通过属性值访问目标元素,比如xml_dict['SubContainer2']['Name3']即可获取对应Var元素的属性字典,完全无需索引。
内容的提问来源于stack exchange,提问作者rbx 775
相关产品推荐
相关产品推荐

