将XML文本转换为指定格式Python列表的问题求助
问题解决:XML转指定Python列表结构的错误修复
问题背景
需要将给定XML文本转换为指定结构的Python列表:
<heading>标签内容对应输出的heading字段<subheading>下的<item>内容对应对应heading下的subheading字段
原代码尝试用嵌套列表实现,但出现所有item被追加到count_item的每个子列表的问题,原代码及测试数据如下:
原代码
output = [ { 'heading':'', 'subheading':[ { 'subheading':'' } ] } ] import re heading_list = re.findall('<heading>.+?</heading>',text) subheading_list = re.findall('<item\d+?>.*?</item\d+?>',text) no_of_items = 0 count_item = [[]]*len(heading_list) for num,sub in enumerate(subheading_list): if '<item1>' in sub and num!=0: no_of_items+=1 count_item[no_of_items].append(sub) else: count_item[no_of_items].append(sub)
测试XML文本
text = """<?xml version="1.0"?><mainmodule><module1><heading>Lesson 01: Design Authorization</heading><subheading><item1>Learning Objectives</item1><item2>Choosing an Authorization Approach</item2><item3>Access Management Solution</item3></subheading></module1><module2><heading>Lesson 02: Design a Solution for Logging and Monitoring</heading><subheading><item1>Learning Objectives</item1><item2>Monitoring Tools</item2><item3>Azure Monitor Health and Availability Monitoring</item3><item4>Initiating Automated Response Using Action Groups</item4><item5>Configure and Manage Alerts</item5><item6>Demo Azure Logging and Monitoring</item6><item7>Demo Azure Alerts</item7><item8>Recap</item8></subheading></module2><module3><heading>Lesson 03: Design for High Availability</heading><subheading><item1>Learning Objectives</item1><item2>Architecture Best Practices for Reliability into Categories</item2><item3>Solution for Recovery in Different Regions</item3><item4>Solution for Azure Backup Management</item4><item5>Solution for Data Archiving and Retention</item5></subheading></module3></mainmodule>"""
期望输出
output = [{ 'heading': 'Lesson 01: Design Authorization', 'subheading': [{'subheading': 'Learning Objectives'}, {'subheading': 'Choosing an Authorization Approach'}, {'subheading': 'Access Management Solution'}]}, { 'heading': 'Lesson 02: Design a Solution for Logging and Monitoring', 'subheading': [{'subheading': 'Learning Objectives'}, {'subheading': 'Monitoring Tools'}, {'subheading': 'Azure Monitor Health and Availability Monitoring'}, {'subheading': 'Initiating Automated Response Using Action Groups'}, {'subheading': 'Configure and Manage Alerts'}, {'subheading': 'Demo Azure Logging and Monitoring'}, {'subheading': 'Demo Azure Alerts'}, {'subheading': 'Recap'}]}, { 'heading': 'Lesson 03: Design for High Availability', 'subheading': [{'subheading': 'Learning Objectives'}, {'subheading': 'Architecture Best Practices for Reliability into Categories'}, {'subheading': 'Solution for Recovery in Different Regions'}, {'subheading': 'Solution for Azure Backup Management'}, {'subheading': 'Solution for Data Archiving and Retention'}]} ]
问题原因
- 列表引用错误:
count_item = [[]]*len(heading_list)会创建多个指向同一个空列表的引用,修改任意一个子列表都会同步影响所有子列表,导致所有item被追加到每个子列表中。 - 正则提取逻辑不严谨:全局提取所有heading和item,没有关联每个
module下的对应关系,容易出现匹配错位。
修正方案
方案一:修正正则逻辑(关联module层级)
先拆分每个module,再分别提取每个module内的heading和对应item,同时修复列表引用问题:
import re text = """<?xml version="1.0"?><mainmodule><module1><heading>Lesson 01: Design Authorization</heading><subheading><item1>Learning Objectives</item1><item2>Choosing an Authorization Approach</item2><item3>Access Management Solution</item3></subheading></module1><module2><heading>Lesson 02: Design a Solution for Logging and Monitoring</heading><subheading><item1>Learning Objectives</item1><item2>Monitoring Tools</item2><item3>Azure Monitor Health and Availability Monitoring</item3><item4>Initiating Automated Response Using Action Groups</item4><item5>Configure and Manage Alerts</item5><item6>Demo Azure Logging and Monitoring</item6><item7>Demo Azure Alerts</item7><item8>Recap</item8></subheading></module2><module3><heading>Lesson 03: Design for High Availability</heading><subheading><item1>Learning Objectives</item1><item2>Architecture Best Practices for Reliability into Categories</item2><item3>Solution for Recovery in Different Regions</item3><item4>Solution for Azure Backup Management</item4><item5>Solution for Data Archiving and Retention</item5></subheading></module3></mainmodule>""" # 提取每个module的完整内容 module_pattern = re.compile(r'<module\d+?>(.*?)</module\d+?>', re.DOTALL) modules = module_pattern.findall(text) output = [] for module in modules: # 提取当前module的heading文本 heading_match = re.search(r'<heading>(.*?)</heading>', module) heading = heading_match.group(1) if heading_match else "" # 提取当前module下所有item的文本 items = re.findall(r'<item\d+?>(.*?)</item\d+?>', module) subheading_list = [{'subheading': item} for item in items] output.append({ 'heading': heading, 'subheading': subheading_list }) # 输出验证 print(output)
方案二:使用XML解析库(更可靠)
正则处理XML容易出现边界错误,推荐使用Python内置的xml.etree.ElementTree解析,更符合XML结构的处理逻辑:
import xml.etree.ElementTree as ET text = """<?xml version="1.0"?><mainmodule><module1><heading>Lesson 01: Design Authorization</heading><subheading><item1>Learning Objectives</item1><item2>Choosing an Authorization Approach</item2><item3>Access Management Solution</item3></subheading></module1><module2><heading>Lesson 02: Design a Solution for Logging and Monitoring</heading><subheading><item1>Learning Objectives</item1><item2>Monitoring Tools</item2><item3>Azure Monitor Health and Availability Monitoring</item3><item4>Initiating Automated Response Using Action Groups</item4><item5>Configure and Manage Alerts</item5><item6>Demo Azure Logging and Monitoring</item6><item7>Demo Azure Alerts</item7><item8>Recap</item8></subheading></module2><module3><heading>Lesson 03: Design for High Availability</heading><subheading><item1>Learning Objectives</item1><item2>Architecture Best Practices for Reliability into Categories</item2><item3>Solution for Recovery in Different Regions</item3><item4>Solution for Azure Backup Management</item4><item5>Solution for Data Archiving and Retention</item5></subheading></module3></mainmodule>""" # 解析XML字符串 root = ET.fromstring(text) output = [] # 遍历所有module节点 for module in root.findall('.//module*'): # 获取heading文本 heading = module.find('heading').text # 获取subheading下的所有item节点 subheading_node = module.find('subheading') items = subheading_node.findall('.//*') # 转换为指定格式的列表 subheading_list = [{'subheading': item.text} for item in items] output.append({ 'heading': heading, 'subheading': subheading_list }) # 输出验证 print(output)
验证结果
两种方案均可生成与期望格式完全一致的输出,解决了原代码中item错位、子列表同步更新的问题。
内容的提问来源于stack exchange,提问作者nikhil kumar
相关产品推荐
相关产品推荐

