Comments 45
Вы ведь не забросите публикацию серии? Интересно, что вышло в итоге, и чем оно отличается от встроенного DOMDocument.
P.S. С дебютом :)
Спасибо за поддержку. Забрасывать не намерен, тема мне кажется интересной, поэтому хочу ее развивать.
Вы зря пишете такие короткие статьи. Кода нет, по теме ничего нет, текста наберется может строк 140. Разбивать текст на статьи надо по теме или функциональности кода, а не по размеру. Довольно редко встречаются такие большие темы, которые надо делить на несколько частей. Судя по названию, вряд ли у вас настолько сложная тема, можно было все описать в одной статье.
P.S. И есть еще теги, которые можно не закрывать (img, input), а еще можно закрывать теги коротко: <div… />
Данная ошибка не пропущена. В этом случаи ошибка относится к ошибке, когда нету закрывающего тега, а открывающий есть. Касательно одиночных тегов — эта функция предусмотрена парсером, у меня есть список одиночных тегов, если тег совпадает с одиночным, он записывается в дом. Касательно краткого закрытия тега — тоже предусмотрено
Разве HTML позволяет закрывать тэг div коротко? Насколько я знаю, коротко закрывать можно только тэги без контента (те самые, которые можно не закрывать) и тэги внедренных SVG и MATHML.
<!DOCTYPE html>
<html>
<body>
<div style="width: 100px; height: 100px; background-color: red;" />
</body>
</html>
А вы поставьте два таких тэга подряд и посмотрите что с ними сделает браузер:
<style>div { border: solid 1px; padding: 10px; }</style>
<div/>
<div/>
<div/>
В вашем же примере тэг div на самом деле закрывается на строчке </body>
P.S. Но всё-таки странно это.\
P.P.S. Они накладываются друг на друга, но отображаются оба.
Это не наложение. Они находятся один внутри другого. То есть браузер просто проигнорировал все лишние "/" и увидел три открывающих тэга.
Ничего странного, HTML — не XML.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style type="text/css">
div { border: solid 1px; padding: 10px; }
</style>
</head>
<body>
<div/>
<div/>
<div/>
</body>
</html>
Ну почему же? В режиме XHTML как раз всё работает.
Просто XHTML определяется браузером не по DOCTYPE, а по Content Type (а для локальных файлов — по расширению).
У слову, у вас Content-Type как раз неправильный указан. Плюс я не уверен что в режим XHTML можно переключиться уже после начала парсинга.
Потому что, во-первых, стало понятно что старые сайты никуда не денутся, а значит упростить парсер не выйдет, ему всё равно нужно будет поддерживать HTML. А ведь именно упрощенный парсинг рекламировался как главный плюс XHTML.
А во-вторых, этот XHTML местами слишком многословный и неудобный для редактирования человеком.
Не ушли, даже в актуальных спецификациях HTML 5.2 есть несколько разделов, посвящённых XML-синтаксису. Я проверял — как минимум в Firefox это всё реализовано и работает. Валидатор (Nu Html Checker) тоже успешно валидирует HTML5 в XML-синтаксисе.
Правильно товарищ пишет: ровно эта проблема решена в tidy, и там просто огромная туча кода на Си для этого. Обильно политая слезами и кровью десятков тысяч страждущих, а также приправленная сотнями юнит-тестов. Свое можно писать там, где не возникает комбинаторного взрыва. А где он возникает, лучше взять готовое.
На первом же изображении: «Берем символ, если он равен '<' — считаем его тегом и обрабатываем». Считаем символ тегом? И таких ошибок — куча.
Информации мало.
Сама информация — низкого качества. Выдумываете бред.
С наскоку дам больше информации лучшего качества:
Html — имеет простую структуру, смотрим rfc1866.
Имеем два типа нод: TagNode и TextNode (не может иметь детей).
Скрипты и стили к парсингу отношения не имеют и рассматриваются как обычные теги, содержащие одну дочернюю TextNode.
Самый простой парсер можно написать на регулярках, и через рекурсию строить дерево.
Если есть желание написать что-либо более интересное — читаем «книгу Дракона», да, она о разработке компиляторов, но в ней полно информации по интересующей нас теме — синтаксическом и лексическом анализе. Определяем алфавит, лексемы. Пишем лексический анализатор (автомат), который все это обрабатывает, пропускаем исходный код и на выходе получаем список лексем. Дальше строим из лексем плоский массив из открывающих/закрывающих тегов, блоков текста. В конце проходим по этому массиву строим дерево и заодно выявляем ошибки — незакрытые теги, цепи и.т.д.
Это небольшая ошибка, я имел ввиду то, что парсер меняем состояние и начинает дальнейшую цепочку символов обрабатывать как тег.
Это смысловая ошибка, читатель не должен догадываться о том, что вы имели ввиду.
Прошу прощения, хотя с другой стороны, тем кто вообще не знаком с синтаксическими анализаторами, как мне кажется, будет более понятен мой вариант объяснения.
Да, читатель может не знать о анализаторах, но вы публикуетесь на техническом ресурсе, где соответствующая аудитория, и контент должен соответствовать. Аудитории будет понятнее и удобнее, если они будут встречать определенные, устойчевые, термины и методы, используемую литературу. Если содержания статьи им будет недостаточно, появиться желание углубиться — они будут знать о том, что им нужно искать.
Также я читал книгу по трансляторам, более того, некоторый материал будет использоваться в дальнейших частях цикла.
Собственно, данный материал должен был использоваться и в этой статье.
Например про те же состояния и теорию конечных автоматов. Частей будет еще где-то две.
Если бы вы описывали процесс, с информацией, указанной выше, то можно было бы еще поверить в две хорошие части, разделенные на: теоретическую и практическую, либо на: разбор и анализ. Что же вы хотите растянуть на три, описывая информацию вашей манерой — непонятно.
Касательно нод. Вы не учли ноду комментариев, а ведь они тоже будут в документе, и их тоже нужно будет обрабатывать.
Вы не учли то, что я писал комментарий, а не статью. Да, для них будет отдельное правило.
Также хочу отметить, что вариант написания парсера на регулярках — плохая идея. Такой парсер будет работать примерно так же, как simple dom.
Естественно — на одной регулярке, получится простая поделка и далеко не уедешь, но другого я и не утверждал. Боюсь, сейчас вы показали полное отсутствие компетентности в данной теме. В профильной литературе, и, например, в lex регулярные выражения используются повсеместно.
Боюсь, сейчас вы показали полное отсутствие компетентности в данной теме. В профильной литературе, и, например, в lex регулярные выражения используются повсеместно.
Нет, я показал отсутствие компетентности в регулярных выражениях, но никак не в синтаксическом анализе. В конце концов, если бы то, что вы сказали выше — правда, думаю моя статья вообще бы не вышла на хабре. К тому же, я не говорю, что использовать регулярные выражения вообще в синтаксических анализаторах это сразу плохо. Вовсе нет. Просто в данной задаче это не нужно, так как она достаточно простая и использовать регулярные выражения нет смысла.
Html — имеет простую структуру, смотрим rfc1866.
Со времен rfc1866 вышло аж три новые версии Html.
Скрипты и стили к парсингу отношения не имеют и рассматриваются как обычные теги, содержащие одну дочернюю TextNode.
Ну-ну:
<script>
<div>
</script>
Здесь тэг <script>
содержит текстовую ноду <div>
. Любой другой тэг в этой ситуации содержал бы вложенный тэг <div>
. А значит, парсить скрипты нужно всё-таки несколько по-другому.
Самый простой парсер можно написать на регулярках, и через рекурсию строить дерево.
Неа, нельзя. HTML не является регулярным языком.
Дальше строим из лексем плоский массив из открывающих/закрывающих тегов, блоков текста.
Нельзя так делать, некоторые тэги (тот же <script>
) меняют режимы лексера.
Со времен rfc1866 вышло аж три новые версии Html.
Не путайте комментарий с постом.
Здесь тэг script содержит текстовую ноду div. Любой другой тэг в этой ситуации содержал бы вложенный тэг div. А значит, парсить скрипты нужно всё-таки несколько по-другому.
Для парсера без разницы — что внутри у тега script. Синтаксический анализатор построил токены, лексический прошелся по ним, и после обработки все, что внутри script, превращается в текстовую ноду. Да, для данного случая анализ сложнее, но сути это не меняет. То, что код внутри не валиден — не проблема парсера html. Уж логика у вас больно странная — автор может вырезать script, но не может вместо этого создать ноду с текстом.
Неа, нельзя. HTML не является регулярным языком.
Читайте не между строк. Писалось о простом парсере, который будет работать с минимумом проблем. Хотя, если пойти дальше, то все равно:
https://habr.com/ru/post/171667/
Льзя. Вы уж простите, но nikic'у я верю больше.
https://www.w3.org/TR/WD-html-lex/ Ну и у w3c получилось на lex, который использует регулярные выражения. А вы и дальше считайте, что нельзя.
Как я html-парсер на php писал, и что из этого вышло. Вводная часть