Регулярное выражение для извлечения содержимого тела HTML - PullRequest
22 голосов
/ 10 декабря 2008

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

XHTML, который мне нужно проанализировать, будет очень простым файлом, мне не нужно беспокоиться о содержимом JavaScript или тегах <![CDATA[, например.

Ниже приведена ожидаемая структура файла HTML, которую я должен проанализировать. Поскольку я точно знаю все содержимое файлов HTML, с которыми мне придется работать, этот фрагмент HTML в значительной степени охватывает весь мой сценарий использования. Если я смогу получить регулярное выражение для извлечения тела этого примера, я буду счастлив.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>
    </title>
  </head>
  <body contenteditable="true">
    <p>
      Example paragraph content
    </p>
    <p>
      &nbsp;
    </p>
    <p>
      <br />
      &nbsp;
    </p>
    <h1>Header 1</h1>
  </body>
</html>

Концептуально, я пытался создать строку регулярного выражения, которая соответствует всему, НО внутреннему содержанию тела. При этом я бы использовал метод C # Regex.Split() для получения содержимого тела. Я думал это регулярное выражение:

((.|\n)*<body (.)*>)|((</body>(*|\n)*)

... справился бы с задачей, но с моим тестовым контентом в RegexBuddy это не сработало.

Ответы [ 6 ]

23 голосов
/ 10 декабря 2008

Будет ли это работать?

((?:.(?!<body[^>]*>))+.<body[^>]*>)|(</body\>.+)

Конечно, вам необходимо добавить необходимые \s, чтобы учесть < body ...> (элемент с пробелами), например:

((?:.(?!<\s*body[^>]*>))+.<\s*body[^>]*>)|(<\s*/\s*body\s*\>.+)

Если подумать, я не уверен, зачем мне нужен негативный прогноз ... Это также должно сработать (для правильно сформированного документа xhtml):

(.*<\s*body[^>]*>)|(<\s*/\s*body\s*\>.+)
9 голосов
/ 10 декабря 2008

XHTML будет легче анализировать с помощью XML-анализатора, чем с помощью регулярного выражения. Я знаю, что это не то, что вы спрашиваете, но анализатор XML сможет быстро перейти к узлу тела и вернуть вам его содержимое без каких-либо проблем с отображением тегов, которые дает вам регулярное выражение.

EDIT: В ответ на комментарий здесь; что синтаксический анализатор XML слишком медленный.

Существует два вида синтаксического анализатора XML, один из которых называется DOM, он большой и тяжелый, простой и удобный, он строит дерево документа, прежде чем что-либо делать. Другой называется SAX, он быстрый и легкий и требует больше работы, он читает файл последовательно. Вы хотите, чтобы SAX нашел тег Body.

Метод DOM хорош для многократного использования, извлечения тегов и определения того, кто является тем, кто является ребенком. Синтаксический анализатор SAX читает файлы по порядку и быстро получает нужную информацию. Regex не будет работать быстрее, чем SAX-парсер, потому что они оба просто перебирают совпадение файлов и шаблонов, за исключением того, что регулярное выражение не перестает смотреть после того, как обнаружило тег body, потому что регулярное выражение не имеет встроенного знание XML. Фактически, ваш синтаксический анализатор SAX, вероятно, использует небольшие кусочки регулярного выражения для поиска каждого тега.

5 голосов
/ 11 июля 2011
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));
}
3 голосов
/ 10 декабря 2008

Почему вы не можете просто разделить его на

</{0,1}body[^>]*> 

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

3 голосов
/ 10 декабря 2008
/<body[^>]*>(.*)</body>/s

заменить на

\1
1 голос
/ 14 сентября 2016

Соответствует первому тегу body: <\s*body.*?>

Соответствует последнему тегу body: <\s*/\s*body.*?>

(примечание: мы учитываем пробелы в середине тегов, что полностью допустимо для разметки)

Объедините их вместе, как это, и вы получите все промежуточное, включая теги тела: <\s*body.*?>.*?<\s*/\s*body.*?>. И убедитесь, что вы используете режим Singleline, который игнорирует разрывы строк.

Это работает в VB.NET и, надеюсь, других тоже!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...