如何从ASP.NET中的字符串中剥离HTML标记?

时间:2009-04-24 12:56:24

标签: c# asp.net html regex string

使用ASP.NET,如何可靠地从给定字符串中剥离HTML标记(即不使用正则表达式)?我正在寻找像PHP strip_tags

这样的东西

实施例

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

输出:

“你好”

我试图不重新发明轮子,但到目前为止我还没有找到满足我需求的东西。

14 个答案:

答案 0 :(得分:107)

如果它只是从字符串中剥离所有 HTML标记,那么这也适用于正则表达式。替换:

<[^>]*(>|$)
全局使用空字符串

。不要忘记之后规范化字符串,替换:

[\s\r\n]+

使用单个空格,并修剪结果。 (可选)将任何HTML字符实体替换为实际字符。

注意

  1. 存在一个限制:HTML和XML允许在属性值中使用>。遇到此类值时,此解决方案返回损坏的标记。
  2. 该解决方案在技术上是安全的,如下所示:结果将永远不会包含任何可用于执行跨站点脚本或打破页面布局的内容。它不是很干净。
  3. 与HTML和正则表达式相同:
    如果您必须在任何情况下都做到正确,请使用a proper parser

答案 1 :(得分:72)

立即下载HTMLAgilityPack! ;)Download 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;
            }

答案 2 :(得分:64)

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

答案 3 :(得分: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

答案 4 :(得分:6)

我已经在asp.net论坛上发布了它,它似乎仍然是那里最简单的解决方案之一。我不保证它是最快或最有效的,但它非常可靠。 在.NET中,您可以使用HTML Web Control对象本身。您真正需要做的就是将您的字符串插入到临时HTML对象(如DIV)中,然后使用内置的“InnerText”来获取标记中未包含的所有文本。请参阅下面的简单C#示例:


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

答案 5 :(得分:5)

我在c#中编写了一个非常快速的方法,它击败了正则表达式。它在CodeProject上的an article中托管。

它的优点是,在更好的性能中,能够替换命名和编号的HTML实体(如&amp;amp;&203;)和注释块替换等等。

请阅读related article on CodeProject

谢谢。

答案 6 :(得分:4)

对于那些不能使用HtmlAgilityPack的人来说,.NETs XML阅读器是一种选择。这可能会在格式良好的HTML上失败,但总是添加一个catch作为备份。请注意,这并不快,但它确实为老学校调试提供了一个很好的机会。

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;
    }

答案 7 :(得分:3)

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

答案 8 :(得分:1)

对于那些抱怨迈克尔蒂普顿的解决方案不起作用的人来说,这是.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;
    }
}

答案 9 :(得分:0)

我已经看过这里建议的基于正则表达式的解决方案,除了最琐碎的案例外,他们没有任何信心。属性中的尖括号是破坏所需的全部,更不用说来自野外的恶意形式的HTML。那些像&amp;这样的实体呢?如果要将HTML转换为纯文本,还需要解码实体。

所以我建议采用以下方法。

使用HtmlAgilityPack,此扩展方法可以有效地从html片段中删除所有HTML标记。还解码像&amp;这样的HTML实体。仅返回内部文本项,每个文本项之间都有一个新行。

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>,{ {1}}浮现在脑海中!)因为它们可能并不包含我们所追求的可读内容。你在那里做什么将取决于你的情况和你想走多远,但使用HtmlAgilityPack将所选标签列入白名单或黑名单将是非常简单的。

如果要将内容呈现回HTML页面,请确保您了解XSS漏洞&amp; how to prevent it - 即始终对任何用户输入的文字进行编码,这些文字会被渲染回HTML页面(<object>变为>等)。

答案 10 :(得分:0)

对于第二个参数,即。保留一些标签,你可能需要使用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/

答案 11 :(得分:0)

using System.Text.RegularExpressions;

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

答案 12 :(得分:0)

您也可以使用AngleSharp来完成此操作,它可以替代HtmlAgilityPack(不是说HAP不好)。比起HAP,从HTML源中提取文本要容易得多。

var parser = new HtmlParser();
var htmlDocument = parser.ParseDocument(source);
var text = htmlDocument.Body.Text();

您可以看看key features部分,他们在其中提出了比HAP“更好”的理由。我认为,在大多数情况下,这可能对当前问题有些大材小用,但仍然是一个有趣的选择。

答案 13 :(得分:-3)

只需使用string.StripHTML();

即可