【问题标题】:RegEx.Replace but exclude matches within html tags?RegEx.Replace 但排除 html 标签中的匹配项?
【发布时间】:2011-05-24 15:01:32
【问题描述】:

我有一个名为 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;
    }

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

【问题讨论】:

  • 您确实需要使用某种 HTML 解析器,检查每个元素是否匹配。如果包含元素能够接受部分包含文本的样式,则应用它。

标签: c# asp.net regex


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    我遇到了同样的问题,想出了这个解决方法

        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 标记,直到正则表达式匹配所有关键字,为 begging 和 end html 标记添加 {0} 和 {1} 占位符,而不是标签。然后我在最后添加html标签, 使用循环内部的占位符。

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

    【讨论】:

    • 这是个好主意。我的问题(可能和你的一样,而不是原始海报)是我的初始文本不是 html,但我想突出显示的一些关键字与通过替换以前的关键字添加的 HTML 相匹配 - 例如如果关键字是“a”,它将匹配“==" 作为我的替换文本。
    【解决方案3】:

    Marcus,重新提出这个问题,因为它有一个未提及的简单解决方案。这种情况听起来与Match (or replace) a pattern except in situations s1, s2, s3 etc 非常相似。

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

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

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

    交替的左侧匹配完整的&lt;a ... &lt;/a&gt; 标签。我们将忽略这些匹配。右侧将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...

    【讨论】:

      猜你喜欢
      • 2015-06-17
      • 1970-01-01
      • 2011-02-04
      • 2018-06-22
      • 2011-04-16
      • 2012-06-23
      • 1970-01-01
      • 2015-08-12
      • 2017-02-18
      相关资源
      最近更新 更多