используя html5lib с xml.etree.ElementTree

Мне нужен способ использовать парсер html5lib для создания реального xml.etree.ElementTree. (lxml не подходит из соображений переносимости.)

ELementTree.parse может использовать парсер как необязательный параметр

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

но не ясно, как будет выглядеть такой парсер. Есть ли класс или объект в HTML5, который я мог бы использовать для аргумента parser? Документации для обеих библиотек по этому вопросу мало.


Контекст:

У меня есть искаженный файл XHTML, который не может быть проанализирован с помощью ElementTree.parse:

<?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>Title</title></head>
<body><div class="cls">Note that this br<br>is missing a closing slash</div></body>
</html>

Поэтому я использовал html5lib.parse вместо параметра по умолчанию treebuilder="etree", который работал нормально.

Но html5lib, по-видимому, не выводит объект xml.etree.ElementTree, а только объект с почти идентичным API. С этим есть две проблемы:

  • find html5lib не поддерживает параметр namespaces, что делает XPath чрезмерно многословным без неуклюжего функция-оболочка.
  • Отладчик Eclipse не поддерживает детализацию деревьев html5lib.

Поэтому я не могу использовать ни ElementTree, ни html5lib по отдельности.


person Arithmomaniac    schedule 26.12.2013    source источник


Ответы (2)


Учитывая xml.etree.ElementTree как etree (как это обычно импортируется как):

Возвращается не etree.ElementTree, а etree.Element (это то же самое, что возвращает etree.fromstring; только etree.parse возвращает etree.ElementTree). Это действительно часть модуля etree — это не что-то с похожим API. Проблема, с которой вы столкнулись, относится как к etree.fromstring, так и к html5lib.

В документации Python для xml.etree.ElementTree не упоминается аргумент namespaces — похоже, это недокументированная особенность объектов ElementTree (но не объектов Element). Таким образом, это, вероятно, не то, на что действительно следует полагаться! Лучше всего, вероятно, будет использовать функцию-оболочку.

Тот факт, что Eclipse не может проходить через деревья, связан с тем, что html5lib по умолчанию имеет значение xml.etree.cElementTree, когда оно существует, что должно быть идентичным согласно документации модуля, но реализовано на C с использованием API CPython, что останавливает работу отладчика Eclipse. Вы можете получить построитель дерева, используя неускоренную версию (примечание из Python 3.3, оба являются реализацией C — cElementTree просто выживает как устаревший псевдоним), используя следующее:

import xml.etree.ElementTree as etree
import html5lib

tb = html5lib.getTreeBuilder("etree", implementation=etree)
p = html5lib.HTMLParser(tb)
tree = p.parse("<html>")
person gsnedders    schedule 28.12.2013
comment
@Arithmomaniac Спасибо, что сказали — отредактировал, чтобы отразить это. - person gsnedders; 29.12.2013

Вы должны обернуть ответ в ElementTree

>>> from xml.etree.ElementTree import ElementTree
>>> from html5lib import parse
>>>
>>> ElementTree(parse("<html>"))
<xml.etree.ElementTree.ElementTree at 0x...>
person reubano    schedule 18.07.2016