Видаліть теги 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

Відповіді:


196

Якщо ви не можете використовувати орієнтоване на синтаксичний аналізатор HTML рішення для фільтрації тегів, ось простий регулярний вираз для нього.

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

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

string noHTMLNormalised = Regex.Replace(noHTML, @"\s{2,}", " ");

Я ще не тестував цього стільки, скільки мені потрібно, але це працювало краще, ніж я очікував, що це спрацює. Я опублікую метод, який я написав нижче.
Дон Роллінг

Ледачий матч ( <[^>]+?>згідно @David S.) може зробити це трохи швидшим, але просто використовував це рішення в прямому ефірі - дуже щасливий +1 :)
Пройшло кодування

Regex.Replace (inputHTML, @ "<[^>] +> | & nbsp | \ n;", "") .Trim (); \ n не видаляється
Махеш Мальпані

3
Я б порекомендував додати пробіл, а не порожній рядок, ми Regex.Replace(inputHTML, @"<[^>]+>|&nbsp;", " ")
виловлюємо

2
@Tauseef Якщо ви використовуєте пробіл під час першого виклику заміни, ви можете в кінцевому підсумку залишити пробіли там, де їх у вихідному введенні не було. Скажімо, ви отримуєте Sound<b>Cloud</b>як вхід; ви закінчите, Sound Cloudпоки це повинно було бути позбавлене, SoundCloudоскільки саме так воно відображається в HTML.
Раві Тапліял

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

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


0

Дезінфекція HTML-документа передбачає багато складних речей. Цей пакет може допомогти: https://github.com/mganss/HtmlSanitizer


Я думаю, що це більше проти XSS-атак, ніж для нормалізації html
Оновлення

1
@Revious Я думаю, що ти маєш рацію. Можливо, моя відповідь мало пов'язана з питанням ОП, оскільки вони не згадали мету видалення тегів html. Але якщо метою є запобігання атакам, як це буває у багатьох випадках, то використання вже розробленого дезінфікуючого засобу може бути кращим підходом. До речі, я не знаю про те, що означає нормалізація html .
Ehsan88

0

HTML у своїй базовій формі - це просто XML. Ви можете проаналізувати текст в об'єкті XmlDocument і в кореневому елементі викликати InnerText для вилучення тексту. Це призведе до видалення всіх HTML-тегів у будь-якій формі, а також матиме справу зі спеціальними символами, такими як & lt; & nbsp; все одним рухом.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.