关于python:将html5lib与xml.etree.ElementTree一起使用

using html5lib with xml.etree.ElementTree

我需要一种使用html5lib解析器生成真正的xml.etree.ElementTree的方法。 (出于可移植性原因,不能选择lxml。)

ELementTree.parse可以将解析器作为可选参数

1
xml.etree.ElementTree.parse(source, parser=None)

但目前尚不清楚这种解析器的外观。我可以在parser参数中使用HTML5中的类或对象吗?有关此问题的两个库的文档都很薄。

内容:

我有一个格式错误的XHTML文件,无法使用ELementTree.parse进行解析:

1
2
3
4
5
6
7
<?xml version="1.0" ?>
<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
Title</head>
<body>Note that this bris missing a closing slash</body>
</html>

所以我用html5lib.parse代替了默认的treebuilder="etree"参数,效果很好。

但是html5lib显然不会输出xml.etree.ElementTree对象,只是一个具有几乎相同的API的对象。这有两个问题:

  • html5lib的find不支持namespaces参数,这使得XPath在没有笨拙的包装函数的情况下过于冗长。
  • Eclipse调试器不支持html5lib etree的追溯。

因此,我不能单独使用ElementTree或html5lib。


给定xml.etree.ElementTree作为etree(通常通常以as形式导入):

返回的不是etree.ElementTree,而是etree.Element(与etree.fromstring返回的相同;只有etree.parse返回etree.ElementTree)。它确实是etree模块的一部分-它没有类似的API。您遇到的问题与html5lib一样适用于etree.fromstring

xml.etree.ElementTree的Python文档没有提到namespaces参数,它似乎是ElementTree对象(但不是Element对象)的未记录功能。因此,它可能并不是真正应该依赖的东西!您最好的选择可能是使用包装器功能。

Eclipse无法通过树的事实归结为html5lib存在时默认为xml.etree.cElementTree的事实-根据模块的文档,这是相同的,但是使用CPython的API在C中实现,从而阻止了Eclipse的调试器从运作。您可以使用以下非加速版本获取treebuilder(Python 3.3中的注释均是C实现-cElementTree只能作为已弃用的别名幸存),请使用以下代码:

1
2
3
4
5
6
import xml.etree.ElementTree as etree
import html5lib

tb = html5lib.getTreeBuilder("etree", implementation=etree)
p = html5lib.HTMLParser(tb)
tree = p.parse("<html>")


您必须将响应包装在ElementTree

1
2
3
4
5
>>> from xml.etree.ElementTree import ElementTree
>>> from html5lib import parse
>>>
>>> ElementTree(parse("<html>"))
<xml.etree.ElementTree.ElementTree at 0x...>