Как я могу удалить теги HTML из строки в ASP.NET?

115

Используя ASP.NET, как я могу надежно отделить HTML-теги от заданной строки (т.е. не использовать регулярное выражение)? Я ищу что-то вроде PHP strip_tags.

Пример:

<ul><li>Hello</li></ul>

Вывод:

"Hello"

Я стараюсь не изобретать колесо, но я не нашел ничего, что отвечало моим потребностям.

  • 3
    Почему нет регулярных выражений?
  • 0
    Я полагаю, что PHP strip_tags использует регулярные выражения за кулисами!
Показать ещё 4 комментария
Теги:
string

13 ответов

100
Лучший ответ

Если он просто удаляет все теги HTML из строки, это также надежно работает с регулярным выражением. Заменить:

<[^>]*(>|$)

с пустой строкой, глобально. Не забудьте впоследствии нормализовать строку, заменив:

[\s\r\n]+

с одним пробелом и обрезкой результата. Опционально замените любые элементы символа HTML на фактические символы.

Примечание:

  • Существует ограничение: HTML и XML позволяют > в значениях атрибутов. Это решение вернет поврежденную разметку при достижении таких значений.
  • Решение технически безопасно, так как в: Результат никогда не будет содержать ничего, что можно было бы использовать для межсайтового скриптинга или для разбивки макета страницы. Это просто не очень чисто.
  • Как со всеми вещами HTML и регулярное выражение:
    Используйте правильный парсер, если вы должны получить его правильно при любых обстоятельствах.
  • 45
    Хотя это и не требуется, я думаю, что многие читатели также захотят убрать HTM-кодирование, например &quote; , Я объединяю это с WebUtility.HtmlDecode для этого (который, в свою очередь, не будет удалять теги). Используйте его после удаления тега, так как он может переписать &gt; и &lt; , Например, WebUtility.HtmlDecode(Regex.Replace(myTextVariable, "<[^>]*(>|$)", string.Empty))
  • 0
    @YahooSerious Спасибо за пример. Это прекрасно работает. Спасибо.
Показать ещё 5 комментариев
65

Go скачать HTMLAgilityPack, сейчас!;) Загрузить LInk

Это позволяет загружать и анализировать HTML. Затем вы можете перемещаться по DOM и извлекать внутренние значения всех атрибутов. Серьезно, это займет около 10 строк кода максимум. Это одна из самых больших бесплатных библиотек .net.

Вот пример:

            string htmlContents = new System.IO.StreamReader(resultsStream,Encoding.UTF8,true).ReadToEnd();

            HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
            doc.LoadHtml(htmlContents);
            if (doc == null) return null;

            string output = "";
            foreach (var node in doc.DocumentNode.ChildNodes)
            {
                output += node.InnerText;
            }
  • 1
    Вы можете даже запросить каждый узел text() , обрезать содержимое и строку. Соедините с пробелом. IEnumerable<string> allText = doc.DocumentNode.SelectNodes("//text()").Select(n => n.InnerText.Trim())
  • 0
    или просто используйте doc.DocumentNode.InnerText, хотя это имеет некоторые проблемы с обработкой пробелов, кажется ...
Показать ещё 1 комментарий
57
Regex.Replace(htmlText, "<.*?>", string.Empty);
  • 5
    Это работает для меня, спасибо
  • 0
    Просто и приятно. Спасибо!
Показать ещё 2 комментария
11
protected string StripHtml(string Txt)
{
    return Regex.Replace(Txt, "<(.|\\n)*?>", string.Empty);
}    

Protected Function StripHtml(Txt as String) as String
    Return Regex.Replace(Txt, "<(.|\n)*?>", String.Empty)
End Function
  • 2
    Не работает во многих случаях, включая не Unix разрывы строк.
7

Я разместил это на форумах asp.net, и это все еще кажется одним из самых простых решений. Я не буду гарантировать его самым быстрым или эффективным, но он довольно надежный. В .NET вы можете сами использовать объекты HTML Web Control. Все, что вам действительно нужно сделать, это вставить вашу строку во временный объект HTML, такой как DIV, а затем использовать встроенный "InnerText", чтобы захватить весь текст, который не содержится в тегах. Ниже приведен простой пример С#:


System.Web.UI.HtmlControls.HtmlGenericControl htmlDiv = new System.Web.UI.HtmlControls.HtmlGenericControl("div");
htmlDiv.InnerHtml = htmlString;
String plainText = htmlDiv.InnerText;
  • 0
    похоже, это не работает, я протестировал его с помощью простого InnerHtml = "<b> foo </ b>"; и InnerText имеет значение "<b> foo </ b>" :(
  • 0
    Это не похоже на работу в asp.net 4.
Показать ещё 2 комментария
5

Я написал довольно быстрый метод в С#, который бьет ад из Regex. Он размещен в статье в CodeProject.

Его преимущества заключаются в том, что среди лучшей производительности есть возможность заменить именованные и пронумерованные HTML-объекты (те, что похожи на &amp;amp; и &203;), и заменить блоки комментариев и многое другое.

Пожалуйста, прочитайте статью .

Спасибо.

4

Для тех из вас, кто не может использовать HtmlAgilityPack,.NET XML-ридер является опцией. Это может завершиться неудачно на хорошо отформатированном HTML, хотя всегда добавляйте catch с regx в качестве резервной копии. Обратите внимание, что это НЕ быстро, но это дает хорошую возможность для старой школы пройти через отладку.

public static string RemoveHTMLTags(string content)
    {
        var cleaned = string.Empty;
        try
        {
            StringBuilder textOnly = new StringBuilder();
            using (var reader = XmlNodeReader.Create(new System.IO.StringReader("<xml>" + content + "</xml>")))
            {
                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Text)
                        textOnly.Append(reader.ReadContentAsString());
                }
            }
            cleaned = textOnly.ToString();
        }
        catch
        {
            //A tag is probably not closed. fallback to regex string clean.
            string textOnly = string.Empty;
            Regex tagRemove = new Regex(@"<[^>]*(>|$)");
            Regex compressSpaces = new Regex(@"[\s\r\n]+");
            textOnly = tagRemove.Replace(content, string.Empty);
            textOnly = compressSpaces.Replace(textOnly, " ");
            cleaned = textOnly;
        }

        return cleaned;
    }
4
string result = Regex.Replace(anytext, @"<(.|\n)*?>", string.Empty);
1

Для тех, кто усложняет решение Michael Tiptop, не работает, вот путь .Net4 +:

public static string StripTags(this string markup)
{
    try
    {
        StringReader sr = new StringReader(markup);
        XPathDocument doc;
        using (XmlReader xr = XmlReader.Create(sr,
                           new XmlReaderSettings()
                           {
                               ConformanceLevel = ConformanceLevel.Fragment
                               // for multiple roots
                           }))
        {
            doc = new XPathDocument(xr);
        }

        return doc.CreateNavigator().Value; // .Value is similar to .InnerText of  
                                           //  XmlDocument or JavaScript innerText
    }
    catch
    {
        return string.Empty;
    }
}
0
using System.Text.RegularExpressions;

string str = Regex.Replace(HttpUtility.HtmlDecode(HTMLString), "<.*?>", string.Empty);
0

Я рассмотрел предлагаемые здесь решения на основе Regex, и они не наполняют меня какой-либо уверенностью, кроме самых тривиальных случаев. Угол скобки в атрибуте - это все, что нужно, чтобы сломать, не говоря уже о некорректно сформированном HTML из дикой природы. А как насчет объектов вроде &amp;? Если вы хотите преобразовать HTML в обычный текст, вам также нужно декодировать объекты.

Итак, предлагаю метод ниже.

Используя HtmlAgilityPack, этот метод расширения эффективно удаляет все теги HTML из html-фрагмента. Также декодирует объекты HTML, такие как &amp;. Возвращает только внутренние текстовые элементы, с новой строкой между каждым текстовым элементом.

public static string RemoveHtmlTags(this string html)
{
        if (String.IsNullOrEmpty(html))
            return html;

        var doc = new HtmlAgilityPack.HtmlDocument();
        doc.LoadHtml(html);

        if (doc.DocumentNode == null || doc.DocumentNode.ChildNodes == null)
        {
            return WebUtility.HtmlDecode(html);
        }

        var sb = new StringBuilder();

        var i = 0;

        foreach (var node in doc.DocumentNode.ChildNodes)
        {
            var text = node.InnerText.SafeTrim();

            if (!String.IsNullOrEmpty(text))
            {
                sb.Append(text);

                if (i < doc.DocumentNode.ChildNodes.Count - 1)
                {
                    sb.Append(Environment.NewLine);
                }
            }

            i++;
        }

        var result = sb.ToString();

        return WebUtility.HtmlDecode(result);
}

public static string SafeTrim(this string str)
{
    if (str == null)
        return null;

    return str.Trim();
}

Если вы действительно серьезны, вы также должны игнорировать содержимое определенных HTML-тегов (<script>, <style>, <svg>, <head>, <object>), потому что они, вероятно, не содержат читаемого контента в том смысле, в котором мы нуждаемся. То, что вы там делаете, будет зависеть от ваших обстоятельств и того, как далеко вы хотите идти, но используя HtmlAgilityPack, это было бы довольно тривиально для белого или черного списка выбранных тегов.

Если вы возвращаете содержимое на страницу HTML, убедитесь, что вы понимаете уязвимость XSS и как ее предотвратить - т.е. всегда кодируйте любые введенный пользователем текст, который возвращается на HTML-страницу (> становится &gt; и т.д.).

-1

Для второго параметра, т.е. сохраните некоторые теги, вам может понадобиться некоторый код, подобный этому, используя HTMLagilityPack:

public string StripTags(HtmlNode documentNode, IList keepTags)
{
    var result = new StringBuilder();
        foreach (var childNode in documentNode.ChildNodes)
        {
            if (childNode.Name.ToLower() == "#text")
            {
                result.Append(childNode.InnerText);
            }
            else
            {
                if (!keepTags.Contains(childNode.Name.ToLower()))
                {
                    result.Append(StripTags(childNode, keepTags));
                }
                else
                {
                    result.Append(childNode.OuterHtml.Replace(childNode.InnerHtml, StripTags(childNode, keepTags)));
                }
            }
        }
        return result.ToString();
    }

Больше объяснений на этой странице: http://nalgorithm.com/2015/11/20/strip-html-tags-of-an-html-in-c-strip_html-php-equivalent/

-3

Просто используйте string.StripHTML();

  • 0
    string.StripHTML не является частью .NET Framework
  • 3
    Как указывает @Serpiton, в BCL такого метода нет. Не могли бы вы указать на реализацию этого метода или предоставить свой собственный?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню