lxml.html.tostring изменил порядок тегов doctype и xml при печати - PullRequest
4 голосов
/ 15 декабря 2011

Представьте, что у меня есть файл test.html с содержимым,

<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>Components of the SDK</title><link rel="stylesheet" href="core.css" type="text/css"/><meta name="generator" content="DocBook XSL Stylesheets V1.74.0"/></head><body></body></html>

И сделать это в приглашении Python,

>>>import lxml.html
>>>t = lxml.html.parse('test.html')
>>>lxml.html.etree.tostring(t)
>>>'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n<?xml version="1.0" encoding="UTF-8" standalone="no"??><html xmlns="http://www.w3.org/1999/xhtml"><head><title>Components of the SDK</title><link rel="stylesheet" href="core.css" type="text/css"/><meta name="generator" content="DocBook XSL Stylesheets V1.74.0"/></head><body/></html>'

Обратите внимание, как теги doctype и xml меняются местами после того, как lxml читает данные и затем снова печатает их через tostring? Как мы можем это исправить, чтобы он не пытался изменить документ (при условии, что он правильно сформирован).

1 Ответ

6 голосов
/ 15 декабря 2011

Краткий ответ

Сделайте это вместо этого (при условии, что все ваши документы имеют правильный формат XML)

etx = lxml.etree.parse('test.html')
print lxml.etree.tostring(etx, xml_declaration=True, encoding=etx.docinfo.encoding, standalone=etx.docinfo.standalone)

Пояснение

test.html на самом деле не является действительным html.Он содержит пустые элементы и инструкцию по обработке XML.Это не понято html.Парсер html интерпретирует инструкцию обработки xml как инструкцию обработки SGML (они похожи на <? ... > вместо xml <? ... ?>) с содержимым xml version="1.0" encoding="UTF-8" standalone="no"?.Таким образом, при повторной сериализации в XML инструкция обработки XML имеет двойные вопросы, например: ??>

Ваши результаты с html5lib синтаксическим анализатором или сериализатором немного лучше - при повторной сериализации в XML инструкция обработки будетбыть в комментариях.Это связано с тем, что HTML5 также не допускает инструкций обработки SGML и будет интерпретировать преамбулу xml как игнорируемый текст.

Чтобы получить требуемые результаты, выполните синтаксический анализ и сериализацию документа с помощью анализатора xml (lxml.etree) вместо.Кажется, что это правильно сформированный xml и правильный XHTML1.1.Если вместо этого выполнить сериализацию с помощью сериализатора html (lxml.html.tostring(), а не lxml.html.etree.tostring()), он выведет документ xgtml полиглота.

Складчатость заключается в том, что сериализатор не пытается точно сохранить объявление xml (этов конце концов, не является частью информационного набора xml).Вам нужно будет передать их методу tostring() из свойства docinfo.

...