Три концепции абзаца
В HTML 5 есть два отдельных понятия: элемент p
и абзац. Я буду называть этот абзац структурным абзацем. В реальном мире я нашел как минимум два других связанных понятия: логический абзац и типографский абзац.
p
элемент понятно. Вы это знаете, вы уже цитировали его описание из спецификации.
(структурный) абзац несколько странный концепция для меня. Может быть, он используется программами чтения с экрана или кем-то еще. Его определение в основном говорит, что это непустая серия фразирующего контента не прерывается другими типами контента (без учета a
, ins
, del
и map
).
Логический абзац — это то, что люди считают абзацем. Это единица текста, несущая одну мысль. Когда начинается другая (возможно, родственная) мысль, абзац обрывается и начинается новый. Оно составлено из последовательности предложений.
Каждое предложение может иметь не только свою языковую структуру, но и может содержать форматирование. Форматирование не ограничивается тем, что HTML называет фразовым содержимым, но я добавлю, по крайней мере, многострочные предварительно отформатированные фрагменты кода, списки, математические формулы (возможно, занимающие несколько строк, отображающие математику из TeX) и все остальное, что можно использовать в середине. предложения или между предложениями, не нарушая при этом хода мысли. Эту большую разницу между логическим абзацем и двумя другими концепциями можно увидеть в моем вопросе Список или более длинный фрагмент кода внутри абзаца.
Типографский абзац состоит из последовательности строк, а не предложений, и может содержать все, что типографская система может обработать внутри. Первоначально я думал, что это точно такая же концепция, как логический абзац, но это не так.
Это пришло мне в голову, когда я думал о tex. Вы можете узнать об этом из latex, который представляет собой просто большой набор определений для TeX и имеет такое же понятие абзаца. Содержимое буферизуется до тех пор, пока не встретится \par
(или пустая строка, которая внутренне преобразуется в \par
), затем оно сбрасывается на вывод как один абзац. То, что выглядит как один (логический) абзац, может быть внутренне несколькими абзацами, поскольку его нужно использовать для реализации более сложного поведения алгоритма набора текста. С этой точки зрения он больше напоминает структурный абзац.
Ответы на ваши вопросы
Абзац (структурный) начинается после элемента h1
, если присутствует только текстовый узел. Но это не элемент p
. Его нельзя стилизовать в CSS с помощью селектора p
, его нет в дереве DOM документа и т. д.
Есть определенные места, где теги элементов отсутствуют в разметке, но элементы все равно создаются. Это относится к тем элементам, у которых начальный тег может быть опущен. Это html
, head
, body
, colgroup
и tbody
. (По крайней мере, tbody
раньше вел себя по-другому в HTML 4, это поведение исходит из XHTML. В HTML его просто не должно быть.) Однако элемент p
не тот случай.
Если создатель контента неправильно вставил <p>
(это был недействительный HTML 5), как вы могли бы это исправить? Как только это неверно, вы не можете вообще ничего об этом предполагать. Кроме того, опускание конечного тега не является неправильным! На самом деле это не вопрос в этом пункте списка, так что идем дальше…
Вы действительно предполагаете действительный XHTML 5 (т.е. XML-сериализацию HTML 5, в частности, все теги закрыты)? Хорошо, тогда вам нужно отслеживать информацию о глубине дерева документов (или складывать, если вам нужны данные в структурированной форме). В противном случае вам придется реализовать полный синтаксический анализ HTML 5, поскольку может быть, например. option
с опущенным конечным тегом внутри (внутри select
). Это нарушит отслеживание глубины.
Абзац закрывается, когда начинается один из именованных элементов, или когда встречается закрывающий тег </p>
, или когда встречается конец родительского элемента. Мммм. Когда вы предполагаете, что XHTML действителен только внутри, вам все равно нужно реализовать правила закрытия для всех элементов, чтобы иметь возможность определять конец родительского элемента… Это будет непросто.
Преобразование сериализации HTML в XML HTML 5
В комментарии вы сказали, что преобразование HTML 5 в XHTML 5 является вашим вариантом использования.
Не используйте регулярные выражения!
Регулярные выражения не были предназначены для выполнения таких сложных задач, как синтаксический анализ HTML. Все, что вы попробуете, будет просто эвристикой. Настоящие регулярные выражения вообще не могут анализировать HTML, потому что HTML не является обычный язык. Забудем о том, что perlre намного мощнее; с большой силой приходит большая ответственность, и вы не должны использовать силу, когда она неправильная. Здесь на SO есть чрезвычайно известный ответ на вопрос по этой теме, настоящее произведение искусства. Джефф Этвуд написал подробнее на эту тему, цитируя этот ответ в начале и объясняя важность понимания ваших инструментов в остальной части статьи.
Я считаю, что текстовый подход к этой цели плох. HTML часто называют супом тегов, и, в отличие от того, что говорит Википедия, я встречал этот термин используется в отношении текстового подхода к его созданию и изменению в целом (а именно document.write()
и element.innerHTML
).
Кстати, это одна из проблем, которую XHTML очень хорошо решил путем отмены. В JavaScript вы не можете использовать document.write()
с XHTML. Если это работает, вы используете анализатор HTML с документом XHTML — используйте Content-Type
HTTP-заголовок с application/xhtml+xml; charset=utf-8
вместо используемого вами типа text/html
MIME.
Использовать DOM
Чистое решение™ — это DOM.
Я считаю, что вам следует реализовать (или использовать другую реализацию) парсер HTML, получите дерево DOM и напишите сериализатор в XHTML. Если входной документ недействителен, отклоните его обработку. Или добавьте в свою программу переключатели, которые сообщат ей, как исправить определенные ошибки, которые алгоритм синтаксического анализа не предназначен для обработки. Способов может быть много.
Я не уверен, какие части спецификации вы можете игнорировать, если они вам не интересны. Алгоритм синтаксического анализа стандартизирован, а также указана обработка ошибок. Вы можете найти ярлык, при котором вам не нужно создавать часть дерева DOM и просто оставить соответствующую часть ввода неразборчивой, но вы должны быть уверены, что продолжаете синтаксический анализ в правильной позиции ввода. Это может запутаться и, безусловно, подвержено ошибкам. Поэтому я рекомендую вам этого не делать.
Практичное решение
На практике кажется, что вы можете использовать как минимум два существующих модуля.
Mojolicious — это веб-фреймворк, содержащий Mojo::DOM. Если вам не нужны манипуляции с DOM и вы хотите просто синтаксический анализ и сериализацию, вы можете использовать базовый Mojo::DOM::HTML. HTML может быть проанализирован Mojo::DOM с использованием my $dom = Mojo::DOM->new($html_markup);
, результирующий объект DOM может быть настроен на использование сериализации XML с помощью $dom->xml(1);
, а сериализация может быть возвращена как $xhtml_markup = "$dom";
или $xhtml_markup = $dom->to_string();
. Из Mojo::DOM POD: «Mojo::DOM — это минималистичный и простой парсер HTML/XML DOM с поддержкой селекторов CSS. Он даже попытается интерпретировать поврежденный XML, поэтому вам не следует использовать его для проверки». Пример использования в ответе от amon. Вы можете использовать это решение, если вы уже используете Mojolicious, в противном случае установка всего большого фреймворка будет излишним для этой работы.
HTML::HTML5::Parser и HTML::HTML5::Writer можно использовать для разбора и сериализации HTML5 соответственно. У них, кажется, есть только несколько зависимостей. Хороший код с их использованием можно найти в ответе автора tobyink. Это должно быть решением для тех, кто еще не использует Mojolicious.
person
Palec
schedule
08.02.2014
p
элементы? - person Jukka K. Korpela   schedule 09.02.2014