You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何移除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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 13:55:20