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

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

пример:

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

выход:

"Привет"

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

13 ответов


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

<[^>]*(>|$)

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

[\s\r\n]+

С одним пробелом и обрезкой результата. При необходимости замените все сущности символов HTML обратно на фактические символы.

Примечание:

  1. существует ограничение: HTML и XML позволяют > в значениях атрибутов. Это решение будет возврат сломанной разметки при обнаружении таких значений.
  2. решение технически безопасно, как в: результат никогда не будет содержать ничего, что может быть использовано для создания межсайтовых сценариев или для разрыва макета страницы. Она просто не очень чистая.
  3. как со всеми вещами HTML и regex:
    использовать правильный парсер если вы должны получить его прямо при всех обстоятельства.

перейти скачать HTMLAgilityPack, сейчас! ;) Ссылка Для Скачивания

Это позволяет загружать и анализировать 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;
            }

Regex.Replace(htmlText, "<.*?>", string.Empty);

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

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


System.Web.UI.HtmlControls.HtmlGenericControl htmlDiv = new System.Web.UI.HtmlControls.HtmlGenericControl("div");
htmlDiv.InnerHtml = htmlString;
String plainText = htmlDiv.InnerText;

Я написал довольно быстрый метод на c#, который бьет из регулярного выражения. Он размещен в статьи на CodeProject.

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

пожалуйста, читайте связанная статья о CodeProject.

спасибо.


для тех из вас, кто не может использовать HtmlAgilityPack, .NETs XML reader является опцией. Это может потерпеть неудачу на хорошо отформатированном HTML, хотя всегда добавляйте улов с 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;
    }

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

для тех, кто жалуется на то, что решение Майкла Типтопа не работает, вот .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's innerText
    }
    catch
    {
        return string.Empty;
    }
}

Я посмотрел на решения на основе регулярных выражений, предложенные здесь, и они не наполняют меня уверенностью, за исключением самых тривиальных случаев. Угловая скобка в атрибуте-это все, что нужно, чтобы сломать, не говоря уже о MAL-formmed 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; и т. д.).


для второго параметра, т. е. сохранить некоторые теги, вам может понадобиться такой код, используя 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/


using System.Text.RegularExpressions;

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

просто использовать string.StripHTML();