Comments 5
Для парсинга 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 определится?
Написание конечного автомата для разбора HTML