在C#中删除字符串中的HTML标签,包括 

88

我该如何在C#中使用正则表达式删除所有的HTML标签,包括&nbsp?我的字符串如下:

  "<div>hello</div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div>"

9
不使用正则表达式,可以尝试使用HTML Agility Pack。参考链接:https://dev59.com/ZXRA5IYBdhLWcg3wvQhh - Tim
1
谢谢Tim,但是这个应用程序非常庞大且完整,添加或下载HTML敏捷包不起作用。 - rampuriyaaa
10个回答

213

如果您无法使用面向HTML解析器的解决方案来过滤标签,这里有一个简单的正则表达式可以实现。

string noHTML = Regex.Replace(inputHTML, @"<[^>]+>|&nbsp;", "").Trim();

最好再通过正则表达式过滤器进行一次处理,以处理多个空格。

string noHTMLNormalised = Regex.Replace(noHTML, @"\s{2,}", " ");

1
一个懒惰匹配(<[^>]+?>,如@David S.所述)可能会使这个过程更快一些,但是我在一个实时项目中使用了这个解决方案 - 非常满意 +1 :) - iCollect.it Ltd
3
我建议添加一个空格而不是一个空字符串,因为我们无论如何都会去除多余的空格。 Regex.Replace(inputHTML, @"<[^>]+>|&nbsp;", " ") - Tauseef
@Tauseef:我同意。&nbsp;表示空格,所以仅仅删除它是没有意义的。 - awe
2
@Tauseef 如果你在第一个替换调用中使用空格,可能会导致在原始输入中没有空格的地方留下空格。比如说,如果你收到 Sound<b>Cloud</b> 作为输入,你最终会得到 Sound Cloud,而它应该被剥离为 SoundCloud,因为这是在 HTML 中显示的方式。 - Ravi K Thapliyal
@Tauseef 在同样的情况下,你最终会将 Sound <b>Cloud</b> 转换为 SoundCloud,但现在你需要输出 Sound Cloud,因为这是它在HTML中呈现的方式。 - Ravi K Thapliyal
显示剩余7条评论

33

我采用了@Ravi Thapliyal的代码并创建了一个方法:它很简单,可能不能清理所有内容,但目前它正在做我需要做的事情。

public static string ScrubHtml(string value) {
    var step1 = Regex.Replace(value, @"<[^>]+>|&nbsp;", "").Trim();
    var step2 = Regex.Replace(step1, @"\s{2,}", " ");
    return step2;
}

17

我已经使用这个函数一段时间了。它可以清理掉几乎所有混乱的html并保留文本原貌,非常实用。

        private static readonly Regex _tags_ = new Regex(@"<[^>]+?>", RegexOptions.Multiline | RegexOptions.Compiled);

        //add characters that are should not be removed to this regex
        private static readonly Regex _notOkCharacter_ = new Regex(@"[^\w;&#@.:/\\?=|%!() -]", RegexOptions.Compiled);

        public static String UnHtml(String html)
        {
            html = HttpUtility.UrlDecode(html);
            html = HttpUtility.HtmlDecode(html);

            html = RemoveTag(html, "<!--", "-->");
            html = RemoveTag(html, "<script", "</script>");
            html = RemoveTag(html, "<style", "</style>");

            //replace matches of these regexes with space
            html = _tags_.Replace(html, " ");
            html = _notOkCharacter_.Replace(html, " ");
            html = SingleSpacedTrim(html);

            return html;
        }

        private static String RemoveTag(String html, String startTag, String endTag)
        {
            Boolean bAgain;
            do
            {
                bAgain = false;
                Int32 startTagPos = html.IndexOf(startTag, 0, StringComparison.CurrentCultureIgnoreCase);
                if (startTagPos < 0)
                    continue;
                Int32 endTagPos = html.IndexOf(endTag, startTagPos + 1, StringComparison.CurrentCultureIgnoreCase);
                if (endTagPos <= startTagPos)
                    continue;
                html = html.Remove(startTagPos, endTagPos - startTagPos + endTag.Length);
                bAgain = true;
            } while (bAgain);
            return html;
        }

        private static String SingleSpacedTrim(String inString)
        {
            StringBuilder sb = new StringBuilder();
            Boolean inBlanks = false;
            foreach (Char c in inString)
            {
                switch (c)
                {
                    case '\r':
                    case '\n':
                    case '\t':
                    case ' ':
                        if (!inBlanks)
                        {
                            inBlanks = true;
                            sb.Append(' ');
                        }   
                        continue;
                    default:
                        inBlanks = false;
                        sb.Append(c);
                        break;
                }
            }
            return sb.ToString().Trim();
        }

只是确认一下:SingleSpacedTrim()函数和Ravi Thapliyal的答案中的string noHTMLNormalised = Regex.Replace(noHTML, @"\s{2,}", " ");做的是同样的事情吗? - Jimmy
@Jimmy 就我所看到的,那个正则表达式没有像 SingleSpacedTrim() 那样捕获单个制表符或换行符。不过这可能是一种期望的效果,如果是这样的话,只需根据需要删除这些情况即可。 - David S.
不错,但它似乎也将单引号和双引号替换为空格,尽管它们不在“_notOkCharacter_”列表中,或者我有什么遗漏吗?这是在开始时调用的解码/编码方法的一部分吗?为了保留这些字符,需要做什么? - ArgisIsland

4
var noHtml = Regex.Replace(inputHTML, @"<[^>]*(>|$)|&nbsp;|&zwnj;|&raquo;|&laquo;", string.Empty).Trim();

2

我使用了 @RaviThapliyal 和 @Don Rolling 的代码但进行了一点修改。由于我们将 &nbsp 替换为空字符串,但实际上应该用空格替换 &nbsp ,因此添加了一个额外的步骤。这对我来说非常有效。

最初的回答

public static string FormatString(string value) {
    var step1 = Regex.Replace(value, @"<[^>]+>", "").Trim();
    var step2 = Regex.Replace(step1, @"&nbsp;", " ");
    var step3 = Regex.Replace(step2, @"\s{2,}", " ");
    return step3;
}

最初的回答:由于 Stack Overflow 对其进行了格式化,因此使用了没有分号的 &nbsp。

1

我认为它更多地针对防止XSS攻击,而不是规范化HTML。 - Revious
1
@Revious 我认为你是对的。也许我的回答与OP的问题关系不大,因为他们没有提到删除HTML标签的目的。但是,如果目的是为了防止攻击,就像许多情况一样,那么使用已经开发好的清洁剂可能是更好的方法。顺便说一下,我不知道“规范化HTML”的含义是什么。 - Ehsan88

0
我正在使用这个语法来去除带有 &nbsp; 的 HTML 标签。
SessionTitle:result[i].sessionTitle.replace(/<[^>]+>|&**nbsp**;/g, '')

--Remove(*) **nbsp**

0

这个:

(<.+?> | &nbsp;)

将匹配任何标签或&nbsp;

string regex = @"(<.+?>|&nbsp;)";
var x = Regex.Replace(originalString, regex, "").Trim();

那么 x = hello


0

HTML基本上只是XML的一种形式。您可以将文本解析为XmlDocument对象,并在根元素上调用InnerText以提取文本。这将同时剥离所有形式的HTML标签以及处理特殊字符,如&lt;和&nbsp;。


-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接