Можете ли вы привести несколько примеров того, почему трудно анализировать XML и HTML с помощью регулярного выражения?

Одна ошибка, я вижу, что люди, делающие over и снова, пытаются разобрать XML или HTML с регулярным выражением. Вот несколько причин синтаксического разбора XML и HTML:

Люди хотят обрабатывать файл как последовательность строк, но это действительно:

<tag
attr="5"
/>

Люди хотят лечить < или < тег в качестве начала тега, но такие вещи существуют в природе:

<img src="imgtag.gif" alt="<img>" />

Люди часто хотят сопоставлять начальные теги с конечными тегами, но теги XML и HTML позволяют содержать теги (какие традиционные регулярные выражения не могут обрабатывать вообще):

<span id="outer"><span id="inner">foo</span></span> 

Люди часто хотят сопоставлять содержимое документа (например, известная проблема "найти все номера телефонов на заданной странице" ), но данные могут быть помечены (даже если это выглядит нормально, если смотреть)

<span class="phonenum">(<span class="area code">703</span>)
<span class="prefix">348</span>-<span class="linenum">3020</span></span>

Комментарии могут содержать плохо отформатированные или неполные теги:

<a href="foo">foo</a>
<!-- FIXME:
    <a href="
-->
<a href="bar">bar</a>

Какие еще ошибки вы знаете?

Ответы

Ответ 1

Вот вам полезный XML-код:

<!DOCTYPE x [ <!ENTITY y "a]>b"> ]>
<x>
    <a b="&y;>" />
    <![CDATA[[a>b <a>b <a]]>
    <?x <a> <!-- <b> ?> c --> d
</x>

И этот маленький пучок радости действителен HTML:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" [
    <!ENTITY % e "href='hello'">
    <!ENTITY e "<a %e;>">
]>
    <title>x</TITLE>
</head>
    <p id  =  a:b center>
    <span / hello </span>
    &amp<br left>
    <!---- >t<!---> < -->
    &e link </a>
</body>

Не говоря уже обо всех зависящих от браузера синтаксических разборах для недопустимых конструкций.

Удачи с помощью регулярных выражений против этого!

EDIT (Jörg W Mittag): Вот еще один хороший фрагмент хорошо сформированного, действительного HTML 4.01:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
  "http://www.w3.org/TR/html4/strict.dtd"> 
<HTML/
  <HEAD/
    <TITLE/>/
    <P/>

Ответ 2

На самом деле

<img src="imgtag.gif" alt="<img>" />

недействителен HTML и не является допустимым XML.

Недействителен XML, потому что '<' и ' > ' не являются допустимыми символами внутри строк атрибутов. Они должны быть экранированы с использованием соответствующих объектов XML & lt; и >

Недопустимый HTML либо потому, что короткая закрывающая форма не разрешена в HTML (но правильная в XML и XHTML). Тег 'img' также является неявным закрытым тегом в соответствии со спецификацией HTML 4.01. Это означает, что ручное закрытие на самом деле неверно и эквивалентно закрытию любого другого тега дважды.

Правильная версия в HTML

<img src="imgtag.gif" alt="&lt;img&gt;">

и правильная версия в XHTML и XML

<img src="imgtag.gif" alt="&lt;img&gt;"/>

Следующий приведенный ниже пример также недействителен

<
tag
attr="5"
/>

Это неверный HTML или XML. Имя тега должно быть прямо за "<", хотя атрибуты и закрытие " > " могут быть там, где они хотят. Таким образом, действительный XML на самом деле

<tag
attr="5"
/>

И вот еще один более забавный: вы можете на самом деле выбрать либо "или", как свой атрибут, указывающий символ

<img src="image.gif" alt='This is single quoted AND valid!'>

Все остальные причины, которые были опубликованы, являются правильными, но самая большая проблема с разбором HTML заключается в том, что люди обычно не понимают все правила синтаксиса правильно. Тот факт, что ваш браузер интерпретирует ваши метки как HTML, не означает, что вы действительно написали допустимый HTML.

Изменить: И даже stackoverflow.com согласен со мной относительно определения действительного и недействительного. Ваш недопустимый XML/HTML не подсвечивается, а моя исправленная версия.

В принципе, XML не обрабатывается регулярными выражениями. Но нет оснований для этого. Для каждого языка существует множество XML-парсеров. У вас есть выбор между SAX-парсерами, DOM-парсерами и парсерами Pull. Все они гарантированно будут намного быстрее, чем синтаксический анализ с регулярным выражением, и затем вы можете использовать классные технологии, такие как XPath или XSLT, в результирующем дереве DOM.

Мой ответ поэтому: не только синтаксический анализ XML с регулярными выражениями, но и плохая идея. Просто используйте один из миллионов существующих синтаксических анализаторов XML и воспользуйтесь всеми расширенными функциями XML.

HTML слишком сложный, чтобы даже попробовать разбору самостоятельно. Во-первых, в синтаксисе закона есть много небольших тонкостей, о которых вы, возможно, и не подозреваете, а во-вторых, HTML в дикой природе - это просто огромная вонючая куча (вы получаете мой дрейф). Существует множество библиотек анализаторов, которые отлично справляются с обработкой HTML-подобных супов, просто используйте их.

Ответ 3

Я написал всю запись в блоге на эту тему: Ограничения регулярного выражения

Суть проблемы в том, что HTML и XML являются рекурсивными структурами, для которых требуются механизмы подсчета для правильного анализа. Истинное регулярное выражение не может рассчитывать. Для подсчета необходимо иметь грамматику контекстной свободы.

В предыдущем параграфе есть небольшое оговорка. Некоторые реализации регулярных выражений теперь поддерживают идею рекурсии. Однако, как только вы начнете добавлять рекурсию в выражения регулярного выражения, вы действительно растягиваете границы и должны учитывать парсер.

Ответ 4

В ваш список не входит одно свойство: атрибуты могут появляться в любом порядке, поэтому, если ваше регулярное выражение ищет ссылку с href "foo" и классом "bar", они могут поступать в любом порядке и иметь любые количество других вещей между ними.

Ответ 5

Это зависит от того, что вы подразумеваете под "разбором". Вообще говоря, XML не может быть проанализирован с использованием регулярного выражения, поскольку грамматика XML отнюдь не является регулярной. Проще говоря, регулярные выражения не могут рассчитывать (ну, регулярные выражения Perl могли бы действительно подсчитывать вещи), поэтому вы не можете балансировать теги open-close.

Ответ 6

Люди действительно ошибаются, используя регулярное выражение, или это просто достаточно хорошо для задачи, которую они пытаются достичь?

Я полностью согласен с тем, что разбор html и xml с использованием регулярного выражения невозможен, как ответили другие люди.

Однако, если ваше требование состоит не в том, чтобы разобрать html/xml, а просто получить один маленький бит данных в "известном хорошем" бите html/xml, то, возможно, регулярное выражение или даже еще более простая "подстрока" достаточно хорошо.

Ответ 7

Обычно люди по умолчанию используют жадные шаблоны, что довольно часто приводит к непродуманному. * размывание больших кусков файла в максимально возможное foo > . * </foo> .

Ответ 8

Я соблазн сказать "не изобретать колесо". Кроме того, что XML - действительно очень сложный формат. Поэтому, может быть, я должен сказать "не изобретать синхротрон".

Возможно, правильное клише начинается "когда все, что у вас есть, это молоток..." Вы знаете, как использовать регулярные выражения, регулярное выражение хорошо подходит для разбора, поэтому зачем изучать библиотеку синтаксического анализа XML?

Потому что синтаксический анализ XML затруднен. Любые усилия, которые вы сохраняете, не имея необходимости учиться использовать библиотеку синтаксического анализа XML, будут более чем компенсированы количеством творческой работы и ошибкой, которую вам придется делать. Ради вас, Google "библиотека XML" и использовать кого-то еще.

Ответ 9

Я верю, что этот классический имеет информацию, которую вы ищете. Вы можете найти точку в одном из комментариев:

Я думаю, что недостаток в том, что HTML - это грамматика типа Хомского типа 2 (контекстная свободная грамматика), а RegEx - грамматика Хомского типа 3 (обычная выражение). Поскольку грамматика типа 2 существенно сложнее, чем грамматика 3-го типа - вы не можете надеяться сделать эту работу. Но многие попробует, некоторые будут претендовать на успех, а другие найдут ошибку и полностью запутайте вас.

Дополнительная информация из Википедии: Иерархия Хомского

Ответ 10

Я думаю, что проблемы сводятся к следующему:

  • Регулярное выражение почти всегда неверно. Есть законные входы, которые он не сможет правильно сопоставить. Если вы достаточно усердно работаете, вы можете сделать это на 99% правильным, или 99,999%, но сделать его на 100% правильным почти невозможно, хотя бы из-за странных вещей, которые позволяет XML с помощью сущностей.

  • Если регулярное выражение неверно, даже для 0.00001% входов, то у вас есть проблема с безопасностью, потому что кто-то может обнаружить один вход, который нарушит ваше приложение.

  • Если регулярное выражение достаточно корректно, чтобы охватить 99,99% случаев, то оно будет полностью нечитаемым и недостижимым.

  • Очень вероятно, что регулярное выражение будет работать очень плохо на входных файлах среднего размера. Моя первая встреча с XML заключалась в замене Perl script, который (неправильно) анализировал входящие XML-документы с помощью правильного синтаксического анализа XML, и мы заменили не только 300 строк нечитаемого кода на 100 строк, которые могли бы понять все, но мы улучшили пользователь время отклика от 10 секунд до 0,1 секунды.

Ответ 11

Вообще говоря, XML не может быть проанализирован с использованием regex, поскольку грамматика XML отнюдь не является регулярной. Проще говоря, регулярные выражения не могут рассчитывать (ну, регулярные выражения Perl могли бы действительно подсчитывать вещи), поэтому вы не можете балансировать теги open-close.

Я не согласен. Если вы будете использовать рекурсию в регулярном выражении, вы можете легко найти открытые и закрытые теги.

Здесь Я показал пример регулярного выражения, чтобы избежать синтаксического анализа ошибок в первом сообщении.

Ответ 12

Я дал упрощенный ответ на эту проблему здесь. Хотя это не соответствует значению 100%, я объясню, как это возможно, если вы готовы выполнить некоторую предварительную обработку.