Извлечение фрагмента текста из тела HTML (в .NET) - PullRequest
1 голос
/ 06 августа 2009

У меня есть HTML-контент, который вводится пользователем с помощью редактора richtext, поэтому он может быть практически любым (кроме тех, которые не должны находиться вне тега body, не беспокоясь о "head" или doctype и т.д.). Пример этого контента:

<h1>Header 1</h1>
<p>Some text here</p><p>Some more text here</p>
<div align=right><a href="x">A link here</a></div><hr />
<h1>Header 2</h1>
<p>Some text here</p><p>Some more text here</p>
<div align=right><a href="x">A link here</a></div><hr />

Хитрость в том, что мне нужно извлечь только первые 100 символов текста (HTML-теги удалены). Мне также нужно сохранить разрывы строк и не прерывать слова.

Таким образом, вывод для вышеупомянутого будет что-то вроде:

Header 1
Some text here

Some more text here

A link here

Header 2
Some text here

Some

Имеет 98 символов и разрывы строк сохраняются. Что я могу достичь, так это удалить все теги HTML с помощью Regex:

Regex.Replace(htmlStr, "<[^>]*>", "")

Затем обрежьте длину с помощью регулярных выражений:

Regex.Match(textStr, @"^.{1,100}\b").Value

Моя проблема в том, как сохранить разрыв строки? Я получаю вывод как:

Header 1
Some text hereSome more text here
A link here
Header 2
Some text hereSome more text

Заметили предложения? Возможно, кто-то может показать мне некоторые другие способы решения этой проблемы. Спасибо!

Дополнительная информация : Моя цель - сгенерировать простой текстовый синопсис из набора HTML-контента. Угадай, это поможет прояснить эту проблему.

Ответы [ 4 ]

2 голосов
/ 06 августа 2009

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

Затем создайте классы для каждого HTML-тега, который вас интересует, и который наследуется от вашего базового класса. Судя по вашему примеру, вам больше всего нужны теги h1, p, a и hr. Реализуйте метод PrintElement таким образом, чтобы он возвращал строку, которая правильно печатает элемент на основе InnerHTML (например, класс p PrintElement вернул бы "\ n [InnerHTML] \ n").

Затем создайте синтаксический анализатор, который проанализирует ваш HTML и определит, какой объект создать, а затем добавит эти объекты в очередь (дерево было бы лучше, но не похоже, что это необходимо для ваших целей).

Наконец, пройдите в очередь, вызывая метод PrintElement для каждого элемента.

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

1 голос
/ 06 августа 2009

Для информации, разбор html с регулярным выражением ... полон тонких проблем. HTML Agility Pack может быть более надежным, но все же страдает от слов, сочетающихся друг с другом:

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html);
string text = doc.DocumentNode.InnerText;
0 голосов
/ 04 октября 2009

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

  • Удалить все разрывы строк
  • Добавить префикс разрыва строки ко всем тегам блока (например, div, p, hr, h1 / 2/3/4 и т. Д.)

Прежде чем извлекать их для отображения в виде простого текста, используйте regex, чтобы удалить тег html и сохранить разрыв строки. Вряд ли какая-либо ракетостроение, но у меня работает.

0 голосов
/ 06 августа 2009

Одним из способов может быть удаление html в три этапа:

Regex.Replace(htmlStr, "<[^/>]*>", "") // don't strip </.*>
Regex.Replace(htmlStr, "</p>", "\r\n") // all paragraph ends are replaced w/ new line
Regex.Replace(htmlStr, "<[^>]*>", "") // replace remaining </.*>
...