如何移除XML或Python对象中fill属性值为none的SVG元素
问题描述
我正在使用xmltodict库读取文件夹中的多个SVG文件并合并为一个SVG库。现在需要移除其中所有fill属性值为none的SVG元素(例如<path d="M0 0h24v24H0V0z" fill="none"/>、<rect fill="none" height="24" width="24"/>这类元素)。可以选择从Python对象(OrderedDict和列表形式)或XML本身进行移除,哪种方式简便都行。
XML示例
<?xml version="1.0" encoding="utf-8"?> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <defs> <style>.icon { display: none } .icon:target { display: inline }</style> </defs> <svg viewBox="0 0 24 24"> <g class="icon" id="action.nightlight-round"> <path d="M0 0h24v24H0V0z" fill="none"/> <path d="M12.01 12c0-3.57 2.2-6.62 5.31-7.87.89-.36.75-1.69-.19-1.9-1.1-.24-2.27-.3-3.48-.14-4.51.6-8.12 4.31-8.59 8.83C4.44 16.93 9.13 22 15.01 22c.73 0 1.43-.08 2.12-.23.95-.21 1.1-1.53.2-1.9-3.22-1.29-5.33-4.41-5.32-7.87z"/> </g> </svg> <svg viewBox="0 0 24 24"> <g class="icon" id="action.not-started"> <g> <rect fill="none" height="24" width="24"/> <path d="M12,2C6.48,2,2,6.48,2,12c0,5.52,4.48,10,10,10s10-4.48,10-10C22,6.48,17.52,2,12,2z M11,16H9V8h2V16z M12,16V8l5,4L12,16z"/> </g> </g> </svg> </svg>
Python对象示例
from collections import OrderedDict # 解析后的OrderedDict结构 svg_dict = OrderedDict([('svg', OrderedDict([('@xmlns', 'http://www.w3.org/2000/svg'), ('@xmlns:xlink', 'http://www.w3.org/1999/xlink'), ('defs', [OrderedDict([('style', '.icon { display: none }\n\t\t\t.icon:target { display: inline }')])]), ('svg', [OrderedDict([('@viewBox', '0 0 24 24'), ('g', OrderedDict([('@class', 'icon'), ('@id', 'action.nightlight-round'), ('path', [OrderedDict([('@d', 'M0 0h24v24H0V0z'), ('@fill', 'none')]), OrderedDict([('@d', 'M12.01 12c0-3.57 2.2-6.62 5.31-7.87.89-.36.75-1.69-.19-1.9-1.1-.24-2.27-.3-3.48-.14-4.51.6-8.12 4.31-8.59 8.83C4.44 16.93 9.13 22 15.01 22c.73 0 1.43-.08 2.12-.23.95-.21 1.1-1.53.2-1.9-3.22-1.29-5.33-4.41-5.32-7.87z')])])]))]), OrderedDict([('@viewBox', '0 0 24 24'), ('g', OrderedDict([('@class', 'icon'), ('@id', 'action.not-started'), ('g', OrderedDict([('rect', OrderedDict([('@fill', 'none'), ('@height', '24'), ('@width', '24')])), ('path', OrderedDict([('@d', 'M12,2C6.48,2,2,6.48,2,12c0,5.52,4.48,10,10,10s10-4.48,10-10C22,6.48,17.52,2,12,2z M11,16H9V8h2V16z M12,16V8l5,4L12,16z')]))]))]))])])]))])
解决方案
方案一:处理Python OrderedDict对象
如果已经将SVG解析为OrderedDict结构,可以用递归遍历的方式过滤掉所有@fill="none"的元素。
import xmltodict from collections import OrderedDict def remove_fill_none_elements(obj): # 处理列表:过滤并递归处理每个元素 if isinstance(obj, list): cleaned_list = [] for item in obj: if isinstance(item, dict): # 跳过fill为none的元素 if item.get('@fill') == 'none': continue cleaned_item = remove_fill_none_elements(item) cleaned_list.append(cleaned_item) else: cleaned_list.append(item) return cleaned_list # 处理字典/OrderedDict:递归处理每个键值对 elif isinstance(obj, (dict, OrderedDict)): cleaned_dict = type(obj)() for key, value in obj.items(): # 如果值是fill为none的字典,跳过该键值对 if isinstance(value, dict) and value.get('@fill') == 'none': continue cleaned_value = remove_fill_none_elements(value) cleaned_dict[key] = cleaned_value return cleaned_dict # 其他类型直接返回 else: return obj # 使用示例 # 1. 读取合并后的SVG文件 with open('merged.svg', 'r', encoding='utf-8') as f: svg_content = f.read() # 2. 解析为OrderedDict svg_dict = xmltodict.parse(svg_content) # 3. 清理元素 cleaned_svg_dict = remove_fill_none_elements(svg_dict) # 4. 转回XML并保存 cleaned_svg = xmltodict.unparse(cleaned_svg_dict, pretty=True) with open('cleaned_merged.svg', 'w', encoding='utf-8') as f: f.write(cleaned_svg)
方案二:直接处理XML文本(推荐)
用lxml库通过XPath直接定位并删除所有fill="none"的元素,代码更简洁直观,无需处理复杂的嵌套结构。
from lxml import etree # 1. 读取SVG内容 with open('merged.svg', 'r', encoding='utf-8') as f: svg_content = f.read() # 2. 解析XML,指定SVG命名空间 ns = {'svg': 'http://www.w3.org/2000/svg'} root = etree.fromstring(svg_content.encode('utf-8')) # 3. 定位所有fill="none"的SVG元素 fill_none_elements = root.xpath('//svg:*[@fill="none"]', namespaces=ns) # 4. 删除这些元素 for elem in fill_none_elements: elem.getparent().remove(elem) # 5. 转回XML并保存 cleaned_svg = etree.tostring(root, encoding='utf-8', pretty_print=True).decode('utf-8') with open('cleaned_merged.svg', 'w', encoding='utf-8') as f: f.write(cleaned_svg)
内容的提问来源于stack exchange,提问作者njminchin
相关产品推荐
相关产品推荐

