Удалите HTML-теги из строки, включая & nbsp, в C #

83

Как удалить все HTML-теги, включая & nbsp, с помощью регулярного выражения в C #. Моя строка выглядит как

  "<div>hello</div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div>"
рампурияаа
источник
9
Не используйте регулярное выражение, ознакомьтесь с пакетом HTML Agility Pack. stackoverflow.com/questions/846994/how-to-use-html-agility-pack
Тим,
Спасибо, Тим, но приложение довольно большое и неповрежденное, добавить или загрузить пакет гибкости html не получится.
rampuriyaaa,

Ответы:

198

Если вы не можете использовать решение, ориентированное на анализатор HTML, для фильтрации тегов, вот простое регулярное выражение для него.

string noHTML = Regex.Replace(inputHTML, @"<[^>]+>|&nbsp;", "").Trim();

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

string noHTMLNormalised = Regex.Replace(noHTML, @"\s{2,}", " ");
Рави К. Таплиял
источник
Я еще не тестировал это столько, сколько мне нужно, но он работал лучше, чем я ожидал. Выложу способ, который написал ниже.
Don Rolling
<[^>]+?>Ленивое совпадение ( согласно @David S.) могло бы сделать это немного быстрее, но просто использовал это решение в живом проекте - очень рад +1 :)
Gone Coding
Regex.Replace (inputHTML, @ "<[^>] +> | & nbsp | \ n;", "") .Trim (); \ n не удаляется
Махеш Малпани
3
Я бы порекомендовал Regex.Replace(inputHTML, @"<[^>]+>|&nbsp;", " ")
объявить
2
@Tauseef Если вы используете пробел в первом вызове замены, вы можете оставить пробелы там, где их не было в исходном вводе. Скажем, вы получаете Sound<b>Cloud</b>на входе; у вас получится, что Sound Cloudон должен был быть удален, SoundCloudпотому что именно так он отображается в HTML.
Ravi K Thapliyal
31

Я взял код @Ravi Thapliyal и создал метод: он прост и может не очищать все, но пока он делает то, что мне нужно.

public static string ScrubHtml(string value) {
    var step1 = Regex.Replace(value, @"<[^>]+>|&nbsp;", "").Trim();
    var step2 = Regex.Replace(step1, @"\s{2,}", " ");
    return step2;
}
Дон Роллинг
источник
16

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

        private static readonly Regex _tags_ = new Regex(@"<[^>]+?>", RegexOptions.Multiline | RegexOptions.Compiled);

        //add characters that are should not be removed to this regex
        private static readonly Regex _notOkCharacter_ = new Regex(@"[^\w;&#@.:/\\?=|%!() -]", RegexOptions.Compiled);

        public static String UnHtml(String html)
        {
            html = HttpUtility.UrlDecode(html);
            html = HttpUtility.HtmlDecode(html);

            html = RemoveTag(html, "<!--", "-->");
            html = RemoveTag(html, "<script", "</script>");
            html = RemoveTag(html, "<style", "</style>");

            //replace matches of these regexes with space
            html = _tags_.Replace(html, " ");
            html = _notOkCharacter_.Replace(html, " ");
            html = SingleSpacedTrim(html);

            return html;
        }

        private static String RemoveTag(String html, String startTag, String endTag)
        {
            Boolean bAgain;
            do
            {
                bAgain = false;
                Int32 startTagPos = html.IndexOf(startTag, 0, StringComparison.CurrentCultureIgnoreCase);
                if (startTagPos < 0)
                    continue;
                Int32 endTagPos = html.IndexOf(endTag, startTagPos + 1, StringComparison.CurrentCultureIgnoreCase);
                if (endTagPos <= startTagPos)
                    continue;
                html = html.Remove(startTagPos, endTagPos - startTagPos + endTag.Length);
                bAgain = true;
            } while (bAgain);
            return html;
        }

        private static String SingleSpacedTrim(String inString)
        {
            StringBuilder sb = new StringBuilder();
            Boolean inBlanks = false;
            foreach (Char c in inString)
            {
                switch (c)
                {
                    case '\r':
                    case '\n':
                    case '\t':
                    case ' ':
                        if (!inBlanks)
                        {
                            inBlanks = true;
                            sb.Append(' ');
                        }   
                        continue;
                    default:
                        inBlanks = false;
                        sb.Append(c);
                        break;
                }
            }
            return sb.ToString().Trim();
        }
Дэвид С.
источник
Просто для подтверждения: функция SingleSpacedTrim () делает то же самое, что и строка noHTMLNormalised = Regex.Replace (noHTML, @ "\ s {2,}", ""); из ответа Рави Таплияла?
Джимми
@Jimmy, насколько я вижу, это регулярное выражение не захватывает отдельные табуляции или символы новой строки, как SingleSpacedTrim (). Хотя это может быть желательным эффектом, в этом случае просто снимите футляры по мере необходимости.
Дэвид С.
Хорошо, но похоже, что одинарные и двойные кавычки заменяются пробелами, хотя их нет в списке notOkCharacter , или мне что-то там не хватает? Вызывается ли эта часть методов декодирования / кодирования в начале? Что необходимо для сохранения этих персонажей?
vm370
4
var noHtml = Regex.Replace(inputHTML, @"<[^>]*(>|$)|&nbsp;|&zwnj;|&raquo;|&laquo;", string.Empty).Trim();
MRP
источник
1

Я использовал код @RaviThapliyal и @Don Rolling, но внес небольшие изменения. Поскольку мы заменяем & nbsp пустой строкой, но вместо этого & nbsp следует заменить пробелом, поэтому добавлен дополнительный шаг. Это сработало для меня как шарм.

public static string FormatString(string value) {
    var step1 = Regex.Replace(value, @"<[^>]+>", "").Trim();
    var step2 = Regex.Replace(step1, @"&nbsp;", " ");
    var step3 = Regex.Replace(step2, @"\s{2,}", " ");
    return step3;
}

Используется & nbps без точки с запятой, потому что он форматировался переполнением стека.

Сабик А Хан
источник
0

это:

(<.+?> | &nbsp;)

будет соответствовать любому тегу или &nbsp;

string regex = @"(<.+?>|&nbsp;)";
var x = Regex.Replace(originalString, regex, "").Trim();

тогда x = hello

Jonesopolis
источник
0

Очистка HTML-документа связана с множеством хитрых вещей. Этот пакет может помочь: https://github.com/mganss/HtmlSanitizer

Ehsan88
источник
Я думаю, это больше против XSS-атак, чем для нормализации html
Revious
1
@Revious Думаю, ты прав. Возможно, мой ответ не имеет большого отношения к вопросу OP, поскольку они не упомянули цель удаления тегов html. Но если целью является предотвращение атак, как это во многих случаях, то использование уже разработанного дезинфицирующего средства может быть лучшим подходом. Кстати, я не знаю, что означает нормализация html .
Ehsan88
0

HTML в своей основной форме - это просто XML. Вы можете проанализировать свой текст в объекте XmlDocument, а в корневом элементе вызвать InnerText для извлечения текста. Это удалит все HTML-теги в любой форме, а также обработает специальные символы, такие как & lt; & nbsp; все за один раз.

nivs1978
источник