如何使用Python合并不同子文件夹中同名的多个XML文件?
遍历子文件夹合并同名XML文件的实现方案
核心思路
- 遍历指定根目录下的所有一级子文件夹
- 逐个检查子文件夹中是否存在目标同名XML文件
- 解析每个有效XML的内容,提取需要合并的节点(保留原结构,避免重复根节点)
- 将合并后的完整XML写入指定输出目录
Python 实现代码
以下代码基于标准库xml.etree.ElementTree实现,无需额外安装依赖:
import os import xml.etree.ElementTree as ET from xml.dom import minidom def merge_xml_files(root_dir, target_xml_name, output_dir): # 创建输出目录(如果不存在) os.makedirs(output_dir, exist_ok=True) merged_root = None # 遍历根目录下的所有子文件夹 for subdir, _, files in os.walk(root_dir): # 跳过根目录本身,只处理子文件夹 if subdir == root_dir: continue # 检查当前子文件夹是否存在目标XML文件 if target_xml_name in files: xml_path = os.path.join(subdir, target_xml_name) try: # 解析XML文件 tree = ET.parse(xml_path) current_root = tree.getroot() # 初始化合并根节点(用第一个XML的根节点作为基准) if merged_root is None: merged_root = ET.Element(current_root.tag, current_root.attrib) # 将当前XML的所有子节点添加到合并根节点中 for child in current_root: merged_root.append(child) except ET.ParseError as e: print(f"解析文件 {xml_path} 出错: {e}") except Exception as e: print(f"处理文件 {xml_path} 时发生未知错误: {e}") # 如果有合并内容,写入输出文件 if merged_root is not None: # 格式化XML输出(美化缩进) rough_string = ET.tostring(merged_root, 'utf-8') reparsed = minidom.parseString(rough_string) pretty_xml = reparsed.toprettyxml(indent=" ") # 去除自动添加的xml声明重复问题 pretty_xml = '\n'.join([line for line in pretty_xml.split('\n') if line.strip() and not line.strip().startswith('<?xml')]) output_path = os.path.join(output_dir, f"merged_{target_xml_name}") with open(output_path, 'w', encoding='utf-8') as f: f.write('<?xml version="1.0" encoding="UTF-8"?>\n') f.write(pretty_xml) print(f"合并完成,文件已保存至: {output_path}") else: print("未找到任何可合并的XML文件") # 示例调用 if __name__ == "__main__": # 替换为你的实际路径和文件名 ROOT_DIRECTORY = "./your_root_folder" TARGET_XML = "data.xml" # 子文件夹中同名的XML文件名 OUTPUT_DIRECTORY = "./merged_output" merge_xml_files(ROOT_DIRECTORY, TARGET_XML, OUTPUT_DIRECTORY)
关键说明
- 跳过根目录:
os.walk会遍历所有层级,这里通过判断subdir == root_dir跳过根目录,只处理一级子文件夹 - XML合并逻辑:以第一个XML的根节点作为合并后的根节点,后续所有XML的子节点直接追加,确保结构合法
- 错误处理:捕获解析错误和未知异常,避免单个文件出错导致整个流程中断
- 格式化输出:使用
minidom美化XML缩进,同时手动添加标准XML声明,避免重复
注意事项
如果你的XML包含命名空间,需要在解析时处理命名空间前缀,否则可能导致节点无法正确识别。可以通过ET.register_namespace注册命名空间,或者在解析时忽略前缀(根据实际需求调整)。
内容的提问来源于stack exchange,提问作者Elena Dobrovskiy
相关产品推荐
相关产品推荐

