【问题标题】:Search and replace non-HTML content搜索和替换非 HTML 内容
【发布时间】:2009-07-25 06:00:39
【问题描述】:

我需要编写一些代码来搜索和替换 HTML 标记之外的字符串中的整个单词。所以如果我有这个字符串:

string content = "the brown fox jumped over <b>the</b> lazy dog over there";
string keyword = "the";

我需要类似的东西:

if (content.ToLower().Contains(keyword.ToLower()))
       content = content.Replace(keyword, String.Format("<span style=\"background-color:yellow;\">{0}</span>", keyword));

但我不想替换粗体标签中的“the”或“there”中的“the”,只替换第一个“the”。

【问题讨论】:

    标签: c# html string


    【解决方案1】:

    您可以使用 this 库来解析您的 html 并仅替换不在任何 html 中的单词,仅替换单词“the”而不是“three”使用 RegEx.Replace("the\s+" ...) 而不是字符串替换

    【讨论】:

      【解决方案2】:

      试试这个:

      content = RegEx.Replace(content, "(?<!>)" 
         + keyword 
         + "(?!(<|\w))", "<span blah...>" + keyword + '</span>';
      

      编辑:我修复了“这些”的情况,但没有修复超过关键字包含在 HTML 中的情况,例如,“狐狸跳过 懒惰的狗。”

      使用 RegEx 和普通的日常 HTML 几乎不可能实现您的要求,因为要知道您是否在标签“内部”,您必须“配对”每个开始和结束标签,并且忽略旨在自动关闭的标签(例如 BR 和 IMG)。

      如果这只是一个网站的吸引眼球,我建议采用另一条路线:修复你的 CSS,以便你添加的 SPAN 只影响标签外的 HTML。

      例如:

      content = content.Replace("the", "<span class=\"highlight\">the</span>");
      

      然后,在你的 CSS 中:

      span.highlight { background-color: yellow; }
      
      b span.highlight,
      i span.highlight,
      em span.highlight,
      strong span.highlight,
      p span.highlight,
      blockquote span.highlight { background: none; }
      

      只需为每个不应突出显示内容的 HTML 标记添加一个排除项。

      【讨论】:

        【解决方案3】:

        我喜欢使用 HTML 解析器的建议,但让我提出一种枚举顶级文本(无封闭标签)区域的方法,您可以在闲暇时对其进行转换和重组。

        本质上,您可以将每个顶级打开标记视为 {,并仅跟踪该标记的嵌套。与您想自己进行的常规解析相比,这可能足够简单。

        以下是一些潜在的陷阱:

        如果不是 XHTML,则需要一个始终为空的标签列表:

        <hr> , <br> and <img> (are there more?).
        

        对于所有开始标签,如果以 /> 结尾,则立即关闭 - {} 而不是 {。

        不区分大小写 - 我相信您会想不区分地匹配标签名称(只需 lc 全部)。

        超级宽松的浏览器解释,如

        "<p> <p>" = "<p> </p><p>" = {}{ 
        

        带引号的实体不允许包含 (它们需要使用 <),但也许浏览器在那里也是超级宽容的。

        本质上,如果你想解析正确 HTML标记,没有问题。

        所以,算法:

        “前一个标签的结尾”=字符串的开始

        反复搜索下一个开放标签(不区分大小写)或字符串结尾:

        < *([^ >/]+)[^/>]*(/?) *>|$
        

        句柄(前一个标签的结束,匹配的开始)作为所有标签之外的区域。

        设置标记名=lc($1)。如果有 / ($2 不为空),则更新 end 并从 start 继续。否则,深度=1,

        1. 当 depth > 0 时,扫描下一个(也不区分大小写):

          如果 $1,那么它是一个关闭标签 (depth-=1)。否则,如果不是 2 美元,那就是另一个开放标签;深度+=1。在任何情况下,继续循环(回到 1。)

        回到开始(你又回到了顶级)。请注意,我在顶部说“扫描顶级打开标记的下一个开始,或字符串的结尾”,即确保处理挂在最后一个结束标记上的顶级文本。

        就是这样。本质上,您可以忽略除当前正在监控的最顶层标签之外的所有其他标签,假设输入标记已正确嵌套(它仍然可以正常工作以防止 一些 类型的错误嵌套) .

        另外,无论我在上面写了什么空格,都应该是任何空格(在 / 和标签名称之间,你可以使用任何你喜欢的空格)。

        正如您所看到的,仅仅因为问题比完整的 HTML 解析稍微容易一些,并不一定意味着您不应该使用真正的 HTML 解析器 :) 您可能会搞砸很多事情。

        【讨论】:

        • 我应该补充一点,一些正则表达式语法 (Perl) 允许平衡括号计数,即它们不是真正的常规语言。我怀疑该设施可以处理像 这样的封闭标签,但你可以尝试一下。
        【解决方案4】:

        您需要提供更多详细信息。

        例如:

        <p>the brown fox</p>
        

        在技术上位于 HTML 标记内。

        【讨论】:

        • 那么我不想要那个“the”。只是 HTML 之外的整个单词。
        • every 在某种程度上都包含在 HTML 中。您的源内容是什么样的?
        猜你喜欢
        • 2015-11-23
        • 1970-01-01
        • 1970-01-01
        • 2013-05-02
        • 1970-01-01
        • 2019-01-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多