2008-10-07 23 views
5

Tôi đang viết mã cho trang kết quả tìm kiếm cần làm nổi bật cụm từ tìm kiếm. Các điều khoản xảy ra trong các ô bảng (ứng dụng đang lặp qua các ô Row GridView) và các ô bảng này có thể có HTML.Regex nào sẽ khớp với văn bản trừ thứ nằm trong các thẻ HTML?

Hiện nay, mã của tôi trông như thế này (hunks có liên quan trình bày dưới đây):

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); 

Thật ngạc nhiên nó hoạt động. NHƯNG, đôi khi các văn bản tôi phù hợp trên là HTML mà trông như thế này:

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

Và nếu bạn tìm kiếm "class" Tôi muốn mã nổi bật để bọc các "lớp học" trong "sang trọng" nhưng tất nhiên không thuộc tính HTML "class" xảy ra ở đó! Nếu bạn tìm kiếm "Fred", cần được đánh dấu.

Vậy một regex tốt sẽ đảm bảo các kết quả phù hợp chỉ xảy ra ở đâu bên ngoài các thẻ html? Nó không phải là siêu hardcore. Đơn giản chỉ cần chắc chắn rằng trận đấu không phải là giữa < và> sẽ làm việc tốt, tôi nghĩ.

+1

Nếu ai đó tìm kiếm Fred trong ví dụ của bạn, nếu nó được đánh dấu? –

+0

Có. Cảm ơn bạn đã hỏi thăm. Câu hỏi hay. Tôi sẽ chỉnh sửa câu hỏi. – Chris

Trả lời

11

Regex này nên thực hiện công việc: (?<!<[^>]*)(regex you want to check: Fred|span) Kiểm tra rằng không thể đối sánh regex <[^>]* quay lại bắt đầu từ chuỗi phù hợp.

Modified mã bên dưới:

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); 
+0

Tìm thấy thông qua Google, đã giúp đỡ rất nhiều, cảm ơn! :) – Teekin

+0

Cảm ơn bạn rất nhiều! Bạn đã cứu ngày của tôi! :) – podeig

+2

Đây là một đoạn mã tuyệt vời. Bạn xứng đáng nhận được nhiều phiếu bầu hơn bạn nhận được. Cảm ơn rất nhiều. – draconis

2

Bạn có thể sử dụng regex với các nhóm cân bằng và backreferences, nhưng tôi khuyên bạn nên sử dụng parser tại đây.

0

Hmm, tôi không phải là lập trình viên C# vì vậy tôi không biết hương vị của regex mà nó sử dụng nhưng (?! <. +?>) Nên bỏ qua mọi thứ bên trong thẻ. Nó sẽ buộc bạn phải sử dụng & # 60 & # 62 trong mã HTML của mình, nhưng bạn vẫn nên làm điều đó.

+0

Để khớp với "lớp" như tôi đã mô tả trong ví dụ của tôi, từ "lớp" sẽ ở đâu trong regex của bạn? Tôi không hiểu cách sử dụng regex của bạn. Ngày của riêng nó, nó xuất hiện để phù hợp với mọi vị trí char trong toàn bộ cụm từ. – Chris

+0

Các regex "(?! <.+?>)" chỉ là một lookahead tiêu cực; nó nói, "từ vị trí này, chúng tôi không nhìn vào một cái gì đó trông mơ hồ như một thẻ." Nó sẽ không phù hợp với bất cứ điều gì, cũng như nó sẽ không phù hợp với bất cứ điều gì, bên trong một thẻ hoặc ra ngoài. –

0

Viết một regex có thể xử lý các phần CDATA sẽ là khó khăn. Bạn có thể không còn asssume rằng> đóng một thẻ.

Ví dụ: "<span class="CustomerName>Fred.</span> is a good customer (<![CDATA[ >10000$ ]]>)"

Giải pháp là (như đã nói trước đó) một trình phân tích cú pháp. Họ đang tốt hơn nhiều trong việc đối phó với các loại mess bạn tìm thấy trong một CDATA. Không thể sử dụng séc ngược của madgnome để tìm số bắt đầu <![CDATA từ một số ]]>, dưới dạng một phần CDATA có thể bao gồm chữ số <![CDATA.

+0

Điểm tốt, tôi không nghĩ về điều đó. –

+0

Tôi biết giải pháp không hoàn hảo, nhưng cân nhắc tất cả những thăng trầm, đó là giải pháp tốt nhất mà tôi đã tìm thấy từ trước tới giờ. – Chris

Các vấn đề liên quan