Какое регулярное выражение будет соответствовать тексту, исключая то, что находится внутри тегов HTML? - PullRequest
5 голосов
/ 07 октября 2008

Я пишу код для страницы результатов поиска, которая должна выделять условия поиска. Термины встречаются в ячейках таблицы (приложение выполняет итерацию в ячейках строк GridView), и эти ячейки таблицы могут иметь HTML.

В настоящее время мой код выглядит следующим образом (соответствующие фрагменты показаны ниже):

const string highlightPattern = @"<span class=""Highlight"">$0</span>";
DataBoundLiteralControl litCustomerComments = (DataBoundLiteralControl)e.Row.Cells[CUSTOMERCOMMENTS_COLUMN].Controls[0];

// Turn "term1 term2" into "(term1|term2)"
string spaceDelimited = txtTextFilter.Text.Trim();
string pipeDelimited = string.Join("|", spaceDelimited.Split(new[] {" "}, StringSplitOptions.RemoveEmptyEntries));
string searchPattern = "(" + pipeDelimited + ")";

// Highlight search terms in Customer - Comments column
e.Row.Cells[CUSTOMERCOMMENTS_COLUMN].Text = Regex.Replace(litCustomerComments.Text, searchPattern, highlightPattern, RegexOptions.IgnoreCase);

Удивительно, но это работает. НО, иногда текст, с которым я сопоставляю, - это HTML, который выглядит так:

<span class="CustomerName">Fred</span> was a classy individual.

И если вы ищете «класс», я хочу, чтобы код выделения выделил «класс» в «классном», но, конечно, не в HTML-атрибуте «класс», который там есть! Если вы ищете «Фред», это должно быть выделено.

Так что же такое хорошее регулярное выражение, которое гарантирует, что совпадения будут происходить только вне HTML-тегов? Это не должно быть супер хардкор. Я думаю, просто убедившись, что совпадение не между <и>, будет работать нормально.

Ответы [ 4 ]

11 голосов
/ 08 октября 2008

Это регулярное выражение должно выполнять работу: (?<!<[^>]*)(regex you want to check: Fred|span) Он проверяет, что невозможно сопоставить регулярное выражение <[^>]* в обратном направлении, начиная с соответствующей строки.

Модифицированный код ниже:

const string notInsideBracketsRegex = @"(?<!<[^>]*)";
const string highlightPattern = @"<span class=""Highlight"">$0</span>";
DataBoundLiteralControl litCustomerComments = (DataBoundLiteralControl)e.Row.Cells[CUSTOMERCOMMENTS_COLUMN].Controls[0];

// Turn "term1 term2" into "(term1|term2)"
string spaceDelimited = txtTextFilter.Text.Trim();
string pipeDelimited = string.Join("|", spaceDelimited.Split(new[] {" "}, StringSplitOptions.RemoveEmptyEntries));
string searchPattern = "(" + pipeDelimited + ")";
searchPattern = notInsideBracketsRegex + searchPattern;

// Highlight search terms in Customer - Comments column
e.Row.Cells[CUSTOMERCOMMENTS_COLUMN].Text = Regex.Replace(litCustomerComments.Text, searchPattern, highlightPattern, RegexOptions.IgnoreCase);
2 голосов
/ 07 октября 2008

Вы можете использовать регулярные выражения с балансировочными группами и обратными ссылками, но я настоятельно рекомендую использовать здесь парсер .

0 голосов
/ 08 октября 2008

Написание регулярного выражения, которое может обрабатывать секции CDATA, будет трудным. Вы больше не можете предполагать, что> закрывает тег.

Например, "<span class="CustomerName>Fred.</span> is a good customer (<![CDATA[ >10000$ ]]> )"

Решение - (как отмечалось ранее) парсер. Они намного лучше справляются с тем беспорядком, который вы найдете в CDATA. Обратную проверку madgnome нельзя использовать для поиска начального <![CDATA из ]]>, так как раздел CDATA может содержать литерал <![CDATA.

0 голосов
/ 08 октября 2008

Хм, я не программист на C #, поэтому я не знаю, какое это регулярное выражение использует, но (?! <. +?>) Должно игнорировать что-либо внутри тегов Это заставит вас использовать & # 60 & # 62 в вашем HTML-коде, но вы все равно должны это делать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...