RegEx.Replace但排除html标签内的匹配?

时间:2011-05-24 15:01:33

标签: c# asp.net regex

我有一个名为HighlightKeywords的辅助方法,我在查看搜索结果时在论坛上使用,以突出显示用户搜索过的帖子中的关键字。

我遇到的问题是,例如用户搜索关键字“hotmail”,然后HighlightKeywords方法找到该关键字的匹配项,并用指定要应用的样式的span标记包装它,它在内部查找匹配项html锚标签,在某些情况下还有图像标签。因此,当我将突出显示的帖子渲染到屏幕时,html标签会被破坏(由于跨度插入其中)。

这是我的功能:

public static string HighlightKeywords(this string s, string keywords, string cssClassName)
    {
        if (s == string.Empty || keywords == string.Empty)
        {
            return s;
        }

        string[] sKeywords = keywords.Split(' ');
        foreach (string sKeyword in sKeywords)
        {
            try
            {
                s = Regex.Replace(s, @"\b" + sKeyword + @"\b", string.Format("<span class=\"" + cssClassName + "\">{0}</span>", "$0"), RegexOptions.IgnoreCase);
            }
            catch {}
        }
        return s;
    }

防止这种情况破坏的最佳方法是什么?即使我只是简单地排除锚标记内发生的任何匹配(无论是网络地址还是电子邮件地址)还是图像标记?

3 个答案:

答案 0 :(得分:4)

没有。你不能这样做。至少,不是不会破坏的方式。正则表达式不能解析HTML的任务。真的对不起。你也想读这个咆哮:RegEx match open tags except XHTML self-contained tags

所以,您可能需要解析HTML(我听说HtmlAgilityPack很好),然后只匹配文档的某些部分 - 不包括锚标记等。

答案 1 :(得分:1)

我遇到了同样的问题,想出了这项工作

    public static string HighlightKeyWords(string s, string[] KeyWords)
    {
        if (KeyWords != null && KeyWords.Count() > 0 && !string.IsNullOrEmpty(s))
        {
            foreach (string word in KeyWords)
            {
                s = System.Text.RegularExpressions.Regex.Replace(s, word, string.Format("{0}", "{0}$0{1}"), System.Text.RegularExpressions.RegexOptions.IgnoreCase);
            }
        }

        s = string.Format(s, "<mark class='hightlight_text_colour'>", "</mark>");

        return s;
    }

看起来有些可怕,但我推迟添加html标签,直到正则表达式匹配所有关键字,在{0}和{1}位置添加了乞讨和结束html标记,而不是标签。然后我在最后添加html标签, 使用圈内的占位符。

如果关键字{0}或{1}作为关键字传入,则仍会中断。

答案 2 :(得分:0)

马库斯,恢复了这个问题,因为它有一个简单的解决方案,没有提到。这种情况听起来与Match (or replace) a pattern except in situations s1, s2, s3 etc非常相似。

关于使用正则表达式解析html的所有免责声明,这是一种简单的方法。

hotmail为例,以最简单的形式展示技术,这里是我们简单的正则表达式:

<a.*?</a>|(hotmail)

交替的左侧匹配完整的<a ... </a>标签。我们将忽略这些匹配。右侧匹配并捕获hotmail到组1,我们知道它们是正确的hotmail,因为它们与左侧的表达式不匹配。

此程序显示了如何使用正则表达式(请参阅online demo底部的结果):

using System;
using System.Text.RegularExpressions;
using System.Collections.Specialized;
class Program
{
static void Main() {
var myRegex = new Regex(@"<a.*?</a>|(hotmail)");
string s1 = @"replace this=> hotmail not that => <a href=""http://hotmail.com"">hotmail</a>";

string replaced = myRegex.Replace(s1, delegate(Match m) {
if (m.Groups[1].Value != "") return "<span something>hotmail</span>";
else return m.Value;
});
Console.WriteLine("\n" + "*** Replacements ***");
Console.WriteLine(replaced);


Console.WriteLine("\nPress Any Key to Exit.");
Console.ReadKey();

} // END Main
} // END Program

参考

How to match (or replace) a pattern except in situations s1, s2, s3...