如何在 ASP.NET 中从字符串中去除 HTML 标记?

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

例如:

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

产出:

“你好”

我试着不去重新发明轮子,但是到目前为止,我还没有找到任何符合我需要的东西。

146630 次浏览

如果它只是从字符串中剥离出 所有 HTML 标记,那么它也可以在正则表达式中使用 可靠。替换:

<[^>]*(>|$)

不要忘记将字符串标准化,替换以下内容:

[\s\r\n]+

可选择将任何 HTML 字符实体替换回实际字符。

注意 :

  1. 有一个限制: HTML 和 XML 允许在属性值中使用 >。此解决方案 威尔在遇到此类值时返回中断的标记。
  2. 这个解决方案在技术上是安全的,比如: 搜索结果永远不会包含任何可用于跨网站脚本或破坏页面布局的内容。只是不太干净。
  3. 和所有 HTML 和 regex 一样:
    如果在任何情况下都必须正确使用 一个合适的解析器,请使用 一个合适的解析器
Regex.Replace(htmlText, "<.*?>", string.Empty);

我已经用 c # 编写了一个非常快的方法,这个方法比正则表达式要快得多。它驻留在 CodeProject 的 一篇文章中。

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

请阅读 有关 CodeProject 的相关文章

谢谢你。

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

去下载 HTMLAgilityPack,现在! ;) 下载连结

这允许您加载和解析 HTML。然后您可以导航 DOM 并提取所有属性的内部值。说真的,最多只需要10行代码。这是最伟大的自由之一。网络图书馆。

下面是一个例子:

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

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


System.Web.UI.HtmlControls.HtmlGenericControl htmlDiv = new System.Web.UI.HtmlControls.HtmlGenericControl("div");
htmlDiv.InnerHtml = htmlString;
String plainText = htmlDiv.InnerText;
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

对于那些不能使用 HtmlAgilityPack 的人,。NETs 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;
}

对于那些抱怨 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's innerText
}
catch
{
return string.Empty;
}
}

只需使用 string.StripHTML();

我看了这里提出的基于 Regex 的解决方案,除了在最琐碎的情况下,它们没有给我任何信心。在属性中使用尖括号就可以中断,更不用说从野外生成格式不正确的 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><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);

您也可以使用 AngleSharp来实现这一点,AngleSharp是 HtmlAgilityPack 的替代品(并不是说 HAP 不好)。它比 HAP 更容易从 HTML 源代码中获取文本。

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

您可以看一下 主要特征部分,其中他们提出了一个比 HAP“更好”的理由。我认为,在大多数情况下,对于当前的问题来说,这可能是过分的,但仍然是一个有趣的选择。