Подтвердить что ты не робот

Регулярное выражение для извлечения содержимого тела HTML

Я ищу выражение regex, которое позволит мне извлечь содержимое HTML только из тегов тела из документа 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>

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

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

... сделал бы трюк, но он, похоже, не работает вообще с моим тестовым контентом в RegexBuddy.

4b9b3361

Ответ 1

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

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

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

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

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

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

Ответ 2

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

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

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

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

Ответ 3

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));
}

Ответ 4

/<body[^>]*>(.*)</body>/s

заменить

\1

Ответ 5

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

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

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

Ответ 6

Сопоставьте первый тег тела: <\s*body.*?>

Сопоставьте последний тег тела: <\s*/\s*body.*?>

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

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

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