用Python替换SVG的内部内容
我有一个SVG模板,我正在复制并自定义它,以便为一个游戏制作几种不同的卡片和图块。我想用程序的方式(最好是用Python)来逐个卡片地更改模板中的元素。我发现有很多方法可以更改属性或CSS,但我找不到一个可以轻松解析现有SVG并替换元素的库。
我的模板的SVG大概长这样:
<!--Square 2" Tile Template -->
<svg xmlns="http://www.w3.org/2000/svg" width="181" height="181">
<text id="tile_text" y="90" width="100%"
style="text-align:center;font-family:Verdana;font-size:20">
TEXT TO REPLACE
</text>
</svg>
我看过Python的lxml
和xml.dom.minidom
,但这两个似乎都不支持像tile_text_element.innerHTML = "新图块名称"
这样的操作。谁能帮帮我?
补充一下我的工作流程,我正在为每张卡片创建一堆个性化的SVG,然后通过Inkscape批量渲染成PDF。
4 个回答
1
我觉得你可以用lxml这个库来实现,具体是通过Element
的text
属性来操作的:
>>> root = etree.Element("root")
>>> root.text = "TEXT"
>>> print(root.text)
TEXT
>>> etree.tostring(root)
b'<root>TEXT</root>'
1
你可以不使用Python来实现这个功能,svg支持参数
所以你可以使用:
<!--Square 2" Tile Template -->
<svg xmlns="http://www.w3.org/2000/svg" width="181" height="181">
<text id="tile_text" y="90" width="100%" style="text-align:center;font-family:Verdana;font-size:20" content-value="param(label)">default</text>
然后使用:
your.svg?label=New Tile Name
需要注意的是,w3.org上的示例是通过模拟参数来实现的,因为并不是所有浏览器都支持这个功能。不过你可以使用他们的模拟方法,但他们提到不建议在正式环境中使用:
请注意,这些示例是通过一个Javascript原型模拟的。它应该在Opera、Firefox和Safari等浏览器中工作,可能在其他浏览器(比如Chrome?插件?)也能用。这个脚本可以直接使用,并且是根据CC许可证发布的,但并不适合用作正式代码。内容创作者被鼓励尝试这个代码,并根据经验向SVG工作组(www-svg@w3.org)提出建议和反馈。
2
另一种方法是使用lxml,这个方法似乎有效,但要注意,代码质量不太好:
$ cat card.py
#!/usr/bin/env python
from lxml import etree
with open('card.svg') as card:
root = etree.fromstring(card.read())
root.find('.//{http://www.w3.org/2000/svg}text').text = "foobar"
print etree.tostring(root)
$ python card.py
<svg xmlns="http://www.w3.org/2000/svg" width="181" height="181">
<text id="tile_text" y="90" width="100%" style="text-align:center;font-family:Verdana;font-size:20">foobar</text>
</svg>
1
你可以使用ETXPath或者普通的XPath,这里有一种可能的方法:
from lxml import etree
SVGNS = u"http://www.w3.org/2000/svg"
svg = '''<!--Square 2" Tile Template -->
<svg xmlns="http://www.w3.org/2000/svg" width="181" height="181">
<text id="tile_text" y="90" width="100%"
style="text-align:center;font-family:Verdana;font-size:20">
TEXT TO REPLACE
</text>
</svg>'''
xml_data = etree.fromstring(svg)
# We search for element 'text' with id='tile_text' in SVG namespace
find_text = etree.ETXPath("//{%s}text[@id='tile_text']" % (SVGNS))
# find_text(xml_data) returns a list
# [<Element {http://www.w3.org/2000/svg}text at 0x106185ab8>]
# take the 1st element from the list, replace the text
find_text(xml_data)[0].text = 'BLAHBLAH'
new_svg = etree.tostring(xml_data)
print new_svg
然后就是结果。
<svg xmlns="http://www.w3.org/2000/svg" width="181" height="181">
<text id="tile_text" y="90" width="100%"
style="text-align:center;font-family:Verdana;font-size:20">BLAHBLAH</text>
</svg>
希望这对你有帮助。