【问题标题】:How to parse broken XML in Python?如何在 Python 中解析损坏的 XML?
【发布时间】:2010-08-26 17:18:12
【问题描述】:

我无法影响的服务器发送非常损坏的 XML。

具体来说,Unicode WHITE STAR 将被编码为 UTF-8 (E2 98 86),然后使用 Latin-1 转换为 HTML 实体表。我得到的是一个文件中的â 98 86(9 个字节),该文件被声明为没有 DTD 的 utf-8。

我无法以一种不会造成不可逆转的混乱的方式来配置 W3C tidy。我只找到了如何让 lxml 静默地跳过它。 SAX 使用 Expat,遇到此问题后无法恢复。出于速度原因,我想避免使用 BeautifulSoup。

还有什么?

【问题讨论】:

  • 不清楚:您是说服务器正在发送 XML 标头:"" xml 某处包含:"&acirc\ x98\x86" ?
  • 没错。我不知道服务器在什么时候对实体进行编码,所以我不愿意在调用解析器之前将其反转。
  • lxml.html 解析器(可能还有 Beautiful Soup )可以解析损坏的 XML,但他们无法修复它,所以你会得到一个 Unicode WHITE STAR (而且我认为你无法修复它也可以使用 SAX 实体处理程序)。在将字节流传递给解析器之前,您可能必须使用 re.sub 和 htmlentitydefs 修复字节流。 (我想知道什么样的进程可以写出这种损坏的输出?进程的一部分必须认为它正在编写 Latin-1 HTML,而另一部分认为它正在生成 UTF8 XML!)
  • 在没有原生 unicode 支持的语言中容易犯错误。 AFAIK 服务器是用 PHP 编写的...
  • 如果 XML 格式不正确,即损坏,则让生成它的人正确生成它。类似的,如果它不符合它应该符合的 DTD 或模式,则返回给发送者。

标签: python xml


【解决方案1】:

BeautifulSoup 在这种情况下是你最好的选择。我建议在完全排除 BeautifulSoup 之前进行分析。

【讨论】:

  • "[...] 你并不关心 HTML 应该是什么样子。这个解析器也不关心。" :-)
  • 我做到了,它比我现在使用的 lxml.objectify 慢几个数量级(在 UI 中接受一些损坏的字符串)
  • @Tobias 你能发布一些实际结果和版本号吗?将有助于其他人参考。是的,我知道这是一个老问题——以防万一。 :)
【解决方案2】:

可能是这样的:

import htmlentitydefs as ents
from lxml import etree  # or maybe 'html' , if the input is still more broken
def repl_ent(m): 
     return ents.entitydefs[m.group()[1:-1]]
goodxml = re.sub( '&\w+;', repl_ent, badxml )
etree.fromstring( goodxml )

【讨论】:

  • 您需要从 htmlentitydefs 中删除五个 XML 实体以避免转义 .
  • 正如我所说,我不愿意这样做,因为它看起来像服务器只对一个特定标签的内容进行实体编码。
  • 问题是我不认为你可以从 SAX 或 SAX 过滤器中做到这一点,所以你必须下拉到 XMLReader 界面,在那里你必须做一些类似于多于。 ( JAVA parser api 有一个可选功能告诉它在发生致命错误后尝试继续,因此可能可以修复它并继续,但我不知道这是否可以在 Python 中完成。如果可以,这可能是一个比上面更复杂的过程。lxml中是否有任何钩子可以做到这一点?)
猜你喜欢
  • 2014-02-17
  • 2011-01-22
  • 1970-01-01
  • 2012-12-11
  • 2016-10-20
  • 1970-01-01
  • 1970-01-01
  • 2017-09-29
  • 2014-07-05
相关资源
最近更新 更多