使用Python合并多SVG文件图层,解决重复层级问题
解决SVG嵌套图层合并问题
问题描述
现有Python代码可合并多个SVG文件,但无法正确处理嵌套图层结构——每个SVG的图层会重复创建(如重复的Layer1),期望将同ID的同层级图层合并,形成统一的嵌套结构。
当前合并后的图层结构
START -Layer1 --Layer2 ---Layer3 ----Layer3a -----PATH -Layer1 --Layer2 ---Layer3 ----Layer3b -----PATH -Layer1 --Layer2 ---Layer2a ----PATH -Layer1 --Layer2 ---Layer2b ----PATH
期望的图层结构
START -Layer1 --Layer2 ---Layer2a ----PATH ---Layer2b ----PATH ---Layer3 ----Layer3a -----PATH ----Layer3b -----PATH
当前代码
import os from xml.etree import ElementTree as ET #SVG files input folder svg_dir = './Import/' #New SVG merged_svg = ET.Element('svg') #Loop through SVG in folder for i, filename in enumerate(os.listdir(svg_dir)): #Check if SVG ends with "update.svg" if filename.endswith('update.svg'): #Open SVG and parse content svg_path = os.path.join(svg_dir, filename) svg_tree = ET.parse(svg_path) #Get root element of SVG svg_root = svg_tree.getroot() #Check if root element exists if svg_root is not None: if i == 0: #Add root element of first SVG merged_svg = svg_root else: #Merge root element of other SVG to the first for attr, value in svg_root.items(): merged_svg.set(attr, value) #Loop through each child element in root for child in svg_root: print(child) if isinstance(child, ET.Element): #Find element with same ID in merged SVG file existing_element = merged_svg.find('.//*[@id="%s"]' % child.get('id')) if existing_element is not None: #If element already exists - append to sub-child print("element already exists - append to sub-child") for sub_child in child: if isinstance(sub_child, ET.Element): existing_element.append(sub_child) else: #If the element does not exist print("element does not exist - append to child") merged_svg.append(child) # Write the merged SVG to a file merged_svg_file = open('./Export/COMBINED.svg', 'w') merged_svg_file.write(ET.tostring(merged_svg).decode()) merged_svg_file.close()
修改后的代码
原代码仅处理了根节点下的第一层元素,未递归处理嵌套的子图层。添加递归函数merge_elements,实现逐层查找同ID元素并合并子内容:
import os from xml.etree import ElementTree as ET def merge_elements(parent, new_element): """递归合并嵌套元素:查找父节点下同ID的元素,存在则合并子元素,不存在则添加""" elem_id = new_element.get('id') if not elem_id: # 无ID的元素直接添加 parent.append(new_element) return # 在当前父节点的直接子元素中查找同ID元素(确保层级匹配) existing_element = None for child in parent: if child.get('id') == elem_id: existing_element = child break if existing_element is not None: # 合并属性(新属性覆盖旧属性) for attr, value in new_element.items(): existing_element.set(attr, value) # 递归处理子元素 for sub_child in new_element: merge_elements(existing_element, sub_child) else: # 元素不存在,直接添加到当前父节点 parent.append(new_element) # SVG文件输入文件夹 svg_dir = './Import/' merged_svg = None # 遍历文件夹中的SVG文件 for filename in os.listdir(svg_dir): if filename.endswith('update.svg'): svg_path = os.path.join(svg_dir, filename) svg_tree = ET.parse(svg_path) svg_root = svg_tree.getroot() if svg_root is None: continue if merged_svg is None: # 初始化合并后的SVG为第一个文件的根节点 merged_svg = svg_root else: # 合并根节点属性 for attr, value in svg_root.items(): merged_svg.set(attr, value) # 递归合并根节点下的所有子元素 for child in svg_root: merge_elements(merged_svg, child) # 写入合并后的SVG文件 if merged_svg is not None: with open('./Export/COMBINED.svg', 'w') as f: f.write(ET.tostring(merged_svg).decode())
关键修改点
- 递归合并逻辑:新增
merge_elements函数,逐层处理嵌套元素,确保同ID的同层级图层被合并,避免跨层级错误。 - 层级匹配:在当前父节点的直接子元素中查找同ID元素,而非全局查找,保证图层结构的正确性。
- 属性合并:合并元素时用新元素的属性覆盖旧元素的同名属性,保留最新配置。
- 代码优化:使用
with语句管理文件,避免资源泄漏;调整初始化逻辑,代码更简洁清晰。
内容的提问来源于stack exchange,提问作者muckyu
相关产品推荐
相关产品推荐

