使用C#正则表达式删除HTML标签

问题描述 投票:0回答:11

如何使用 C# 正则表达式替换/删除所有 HTML 标签,包括尖括号? 有人可以帮我看一下代码吗?

c# html regex parsing
11个回答
178
投票

正如之前经常提到的,不应使用正则表达式来处理 XML 或 HTML 文档。它们在 HTML 和 XML 文档中表现不佳,因为无法以通用方式表达嵌套结构。

您可以使用以下内容。

String result = Regex.Replace(htmlDocument, @"<[^>]*>", String.Empty);

这适用于大多数情况,但在某些情况下(例如包含尖括号的 CDATA)这将无法按预期工作。


85
投票

正确的答案是不要这样做,请使用 HTML Agility Pack

编辑添加:

为了无耻地窃取 jesse 下面的评论,并避免被指责没有充分回答问题,这里有一个使用 HTML Agility Pack 的简单、可靠的代码片段,它甚至可以处理最不完美、反复无常的 HTML 部分:

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(Properties.Resources.HtmlContents);
var text = doc.DocumentNode.SelectNodes("//body//text()").Select(node => node.InnerText);
StringBuilder output = new StringBuilder();
foreach (string line in text)
{
   output.AppendLine(line);
}
string textOnly = HttpUtility.HtmlDecode(output.ToString());

使用正则表达式解析 HTML 的合理案例很少,因为如果没有上下文感知,就无法正确解析 HTML,即使在非传统的正则表达式引擎中提供上下文感知也是非常痛苦的。您可以使用正则表达式实现这一目标,但您需要进行手动验证。

Html Agility Pack 可以为您提供强大的解决方案,减少手动修复由于天真地将 HTML 视为上下文无关语法而导致的异常的需要。

正则表达式可能在大多数情况下都能满足您的需求,但在非常常见的情况下它会失败。如果您能找到比 HTML Agility Pack 更好/更快的解析器,那就去吧,但请不要让世界遭受更多破坏性的 HTML 黑客攻击。


39
投票

这个问题太宽泛,无法明确回答。 您是在谈论从现实世界的 HTML 文档(例如网页)中删除所有标签吗? 如果是这样,您必须:

  • 删除
  • 删除所有 SGML 注释
  • 删除整个 HEAD 元素
  • 删除所有 SCRIPT 和 STYLE 元素
  • Grabthar 知道如何使用 FORM 和 TABLE 元素
  • 删除剩余的标签
  • 从 CDATA 部分中删除 序列,但保留其内容

这就是我的想法——我确信还有更多。 完成所有这些后,您最终会在某些地方看到单词、句子和段落,而在其他地方则出现大块无用的空白。

但是,假设您只使用一个片段,并且只需删除所有标签就可以摆脱困境,这是我将使用的正则表达式:

@"(?></?\w+)(?>(?:[^>'""]+|'[^']*'|""[^""]*"")*)>"

在各自的替代方案中匹配单引号和双引号字符串足以解决属性值中的尖括号问题。 我认为没有必要显式匹配标签内的属性名称和其他内容,就像 Ryan 的答案中的正则表达式那样;第一个替代方案可以处理所有这些。

如果您对那些

(?>...)
结构感到好奇,它们是 原子团。 它们使正则表达式更加高效,但更重要的是,它们可以防止失控回溯,这是当您像我一样混合交替和嵌套量词时应该始终注意的事情。 我真的不认为这会是一个问题,但我知道如果我不提及它,其他人会的。 ;-)

当然,这个正则表达式并不完美,但它可能已经满足您的需要了。


28
投票
Regex regex = new Regex(@"</?\w+((\s+\w+(\s*=\s*(?:"".*?""|'.*?'|[^'"">\s]+))?)+\s*|\s*)/?>", RegexOptions.Singleline);

来源


20
投票

@JasonTrue 是正确的,不应通过正则表达式来剥离 HTML 标签。

使用 HtmlAgilityPack 剥离 HTML 标签非常简单:

public string StripTags(string input) {
    var doc = new HtmlDocument();
    doc.LoadHtml(input ?? "");
    return doc.DocumentNode.InnerText;
}

14
投票

我想回应 Jason 的回应,尽管有时你需要天真地解析一些 Html 并提取文本内容。

我需要使用一些由富文本编辑器创建的 Html 来完成此操作,总是很有趣和游戏。

在这种情况下,您可能需要删除某些标签的内容以及标签本身。

就我而言,标签被扔进了这个组合中。有些人可能会发现我的(稍微)不太幼稚的实现是一个有用的起点。

   /// <summary>
    /// Removes all html tags from string and leaves only plain text
    /// Removes content of <xml></xml> and <style></style> tags as aim to get text content not markup /meta data.
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public static string HtmlStrip(this string input)
    {
        input = Regex.Replace(input, "<style>(.|\n)*?</style>",string.Empty);
        input = Regex.Replace(input, @"<xml>(.|\n)*?</xml>", string.Empty); // remove all <xml></xml> tags and anything inbetween.  
        return Regex.Replace(input, @"<(.|\n)*?>", string.Empty); // remove any tags but not there content "<p>bob<span> johnson</span></p>" becomes "bob johnson"
    }

6
投票

在此 URL 尝试正则表达式方法:http://www.dotnetperls.com/remove-html-tags

/// <summary>
/// Remove HTML from string with Regex.
/// </summary>
public static string StripTagsRegex(string source)
{
return Regex.Replace(source, "<.*?>", string.Empty);
}

/// <summary>
/// Compiled regular expression for performance.
/// </summary>
static Regex _htmlRegex = new Regex("<.*?>", RegexOptions.Compiled);

/// <summary>
/// Remove HTML from string with compiled Regex.
/// </summary>
public static string StripTagsRegexCompiled(string source)
{
return _htmlRegex.Replace(source, string.Empty);
}

4
投票

用这个..

@"(?></?\w+)(?>(?:[^>'""]+|'[^']*'|""[^""]*"")*)>"

2
投票

.+?
中添加
<[^>]*>
并尝试这个正则表达式(基于this):

<[^>].+?>

c# .net 正则表达式演示 enter image description here


0
投票

由于

"//body//text()"
XPath,@JasonTrue 的答案似乎不再有效。

访问文档的所有子节点,然后过滤掉空文本标签可能是一种方法。

public static string StripInnerText(string html)
{
    if (string.IsNullOrEmpty(html))
    return null;

    HtmlAgilityPack.HtmlDocument doc = new();
    doc.LoadHtml(html);

    var texts = doc.DocumentNode.ChildNodes
        .Select(node => node.InnerText)
        .Where(text => !string.IsNullOrWhiteSpace(text))
        .Select(text => text.Trim())
        .ToList();

    var output = string.Join(Environment.NewLine, texts);

    string textOnly = HttpUtility.HtmlDecode(output.ToString());

    return textOnly;
}

使用以下小提琴进行测试: https://dotnetfiddle.net/NQC2Y5

很抱歉发布新答案,因为我目前没有 50 声望,这个问题和这里的所有答案对我来说非常有用,我觉得我有责任做出贡献。


-2
投票

使用此方法删除标签:

public string From_To(string text, string from, string to)
{
    if (text == null)
        return null;
    string pattern = @"" + from + ".*?" + to;
    Regex rx = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);
    MatchCollection matches = rx.Matches(text);
    return matches.Count <= 0 ? text : matches.Cast<Match>().Where(match => !string.IsNullOrEmpty(match.Value)).Aggregate(text, (current, match) => current.Replace(match.Value, ""));
}
© www.soinside.com 2019 - 2024. All rights reserved.