使用ASP.NET,如何可靠地剥离给定字符串中的HTML标签(即不使用正则表达式)?我正在寻找类似PHP的东西strip_tags
。
例:
<ul><li>Hello</li></ul>
输出:
“你好”
我尝试不重新发明轮子,但是到目前为止,我还没有找到任何满足我需求的东西。
使用ASP.NET,如何可靠地剥离给定字符串中的HTML标签(即不使用正则表达式)?我正在寻找类似PHP的东西strip_tags
。
<ul><li>Hello</li></ul>
“你好”
我尝试不重新发明轮子,但是到目前为止,我还没有找到任何满足我需求的东西。
Answers:
如果只是从字符串中剥离所有 HTML标记,则这也可以与regex 可靠地一起工作。更换:
<[^>]*(>|$)
与空字符串,全局。不要忘了之后将字符串标准化,替换为:
[\s\r\n]+
与单个空格,并修剪结果。(可选)将所有HTML字符实体替换回实际字符。
注意事项:
"e;
。我WebUtility.HtmlDecode
为此与它结合(反过来也不会删除标签)。删除标记后使用它,因为它可能会重写>
和<
。EGWebUtility.HtmlDecode(Regex.Replace(myTextVariable, "<[^>]*(>|$)", string.Empty))
立即下载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;
}
text()
节点,修剪内容和字符串。IEnumerable<string> allText = doc.DocumentNode.SelectNodes("//text()").Select(n => n.InnerText.Trim())
if (doc == null)
检查?这总是假的,不是吗?
Regex.Replace(htmlText, "<.*?>", string.Empty);
RegexOptions.SingleLine
。
我已经将其发布在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;
我用C#编写了一个非常快速的方法,它使Regex胜出了。它托管在CodeProject上的一篇文章中。
它的优点是,在更好的性能中,它具有替换命名和编号的HTML实体(如&amp;
和&203;
)以及注释块替换的功能。
请阅读CodeProject上的相关文章。
谢谢。
对于无法使用HtmlAgilityPack的用户,可以选择.NETs XML阅读器。尽管在格式正确的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;
}
对于那些对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;
}
}
我看过这里建议的基于正则表达式的解决方案,除了在最琐碎的情况下,它们没有使我充满信心。一个属性中的尖括号就足以打破它,更不用说野蛮格式错误的HTML了。那像这样的实体呢&
呢?如果要将HTML转换为纯文本,则也需要解码实体。
因此,我提出以下方法。
使用HtmlAgilityPack,此扩展方法可以有效地从html片段中剥离所有HTML标记。还可以解码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页面(>
变为>
等)。
对于第二个参数,即保留一些标签,您可能需要使用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/
您也可以使用AngleSharp来完成此操作,它可以替代HtmlAgilityPack(不是说HAP不好)。比起HAP,从HTML源中获取文本要容易得多。
var parser = new HtmlParser();
var htmlDocument = parser.ParseDocument(source);
var text = htmlDocument.Body.Text();
您可以看一下关键功能部分,在这些部分中它们比HAP更好。我认为在大多数情况下,这对于当前问题可能是过大了,但仍然是一个有趣的选择。