通过应用变换简化SVG - 减小文件大小
我经常会遇到一些结构像这样的SVG文件:
<svg:g
transform="translate(-251.5,36.5)"
id="g12578"
style="fill:#ffff00;fill-opacity:1">
<svg:rect
width="12"
height="12"
x="288"
y="35.999958"
id="rect12580"
style="fill:#ffff00;fill-opacity:1;stroke:#000000;stroke-width:1" />
</svg:g>
我想直接对坐标进行平移,并删除变换属性:
<svg:g
id="g12578"
style="fill:#ffff00;fill-opacity:1">
<svg:rect
width="12"
height="12"
x="36.5"
y="69.499958"
id="rect12580"
style="fill:#ffff00;fill-opacity:1;stroke:#000000;stroke-width:1" />
</svg:g>
你知道有没有简化SVG的脚本或程序吗?或者有没有Python的小代码可以解析SVG文件的?
这个脚本适合我特定的情况,但我希望能有一个通用的解决方案:
#http://epydoc.sourceforge.net/stdlib/xml.dom.minidom.Element-class.html
from xml.dom.minidom import parse, parseString
import re
f = open('/home/moose/mathe/svg/Solitaire-Board.svg', 'r')
xmldoc = parse(f)
p = re.compile('translate\(([-\d.]+),([-\d.]+)\)', re.IGNORECASE)
for node in xmldoc.getElementsByTagName('svg:g'):
transform_dict = node.attributes["transform"]
m = p.match(transform_dict.value)
if m:
x = float(m.group(1))
y = float(m.group(2))
child_rectangles = node.getElementsByTagName('svg:rect')
for rectangle in child_rectangles:
x_dict = rectangle.attributes["x"]
y_dict = rectangle.attributes["y"]
new_x = float(x_dict.value) + x
new_y = float(y_dict.value) + y
rectangle.setAttribute('x', str(new_x))
rectangle.setAttribute('y', str(new_y))
node.removeAttribute('transform')
print xmldoc.toxml()
我觉得如果能去掉变换属性,SVG的大小可以大幅度减小,而且不会影响质量。如果这个工具还能减少坐标的精度,删除不必要的区域,合理地进行分组和样式设置,那就太好了。
3 个回答
0
1) 你可以用正则表达式来解析和编辑它。这样你就能轻松获取翻译的值和 x、y 的坐标。
2) 如果你检查了 minidom,确认你唯一的问题就是 ':' 这个符号,那你可以先把 ':' 替换掉,编辑你需要的内容,然后再把它换回来。
3) 你可以参考这个问题: 有没有什么脚本化的 SVG 编辑器? 来学习如何更好地解析这种 XML 格式。
1
你可以看看 scour:
Scour 的目标是尽可能减小 SVG 文件的大小,同时保持文件的原始显示效果。不过,它并不是对所有文件都能完美处理,所以建议用户不要覆盖原始文件。
Scour 对 SVG 文件进行的优化包括:去掉空的元素、去掉元数据元素、去掉未使用的 id 属性值、去掉无法显示的元素、将坐标精简到一定的有效位数,以及去掉矢量编辑器的元数据。
3
我建议你使用 lxml
。这个库非常快,而且有很多好用的功能。如果你正确地声明了 svg
的命名空间前缀,就可以解析你的例子。这个操作其实很简单:
>>> svg = '<svg xmlns:svg="http://www.w3.org/2000/svg">' + example_svg + '</svg>'
现在你可以用 lxml.etree
(或者 xml.etree.ElementTree
)来解析它:
>>> doc = etree.fromstring(svg)
如果你使用 lxml
,你还可以利用 XPath 的功能:
>>> ns = {'svg': 'http://www.w3.org/2000/svg'}
>>> doc.xpath('//svg:g/@transform', namespaces=ns)
<<< ['translate(-251.5,36.5)']