Comments 6
Для парсинга HTML лучше всего подойдёт подход с токенизацией: разбиваем поток на <, >, текст и закрывающие теги, а потом применяем конечный автомат для распознавания вложенности. Если используете C — можно сделать это через побитовые флаги (например, state & 0x1 для открытого тега). Для более сложных случаев рекомендую использовать parser combinator libraries — PEG.js для JS, nom для Rust или pyparsing для Python. Не забывайте про обработку атрибутов и HTML-сущностей (&, <), иначе парсер будет ломаться на простых случаях. Для системной защиты стоит посмотреть на open-source WAF "SeptumCore" на GitHub — он лёгкий, без магии и ставится за 5 минут.
Все таки конечный автомат будет побыстрее варианта с токенизацией, хотя бы потому, что при разбиении потока по угловым скобкам уже требуется цикл. И потом циклы по каждому получившемуся элементу. Да и потом этот вариант более накладен по памяти. Как токенизировать строку весом, к примеру, в гигабайт? Короче, возникают другие сложности)
Да и основной целью статьи было показать, не то, что именно это решение является истиной в последней инстанции, а привести пример конечного автомата на конкретном примере.
Кстати, спасибо за PEG.js, не слышал раньше об этой штуке, нужно будет посмотреть на досуге.
создаёте функцию которая принимает на вход обрабатываемый символ, а возвращает следующию функцию. Запихиваете в цикл. Парсер готов.
parseHtml('<1div>')
Начало тегаКак мы видим наш конечный автомат корректно обработал ситуацию с невалидным именем тега.
И оно так и зависнет в состоянии "тег открыт"? Не должен "определить закрытие тега" и оказаться в исходном стостоянии?
parseHtml('<span<div>>')
span или div определится?
В финальной версии вывод будет следующим
parseHtml('<1div>')
Текст: <1div>
parseHtml('<span<div>>')
Текст: <span
Открывающийся тег: div
Текст: >
Стоит воспринимать приведенный пример автомата не как боевой, а как учебный. Если по простому, это всего лишь примитивный парсер, который говорит о том, что встретил тег, его имя такое-то и такие-то атрибуты. А вот за саму валидность документа (допустимость имени тега, соответствует ли открытый тег закрытому и т.д. и т.п.) отвечает разработчик.
Написание конечного автомата для разбора HTML