稍等片刻,正在加载中...

Python之处理svg文件中的style属性

功能介绍

主要是把svg图片中的style属性内部的值,放到外部。

demo.xml

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" xml:space="preserve"
     preserveAspectRatio="none"><defs></defs>
    <g transform="matrix(0.439528 0 0 0.439528 330.719764 171.306754)" id="图层_1">
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;"
      transform=" translate(-341.275, -21.812)" d="M 682.55 43.624 H 0 V 0 h 682.55 V 43.624 z" stroke-linecap="round"/>
</g>
</svg>

正则实现

from xml.dom import minidom
import re

def update_xml(xml_file_path):
    """
    功能:style属性移外部
    :param xml_file_path: xml 文件路径
    :return: 返回 xml 文件
    """
    dom = minidom.parse(xml_file_path)
    root = dom.documentElement
    svg_dom = root.toxml()
    styles = re.findall('style="[^"]+"', svg_dom)
    try:
        for style in styles:
            data_list = []
            attrs = re.findall('([\w-]+):\s*([^;]+)', style)
            name, value = attrs[-1]
            sub_value = value.replace("\"", "")
            attrs[-1] = (name, sub_value)
            for attr in attrs:
                key, value = attr
                if not value in ['butt']:
                    data_list.append(key + '="' + value + '"')
            svg_dom = svg_dom.replace(style, " ".join(data_list))
        with open(xml_file_path, 'w', encoding='utf-8') as f:
            f.write(svg_dom)
        return xml_file_path
    except Exception as e:
        print(f'update_xml : {e}')


if __name__ == '__main__':
    update_xml('demo.xml')

更新后的demo.xml

<svg preserveAspectRatio="none" version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink"><defs/>
    <g id="图层_1" transform="matrix(0.439528 0 0 0.439528 330.719764 171.306754)">
<path d="M 682.55 43.624 H 0 V 0 h 682.55 V 43.624 z" stroke-linecap="round" stroke="none" stroke-width="1"
      stroke-dasharray="none" stroke-dashoffset="0" stroke-linejoin="miter" stroke-miterlimit="4" fill="rgb(0,0,0)"
      fill-rule="nonzero" opacity="1" transform=" translate(-341.275, -21.812)"/>
</g>
</svg>

注意

  • svg 标签可能不及这几个标签的。可能会有多层标签里都有style内部属性。

由于本人正则不怎么会,所以在处理attrs = re.findall('([\w-]+):\s*([^;]+)', style)的时候,出现了attrs这个列表里最后一对元组里的第二个值是有一个双引号的"。
所以就采用了这种方式:

name, value = attrs[-1]
sub_value = value.replace("\"", "")

进行处理。如果您有更好的处理方式请在评论区告诉我或者私信也行,谢谢。

更新实现的功能

import cssutils
from xml.dom import minidom

def update_xml(xml_file_path):
    dom = minidom.parse(xml_file_path)
    root = dom.documentElement
    root = extract_change_style(root)
    with open(xml_file_path, 'w', encoding='utf-8') as f:
        f.write(root.toxml())
    return xml_file_path


def extract_change_style(node):
    """
    处理 xml 内部的 style
    :param node:
    :return:
    """
    for i in range(0, node.attributes.length):
        attr = node.attributes.item(i)
        attr_name = attr.name
        if attr_name == 'style':
            attr_value = attr.value
            sheet = cssutils.parseString("#rule{" + attr_value + "}")

            for rule in sheet.cssRules:
                if rule.type == rule.STYLE_RULE:
                    for property in rule.style:
                        if property.name in ['fill', 'stroke', 'stop-color']:
                            if not property.value in ['none', 'transport']:
                                node.setAttribute(property.name, property.value)
                                rule.style.removeProperty(property.name)

            text = sheet.cssText
            text = text.decode('utf-8').replace("#rule {", "").replace("}", "").replace("\n", "").replace("\r\n",
                                                                                                          "").replace(
                "    ", "")
            node.setAttribute("style", text)

    for i, child in enumerate(node.childNodes):
        if child.nodeType == 1:
            temp = extract_change_style(child)
            node.childNodes[i] = temp
    return node

上面的功能是实现:提取style里的fillstroke, stop-color,并且值不为none或者transport才会被提取到外部中。

posted @ 2020-12-02 17:52  一切皆往事  阅读(765)  评论(0编辑  收藏  举报