【问题标题】:Highlight whole words, omit HTML突出显示整个单词,省略 HTML
【发布时间】:2009-08-23 18:51:49
【问题描述】:

我正在编写一些 C# 代码来解析 RSS 提要并突出显示内容中特定的整个单词,但是,我只需要突出显示 HTML 之外的单词。到目前为止,我有:

string contentToReplace = "This is <a href=\"test.aspx\" alt=\"This is test content\">test</a> content";

string pattern = "\b(this|the|test|content)\b";

string output = Regex.Replace(contentToReplace, pattern, "<span style=\"background:yellow;\">$1</span>", RegexOptions.Singleline | RegexOptions.IgnoreCase);

这很好用,除了它会在 alt 标签中突出显示单词“test”。我可以轻松编写一个剥离 HTML 的函数,然后进行替换,但我需要保留 HTML 以显示内容。

【问题讨论】:

    标签: c# regex string


    【解决方案1】:

    如果输入是有效的 XHTML/XML,您可以将其解析为树结构 (DOM/XLinq),递归遍历树,替换文本节点中出现的所有关键字,最后将树结构序列化回字符串。

    未经测试的伪代码:

    XNode Highlight(XElement element, List<string> keywords)
    {
        var result = new XElement(element.Name);
        // copy element attributes to result
    
        foreach (var node in element)
        {
            if (node.Type == NodeType.Text)
            {
                var value = node.Value;
                // while value contains keyword
                // {
                //      add substring before keyword in value to result
                //      add new XElement with highlighted keyword to result
                //      remove consumed substring from value
                // }
            }
            else if (node.Type == NodeType.Element)
            {
                result.Add(Highlight((XElement)node, keywords));
            }
            else
            {
                result.Add(node);
            }
        }
    
        return result;
    }
    
    var output = Highlight(XElement.Parse(input), new List<string> {...}).ToString();
    

    【讨论】:

    • 天哪,这将需要一些时间来解决我的问题。我会将其标记为答案,因为它似乎获得了最多的选票。
    • 如果 html 文档格式不正确,这将不起作用。不需要所有标签都在 html 中关闭。以 td 标签为例。您可以有一个未封闭的 td 标记,它是有效的 html,但它是无效的 xml。如果文档是 xhtml 但问题没有提及该细节,这将起作用。
    • 这就是为什么我的答案以“如果输入是有效的 XHTML/XML”开头的原因
    • 好吧,由于内容来自随机站点,它很可能不是有效的 XHTML。听起来这并不容易。为耻。
    【解决方案2】:

    如果您有有效的 XML 但不想解析它,另一种解决方案是:首先将输入字符串拆分为多个部分,使每个部分仅包含一个标签或文本,但不能同时包含两者。例如:

    "This is ",
    "<a href=\"test.aspx\" alt=\"This is test content\">",
    "test"
    "</a>"
    " content"
    

    然后遍历各个部分并将您的正则表达式仅应用于不以'&lt;' 开头的字符串。最后,将所有部分重新连接成一个字符串。

    【讨论】:

      【解决方案3】:

      这是一个基本的。

      private void Form1_Load(object sender, EventArgs e)
          {
              string contentToReplace = "This is <a href=\"test.aspx\" alt=\"This is test content\"> hello test world</a> content";
      
              string pattern = @"(>{1}.*)(test)(.*<{1})";
      
              string output = Regex.Replace(contentToReplace, pattern, "$1<span>$2</span>$3", RegexOptions.Singleline | RegexOptions.IgnoreCase);
      
              //output is :
              //This is <a href="test.aspx" alt="This is test content"> hello <span>test</span> world</a> content
      
      
              MessageBox.Show(output);
              Close();
          }
      

      【讨论】:

      • 如果输入是 "...&gt; hello test test world &lt;..." 会发生什么?正则表达式是替换两个出现的"test" 还是只替换第一个?
      • 这将匹配如下内容:&lt;img alt="&gt; test &lt;" src="..." /&gt;'' (which it shouldn't match) and fail to match test''(应该匹配)。
      • @dtb - 是的,刚刚测试了您的案例。它失败了
      • @strager - 是的,你的案子也会失败。
      猜你喜欢
      • 1970-01-01
      • 2017-06-23
      • 1970-01-01
      • 2014-08-07
      • 2019-06-24
      • 2017-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多