MatchEvaluator для переноса текста без учета регистра, ЗА ИСКЛЮЧЕНИЕМ текста в теге image HTML (но НЕ игнорирует ВСЕ теги) - PullRequest
0 голосов
/ 03 августа 2020

У меня есть HTML основной текст, созданный в моей CMS. У меня есть собственный метод выделения условий поиска в тексте, чтобы, когда пользователь переходит на страницу из результатов поиска, выделяются все вхождения этого условия поиска. У меня эта настройка нечувствительна к регистру, поэтому соответствующий текст будет выделен независимо от заглавных букв, а результат сохранит исходное использование заглавных букв:

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 заменить в строке только за пределами тегов , потому что в тегах <p> и <span> есть много текста, который мне НЕОБХОДИМО заменить. Мне нужно только игнорировать текст внутри тегов <img> и <a>.

1 Ответ

0 голосов
/ 03 августа 2020

Вы можете использовать

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# онлайн-демо

Регулярное выражение

(<(?:img|a)(?:\s[^>]*>)?)|text

См. его демо . Он соответствует:

  • (<(?:img|a)(?:\s[^>]*>)?) - Группа захвата 1: <, img или a, затем необязательная последовательность пробелов, а затем любые символы 0+, кроме > а затем > char
  • | - или
  • text - некоторая строка.

Если группа 1 совпадает, замените ее на Group 1 (т.е. восстановить теги <a> или <img>), иначе обернуть совпадение тегом span.

Не забудьте экранировать свой searchTerm, чтобы убедиться, что это не вызовет проблем, если он содержит специальные символы. Для поиска всего слова рассмотрите возможность использования однозначных границ слов, (?<!\w) и (?!\w), new Regex($@"(<(?:img|a)(?:\s[^>]*>)?)|(?<!\w){Regex.Escape(searchTerm)}(?!\w)", RegexOptions.IgnoreCase).

...