Функция
lxml tostring()
выглядит совершенно неработоспособной при печати только частей документов. Свидетель:
from lxml.html import fragment_fromstring, tostring
frag = fragment_fromstring('<p>This stuff is <em>really</em> great!')
em = frag.cssselect('em').pop(0)
print tostring(em)
Я ожидаю <em>really</em>
, но вместо этого он печатает <em>really</em> great!
, что неправильно . Великий !' является не частью выбранного em
. Это не только неправильно, это пилюля, по крайней мере, для обработки структурированного документа XML, где такой конечный текст будет обычным делом.
Насколько я понимаю, lxml хранит любой свободный текст, который идет после текущего элемента в атрибуте .tail
элемента. Сканирование кода для tostring()
приводит меня к функции _write()
ElementTree.py, которая явно всегда печатает хвост. Это правильное поведение для целых деревьев, но не для последнего элемента при рендеринге поддерева, но оно не делает различий.
Чтобы получить правильное отображение без хвоста выбранного XML, я попытался написать функцию toxml()
с нуля, чтобы использовать вместо нее. В основном это сработало, но есть много особых случаев при обработке комментариев, инструкций по обработке, пространств имен, кодировок, yadda yadda. Поэтому я поменял передачу и теперь просто копилкой tostring()
, постобработав вывод, чтобы удалить оскорбительный текст .tail
:
def toxml(e):
""" Replacement for lxml's tostring() method that doesn't add spurious
tail text. """
from lxml.etree import tostring
xml = tostring(e)
if e.tail:
xml = xml[:-len(e.tail)]
return xml
Базовая серия тестов показывает, что это прекрасно работает.
Критика и / или предложения?