Я ищу выражение регулярного выражения, которое позволит мне извлекать HTML-содержимое между тегами body из документа XHTML.
XHTML, который мне нужно проанализировать, будет очень простыми файлами, например, мне не нужно беспокоиться о содержимом JavaScript или тегах <




XHTML будет легче анализировать с помощью синтаксического анализатора XML, чем с помощью регулярного выражения. Я знаю, что это не то, о чем вы просите, но синтаксический анализатор XML сможет быстро перейти к узлу тела и вернуть вам его содержимое без каких-либо проблем с отображением тегов, которые дает вам регулярное выражение.
Обновлено: В ответ на комментарий здесь; что синтаксический анализатор XML работает слишком медленно.
Существует два типа анализаторов XML: один называется DOM - большой, тяжелый, простой и дружелюбный, он строит дерево из документа, прежде чем вы сможете что-либо сделать. Другой называется SAX, он быстрый, легкий и требует больше работы, он читает файл последовательно. Вам нужно, чтобы SAX нашел тег Body.
Метод DOM хорош для многократного использования, извлечения тегов и определения дочерних элементов. Синтаксический анализатор SAX читает файл по порядку и быстро получает нужную информацию. Regex не будет быстрее, чем парсер SAX, потому что они оба просто проходят по файлу и соответствуют шаблону, за исключением того, что регулярное выражение не прекращает поиск после того, как оно нашло тег тела, потому что регулярное выражение не имеет встроенного знание XML. Фактически, ваш синтаксический анализатор SAX, вероятно, использует небольшие фрагменты регулярного выражения для поиска каждого тега.
Нет причин заново изобретать колесо. Если это XHTML, то это XML, а анализатор XML - это инструмент для работы. +1
Это было первое решение, которое мне надоело, но оно работало довольно медленно. Я подумал, что RegEx будет быстрее.
Существует два типа анализаторов XML: один называется DOM - большой, тяжелый, простой и дружелюбный, он строит дерево из документа, прежде чем вы сможете что-либо сделать. Другой называется SAX, он быстрый, легкий и требует больше работы, он читает файл последовательно. Вам нужно, чтобы SAX нашел тег Body.
это чрезвычайно простая работа для парсера, она действительно не должна быть медленной
Первоначально я пробовал это с помощью класса .NET System.Xml.XmlDocument, если это объясняет какую-либо медлительность. - Мэтью Растон
Даже если он работает медленнее, он будет обрабатывать все исключительные случаи, такие как name = "</body>" и т. д.
Это сработает?
((?:.(?!<body[^>]*>))+.<body[^>]*>)|(</body\>.+)
Конечно, вам нужно добавить необходимый \s, чтобы учесть < body ...> (элемент с пробелами), как в:
((?:.(?!<\s*body[^>]*>))+.<\s*body[^>]*>)|(<\s*/\s*body\s*\>.+)
Если подумать, я не уверен, зачем мне нужен негативный прогноз ... Это тоже должно сработать (для правильно сформированного документа xhtml):
(.*<\s*body[^>]*>)|(<\s*/\s*body\s*\>.+)
Ммм, похоже, хороший случай продемонстрировать, что RE не следует использовать против (неизвестного) HTML: <body onload = "DoSomething ('>');"> действительно ... :-)
PhiLho, вы ошибаетесь, это недопустимый XHTML. ">" должно быть экранировано как "& gt;" быть XML-правильно сформированным. Однако веб-браузеры используют различные уловки для чтения неработающего HTML / XHTML. Страницы с содержимым JavaScript обычно не имеют правильного формата XML, если они не помещены в CDATA.
Спасибо за это. Не могли бы вы подробнее описать, как использовать это с библиотекой Regex на C#. оператор для возврата желаемого содержимого из строки HTML-документа
@enduser двенадцать лет спустя, я считаю, что этот ответ больше касался использования регулярного выражения, чем его использования в C#. Для последнего я бы следовал одному из примеров из c-sharpcorner.com/article/c-sharp-regex-examples.
/<body[^>]*>(.*)</body>/s
заменить
\1
Это должно соответствовать всему документу и помещать тело в \ 3. Таким образом, вы знаете, что если он не соответствует всему документу, что при форматировании текущего документа нужно еще кое-что учесть, и вы можете выдать ошибку.
Я знаю, что это очень старый пост, но черт возьми ... Мне нравится этот ответ, и я должен был сообщить об этом.
Обратите внимание, что в регулярных выражениях Perl и Java необходимо включить флаг s, чтобы внутренний (.*) соответствовал символам новой строки, что обычно и требуется. Также, на мой взгляд, необязательно иметь начальную или конечную группировку - более простым ответом будет /<body[^>]*>(.*)</body>/s и использование группы 1.
@aarestad спасибо, я редактировал, вы правы - мои навыки работы с регулярными выражениями на тот момент были немного зеленее :)
Почему ты не можешь просто разделить это на
</{0,1}body[^>]*>
а взять вторую струну? Я считаю, что это будет намного быстрее, чем искать огромное регулярное выражение.
Тем не менее, если вы исправите это, ваш подход может быть проще. :)
Что ж, я только что заметил это, прежде чем вы разместили комментарий и отредактировали этот ответ: P
На самом деле у меня недостаточно очков для редактирования ... должно быть, это был кто-то другой.
String toMatch = "aaaaaaaaaaabcxx sldjfkvnlkfd <body>i m avinash</body>";
Pattern pattern=Pattern.compile(".*?<body.*?>(.*?)</body>.*?");
Matcher matcher=pattern.matcher(toMatch);
if (matcher.matches()) {
System.out.println(matcher.group(1));
}
Соответствует первому тегу тела: <\s*body.*?>
Соответствует последнему тегу тела: <\s*/\s*body.*?>
(примечание: мы учитываем пробелы в середине тегов, что, кстати, является полностью допустимой разметкой)
Объедините их вместе вот так, и вы получите все, что между ними, включая теги тела: <\s*body.*?>.*?<\s*/\s*body.*?>. И убедитесь, что вы используете режим Singleline, который игнорирует разрывы строк.
Это работает в VB.NET и, надеюсь, в других тоже!
Split()- неподходящий инструмент для этой работы. Просто используйтеRegex.Match(subject, "(?s)<body[^>]*>(.*)</body>").Groups[1].Value.