简体   繁体   English

用Python替换SVG的内部内容

[英]Replacing inner contents of an SVG in Python

I have an svg template that I am copying and customizing to create several different cards and tiles for a game. 我有一个svg模板,我正在复制和自定义为游戏创建几个不同的卡和磁贴。 I want to programmatically (in Python, preferably) change elements from the template per-card. 我想以编程方式(在Python中,最好)从每张卡的模板中更改元素。 I seem to have no trouble finding ways to change attributes or css, but I'm having trouble finding a library where I can easily parse an existing svg and replace elements. 我似乎没有找到改变属性或css的方法,但我找不到一个库,我可以很容易地解析现有的svg并替换元素。

The svg of my template looks somewhat like this: 我的模板的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>

I have looked at Python's lxml and xml.dom.minidom but neither of them seem to support something like tile_text_element.innerHTML = "New Tile Name" . 我看过Python的lxmlxml.dom.minidom但它们似乎都不支持像tile_text_element.innerHTML = "New Tile Name" Help? 救命?

EDIT: 编辑:

To add a little bit about my workflow, I am creating a bunch of individualized svgs for each card, then batch rendering them to pdf through inkscape. 为了增加我的工作流程,我为每张卡创建了一堆个性化的svgs,然后通过inkscape批量渲染为pdf。

Another way is to use lxml, seems to work, WARNING bad quality code: 另一种方法是使用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>

You can do with ETXPath or just XPath, but here a possible way: 您可以使用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

Then the result. 然后是结果。

<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>

Hope it helps. 希望能帮助到你。

You can do this without Python, svg support parameters 你可以在没有Python,svg支持参数的情况下做到这一点

So you may use 所以你可以使用

<!--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>

and use: 并使用:

your.svg?label=New Tile Name

Note that the working example on w3.org emulates parameters, as not every browser seems to support it, but you can reuse their emulation, but they state you should not use it in production: 请注意,w3.org上的工作示例模拟参数,因为并非每个浏览器都支持它,但您可以重用它们的模拟,但它们声明您不应该在生产中使用它:

Note that these examples are emulated by a Javascript prototype. 请注意,这些示例由Javascript原型模拟。 It should work in Opera, Firefox, and Safari, and maybe others (Chrome? Plugins?). 它应该适用于Opera,Firefox和Safari,以及其他(Chrome?插件?)。 The script may be used as is, and is released under a CC license, but it is not intended as production code. 该脚本可以按原样使用,并在CC许可下发布,但不作为生产代码。 Content authors are encouraged to experiment with this code, and to comment to the SVG WG at www-svg@w3.org with suggestions and critiques of the specification based on experience. 鼓励内容作者尝试使用此代码,并在www-svg@w3.org上向SVG WG发表评论,并根据经验对规范提出建议和批评。

I think you can do it in lxml with text property of Element : 我认为你可以在lxml中使用Element text属性来完成它:

Elements contain text 元素包含文本

>>> root = etree.Element("root")
>>> root.text = "TEXT"

>>> print(root.text)
TEXT

>>> etree.tostring(root)
b'<root>TEXT</root>'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM