2008-10-07 2 views
5

Я пишу код для страницы результатов поиска, которая должна выделять поисковые запросы. Эти термины встречаются внутри ячеек таблицы (приложение выполняет итерацию через ячейки строки GridView), и эти ячейки таблицы могут иметь HTML.Какое регулярное выражение будет соответствовать тексту, исключая то, что находится в тегах 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 «класс», который, оказывается, там! Если вы ищете «Fred», это должно быть выделено.

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

+1

Если кто-то искал Фреда в вашем примере, должен ли он быть выделен? – 2008-10-07 18:38:35

+0

Да. Спасибо за вопрос. Хороший вопрос. Я отредактирую вопрос. – Chris 2008-10-07 18:43:17

ответ

11

Это регулярное выражение должно выполнять эту работу: (?<!<[^>]*)(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

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

0

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

+0

Чтобы соответствовать «классу», как я описал в моем примере, где слово «класс» входит в ваше регулярное выражение? Я не понимаю, как использовать ваше регулярное выражение. По своей сути он, похоже, соответствует каждой позиции char во всей фразе. – Chris 2008-10-08 07:14:45

+0

Регулярное выражение "(?! <.+?>)" является лишь негативным взглядом; он говорит: «С этой позиции мы не смотрим на то, что выглядит неопределенно, как тег». Он ничего не будет соответствовать, и он не предотвратит совпадение чего-либо, внутри тега или вне. – 2008-10-09 13:36:59

0

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

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

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

Смежные вопросы