2008-11-13 40 views
8

Trước khi có ai hỏi, tôi không làm bất kỳ loại màn hình nào.Regex - Tìm nội dung của div theo id với div lồng nhau

Tôi đang cố gắng phân tích cú pháp chuỗi html để tìm một div có id nhất định. Tôi không thể cho cuộc sống của tôi có được điều này để làm việc. Biểu thức sau đây hoạt động trong một cá thể, nhưng không hoạt động trong một thể hiện khác. Tôi không chắc chắn nếu nó đã làm với các yếu tố phụ trong html hay không.

<div\s*?id=(\""|&quot;|&#34;)content(\""|&quot;|&#34;).*?>\s*?(?>(?! <div\s*?> | </div>) | <div\s*?>(?<DEPTH>) | </div>(?<-DEPTH>) | .?)*(?(DEPTH)(?!))</div> 

Đó là tìm div đầu tiên có id đúng, nhưng sau đó đóng tại div đóng đầu tiên chứ không phải div liên quan.

<div id="firstdiv">begining content<div id="content">some other stuff 
    <div id="otherdiv">other stuff here</div> 
    more stuff 
    </div> 
</div> 

này nên mang lại

<div id="content">some other stuff 
    <div id="otherdiv">other stuff here</div> 
    more stuff 
</div> 

, nhưng đối với một số lý do, nó không phải là. Nó mang lại:

<div id="content">some other stuff 
     <div id="otherdiv">other stuff here</div> 

Có ai có biểu hiện dễ dàng hơn để xử lý việc này không?

Để làm rõ, đây là trong .NET và tôi đang sử dụng từ khóa DEPTH. Bạn có thể tìm thêm chi tiết here.

+0

upvoted - đây là câu hỏi tuyệt vời cho việc lập trình viên mới giới hạn những biểu thức thông thường có thể thực hiện. – Cybis

+0

Có lẽ không phải trong tinh khiết Reg. Exp. nhưng nó chắc chắn có thể được thực hiện với .net. Xem câu trả lời của tôi. – pro3carp3

Trả lời

5

Trong .NET, bạn có thể làm điều này:

(?<text> 
(<div\s*?id=(\"|&quot;|&\#34;)content(\"|&quot;|&\#34;).*?>) 

    (?> 
     .*?</div> 
    | 
     .*?<div (?>depth) 
    | 
     .*?</div> (?>-depth) 
)*) 
    (?(depth)(?!)) 
.*?</div> 

Bạn phải sử dụng tùy chọn singleline. Dưới đây là ví dụ sử dụng bảng điều khiển:

using System; 
using System.Text.RegularExpressions; 

namespace Temp 
{ 
    class Program 
    { 
     static void Main() 
     { 
      string s = @" 
<div id=""firstdiv"">begining content<div id=""content"">some other stuff 
    <div id=""otherdiv"">other stuff here</div> 
    more stuff 
    </div> 
</div>"; 
      Regex r = new Regex(@"(?<text>(<div\s*?id=(\""|&quot;|&\#34;)" 
       + @"content(\""|&quot;|&\#34;).*?>)(?>.*?</div>|.*?<div " 
       + @"(?>depth)|.*?</div> (?>-depth))*)(?(depth)(?!)).*?</div>", 
       RegexOptions.Singleline); 
      Console.WriteLine("HTML:\n"); 
      Console.WriteLine(s); 
      Match m = r.Match(s); 
      if (m.Success) 
      { 
       Console.WriteLine("\nCaptured text:\n"); 
       Console.WriteLine(m.Groups[4]); 

      } 
      Console.ReadLine(); 
     } 
    } 
} 
+0

Để nó cho Microsoft để thay đổi định nghĩa của ngôn ngữ thông thường. – Cybis

5

Bạn có yêu cầu cụm từ thông dụng có thể theo dõi số lượng thẻ DIV được lồng trong thẻ DIV không? Tôi e rằng điều đó là không thể với các biểu thức thông thường.

Bạn có thể sử dụng biểu thức chính quy để nhận chỉ mục của thẻ DIV đầu tiên, sau đó lặp qua các ký tự trong chuỗi, bắt đầu từ chỉ mục đó và giữ số lượng thẻ div mở. Khi bạn gặp phải thẻ div đóng và số đếm là 0, thì bạn có chỉ mục bắt đầu và kết thúc trong chuỗi chứa chuỗi con bạn muốn.

+0

Tôi hiểu rằng có những phần mở rộng đệ quy cho phép điều này, nhưng nó không thể được thực hiện trong regex thuần túy. –

0

Ngôn ngữ lập trình nào? Nếu đó là .Net và bạn chắc chắn rằng html được định dạng tốt, bạn có thể tải nó vào một đối tượng XmlDocument hoặc XDocument và thực hiện truy vấn xpath trên nó.

+0

... và có thể phân tích cú pháp nhanh hơn biểu thức chính quy đó. –

2

Cybis nói sự thật. Loại công cụ này rơi vào các ngôn ngữ không có bối cảnh, vốn mạnh hơn các ngôn ngữ thông thường (loại thứ được bao phủ bởi các cụm từ thông dụng). Có rất nhiều lý thuyết khoa học máy tính có liên quan, nhưng hãy để phần còn lại nói rằng bất kỳ ngôn ngữ nào đáng giá muối của nó sẽ có một thư viện cho loại công cụ này được viết mà có lẽ bạn nên sử dụng.

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