功能介紹
主要是把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
里的fill
,stroke
, stop-color
,並且值不為none
或者transport
才會被提取到外部中。