【问题标题】:Why are text objects altered when modifying SVG files with BeautifulSoup?使用 BeautifulSoup 修改 SVG 文件时为什么会更改文本对象?
【发布时间】:2017-09-16 05:11:49
【问题描述】:

我正在使用 python3 中的 BeautifulSoup 模块来修改我用 Inkscape 创建的一些 svg 文件。具体来说,我正在修改这些文件中的一些文本,并在某些情况下更改某些对象的颜色。我注意到,无论我做什么,所有文本的位置总是在输出 svg 文件中移动。 例如参见: svg in/out files + png versions

与原始文件相比,输出 svg 中的文本对象的大小似乎有所不同。我可以将文本对象从输出文件复制到原始文件,但我不再看到这种转变,但这是一个烦人的解决方案。

有谁知道导致文本对象大小发生这种变化的原因以及可以防止这种变化吗?

这是我运行的一段代码示例(输入和输出 svg 的副本在上面的链接中):

from bs4 import BeautifulSoup

svgFile = "test_in.svg"
outputFile = "test_out.svg"

svg = open(svgFile, 'r').read()
soup = BeautifulSoup(svg, features = 'xml')
texts = soup.findAll('text')

for t in texts:
    if t['id'] == 'testID':
        print(t, '\n')
        t.contents[0].string = 'new text'
        print(t, '\n')

# Output the edited SVG file
f = open(outputFile, "w")
f.write(soup.prettify())
f.close()

xml/svg 树中的文本元素似乎没有任何变化,所以我觉得问题必须来自对文件其他部分的更改。 (另外,我可以省略t.contents[0].string = 'new text' 并且文本移动仍然发生。)第一个print(t) 给出:

<text id="testID" inkscape:label="#text3581" sodipodi:linespacing="125%" style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial" transform="matrix(0,1,-1,0,0,0)" x="449.63721" xml:space="preserve" y="-280.92737"><tspan id="tspan3583" sodipodi:role="line" style="font-size:14px;font-weight:normal;-inkscape-font-specification:Arial" x="449.63721" y="-280.92737">Text to change</tspan></text>

第二个 print(t) 的输出看起来完全一样,除了 'text to change' 现在是 'new text'

<text id="testID" inkscape:label="#text3581" sodipodi:linespacing="125%" style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial" transform="matrix(0,1,-1,0,0,0)" x="449.63721" xml:space="preserve" y="-280.92737"><tspan id="tspan3583" sodipodi:role="line" style="font-size:14px;font-weight:normal;-inkscape-font-specification:Arial" x="449.63721" y="-280.92737">new text</tspan></text> 

任何见解都将不胜感激!

【问题讨论】:

  • 请发布一个在转换过程中移动的文本对象的小 svg 示例。
  • 已编辑以包含输入和输出 svg 文件的 png 版本

标签: python python-3.x svg beautifulsoup inkscape


【解决方案1】:

您正在通过插入换行符并调用prettify() 添加额外的空格。

   <tspan id="tspan3583" sodipodi:role="line" style="font-size:14px;font-weight:normal;-inkscape-font-specification:Arial" x="449.63721" y="-280.92737">
    new text
   </tspan>

“新文本”之前有四个额外的空格。

通常不会有问题。默认情况下,在 XML 中,元素开头的空格会被去除。不幸的是,您的 SVG 文件在您的文本元素中具有以下属性:

xml:space="preserve"

这告诉浏览器您关心这些空间,并且希望它们被保留和显示。

您有两种解决方案:

  1. 停止添加换行符和/或美化
  2. 检查并删除目标文本元素中的任何xml:space 属性。或者将值从 "preserve" 更改为 "default"

【讨论】:

  • 我知道这是几个月前的事了,但我终于开始测试了。解决方案 1 效果很好。我所要做的就是用f.write(str(soup)) 替换f.write(soup.prettify())。就像您指出的那样,这会停止添加换行符和前导空格。
【解决方案2】:

我遇到了同样的问题。问题是当 bs4 解析文件时,它会将文本内容添加到新行中,因此在文本之前和之后添加了额外的空格,这就是它在 svg 内移动的原因。

这是您输入的 svg 文件的屏幕截图。您会看到文本与标签在同一行

在您的输出 svg 文件(如下)中,您将看到在 bs4 解析后,“新文本”内容与标签位于单独的一行。同样发生的情况是,现在文本内容前后有很多空白,这就是导致其在 svg 图像中的位置发生变化的原因。我现在也遇到这个问题了,不知道怎么解决的。

【讨论】:

  • 我想出的花哨的解决方案是在使用 bs4 更改之前将文本居中。空白仍然会被添加,但文本不会移动。既然我知道了问题的实际根源,我可能会尝试花一些时间来尝试提出一个更优雅的解决方案。感谢您指出这一点。
猜你喜欢
  • 2013-11-13
  • 2011-08-04
  • 1970-01-01
  • 2010-09-09
  • 1970-01-01
  • 1970-01-01
  • 2016-02-27
  • 2012-09-30
  • 1970-01-01
相关资源
最近更新 更多