MatchEvaluator 对大小写不敏感的文本换行,除非文本位于图像 HTML 标记内(但不忽略所有标记)
Posted
技术标签:
【中文标题】MatchEvaluator 对大小写不敏感的文本换行,除非文本位于图像 HTML 标记内(但不忽略所有标记)【英文标题】:MatchEvaluator to wrap text insensitive to case, EXCEPT when text is within an image HTML tag (but NOT ignoring ALL tags) 【发布时间】:2020-11-23 18:52:53 【问题描述】:我有一个在我的 CMS 中创建的 html 正文。我有一个自定义方法来突出显示文本中的搜索词,这样当用户从搜索结果导航到页面时,所有出现的搜索词都会被突出显示。我将此设置为不区分大小写,以便匹配的文本无论大小写都会突出显示,结果将保留原始大写:
var regex = new Regex(searchTerm, RegexOptions.IgnoreCase);
var evaluator = new MatchEvaluator(match => Evaluators.Wrap(match, textToFormat, "<span class='highlight'>0</span>"));
var highlightedText = regex.Replace(textToFormat, evaluator);
这会导致以下结果(假设用户搜索了“文本”):
"This is some text!" -> "This is some <span class='highlight'>text</span>!"
但是,我发现当 HTML 正文包含图像标签且图像 URL 包含搜索词时会出现问题。这破坏了页面上的图像。
"This is some text: <img src='/images/text.png'/>" -> "This is some <span class='highlight'>text</span>: <img src='/images/<span class='highlight'>text</span>.png'/>"
有没有一种方法可以让我忽略图像标签内的文本,同时仍然包裹所有其他文本并保持大写?
这与C# Regex replace in string only outside tags 不同,因为<p>
和<span>
标记中有很多我需要替换的文本。我只需要忽略<img>
和<a>
标签内的文本。
【问题讨论】:
【参考方案1】:你可以使用
var regex = new Regex($@"(<(?:img|a)(?:\s[^>]*>)?)|Regex.Escape(searchTerm)", RegexOptions.IgnoreCase);
var highlightedText = regex.Replace(textToFormat, m =>
m.Groups[1].Success ? m.Groups[1].Value : $"<span class='highlight'>m.Value</span>");
# => This is some <span class='highlight'>Text</span>: <a href='/text.html'><img src='/images/text.png'/></a>
见C# demo online
正则表达式是
(<(?:img|a)(?:\s[^>]*>)?)|text
见its demo。它匹配:
(<(?:img|a)(?:\s[^>]*>)?)
- 捕获组 1:<
、img
或 a
,然后是可选的空格序列,然后是除 >
之外的任何 0+ 字符,然后是 >
字符
|
- 或
text
- 一些字符串。
如果 Group 1 匹配,则替换为 Group 1 值(即恢复 <a>
或 <img>
标签),否则用 span 标签包装匹配项。
不要忘记转义您的searchTerm
,以确保它在包含特殊字符时不会引起问题。要搜索整个单词,请考虑使用明确的单词边界,(?<!\w)
和 (?!\w)
、new Regex($@"(<(?:img|a)(?:\s[^>]*>)?)|(?<!\w)Regex.Escape(searchTerm)(?!\w)", RegexOptions.IgnoreCase)
。
【讨论】:
以上是关于MatchEvaluator 对大小写不敏感的文本换行,除非文本位于图像 HTML 标记内(但不忽略所有标记)的主要内容,如果未能解决你的问题,请参考以下文章