【问题标题】:Parsing svg in python在python中解析svg
【发布时间】:2014-03-18 14:36:24
【问题描述】:

我有 SVG 和 html 文件,其中有几个 java 脚本标签,我需要找到所有脚本标签并在第一个脚本标签之前和最后一个脚本标签之后插入注释。我正在尝试使用 Beautifulsoup 来实现它。它适用于 HTML 版本,但对于 SVG,它会抛出错误。

 //for html version of file, working as expected
 soup = BeautifulSoup(data,selfClosingTags=['link','meta'])
 for num,tag in enumerate(soup.findAll('script')):
        if num==0:
            soup.head.insert(-1,startcomment)
        tag.extract()
        soup.head.insert(len(-1,tag)
        if num==len(soup.findAll('script'))-1:
            soup.head.insert(-1,endcomment)

但是现在,当我尝试在第一行中实现与 soup = BeautifulSoup(data,"xml") 相同的 svg 时,它会引发异常.. svg 也是 xml?所以我应该可以这样做

更新 - SVG 格式

<?xml version="1.0"?>
<?xml-stylesheet href="../../../some.css" type="text/css"?>
<svg id="mycontent" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"   xmlns:svg="http://www.w3.org/2000/svg" version="1.2" baseProfile="tiny" focusable="true" onload="Jsfunction.load()">
<script xlink:href="../first.js" />
<script xlink:href="../second.js" />
<script xlink:href="../third.js" />
</svg>

应该改为

<?xml version="1.0"?>
<?xml-stylesheet href="../../../some.css" type="text/css"?>
<svg id="mycontent" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"   xmlns:svg="http://www.w3.org/2000/svg" version="1.2" baseProfile="tiny" focusable="true" onload="Jsfunction.load()">
<!-- some comment -->
<script xlink:href="../first.js" />
<script xlink:href="../second.js" />
<script xlink:href="../third.js" />
<!-- end comment -->
</svg>

【问题讨论】:

  • 它会抛出什么异常?您使用的是哪个版本的 BeautifulSoup?
  • BS 版本 3.2.1,例外是与 str 和 bool 值有关的东西,我认为这是由于 svg 额外的参数。我现在没有office系统,所以不能准确,明天更新。但是我想为所有脚本标签读取这个xml并在之前和之后输入cmets......所有脚本标签将一个接一个
  • BeautifulSoup 3 开发多年前已停止,您真的想改用 BeautifulSoup 4(安装 lxml 来处理此处的 XML 解析)。
  • 是的,我有 lxml 并且可以升级 BS4(如果它支持 python 2.7.x)
  • 支持python 2.7,是的。

标签: python xml python-2.7 xml-parsing beautifulsoup


【解决方案1】:

使用 BeautifulSoup 版本 4,而不是 3,并安装 lxml 来处理 XML 解析。

目前(从 4.3.2 版开始),BeautifulSoup 确实忽略了处理指令(如 &lt;?xml-stylesheet?&gt; 指令),请参阅 bug 1294645。您可以通过修补树构建器来解决此问题:

from bs4.builder import LXMLTreeBuilderForXML
from bs4 import ProcessingInstruction

def handle_pi(self, target, data):
    self.soup.endData()
    self.soup.handle_data(target + ' ' + data)
    self.soup.endData(ProcessingInstruction)

LXMLTreeBuilderForXML.pi = handle_pi

该错误已被标记为已解决,从 BeautifulSoup 4.4(2015 年 7 月发布)开始,您不再需要上述解决方法。

您希望将script 标签列表存储在一个变量中,这样您就可以访问第一个和最后一个标签而无需循环:

from bs4 import BeautifulSoup, Comment

soup = BeautifulSoup(data, 'xml')
start_comment = soup.new_string('some comment', Comment)
end_comment = soup.new_string('end comment', Comment)

script_tags = soup.find_all('script')
script_tags[0].insert_before(start_comment)
script_tags[-1].insert_after(end_comment)

对于您的示例 SVG 文档,结果如下:

>>> print soup.prettify(formatter='xml')
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="../../../some.css" type="text/css"?>
<svg:svg baseProfile="tiny" focusable="true" id="mycontent" onload="Jsfunction.load()" version="1.2" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 <!--some comment-->
 <svg:script xlink:href="../first.js"/>
 <svg:script xlink:href="../second.js"/>
 <svg:script xlink:href="../third.js"/>
 <!--end comment-->
</svg:svg>

【讨论】:

  • 看起来不错,但是在重新打印时删除了我的样式表和 svg 标签中的许多参数.. 是因为美化.. 任何打印数据的方式
  • @DevC:啊,我错过了处理说明。我的猜测是 Beautifulsoup 不支持 PI,最好在这里使用另一个库。虽然 BS4 也尝试处理 XML,但这不是它的核心优势。
  • 你能提出一些建议吗,只要它支持 Python 2.7,我愿意接受任何事情
  • docs.python.org/2/library/xml.etree.elementtree.html 是标准库的一部分。 :-) lxml,您已经安装,支持相同的 API,但有额外的细节。
  • @DevC:注意:我猜错了。 BeautifulSoup 确实支持 PI,但初始解析不包括样式表 PI。正在调查。
猜你喜欢
  • 2013-03-29
  • 1970-01-01
  • 2020-08-28
  • 1970-01-01
  • 1970-01-01
  • 2014-01-15
  • 2013-07-08
  • 2021-10-02
  • 1970-01-01
相关资源
最近更新 更多