2013-02-19 36 views
5

Tôi có một bảng như thế nàyHtml Agility Pack lặp qua hàng bảng và cột

<table border="0" cellpadding="0" cellspacing="0" id="table2"> 
    <tr> 
     <th>Name 
     </th> 
     <th>Age 
     </th> 
    </tr> 
     <tr> 
     <td>Mario 
     </td> 
     <th>Age: 78 
     </td> 
    </tr> 
      <tr> 
     <td>Jane 
     </td> 
     <td>Age: 67 
     </td> 
    </tr> 
      <tr> 
     <td>James 
     </td> 
     <th>Age: 92 
     </td> 
    </tr> 
</table> 

Và muốn sử dụng HTML Agility Pack để phân tích nó. Tôi đã thử mã này không có sẵn:

foreach (HtmlNode row in doc.DocumentNode.SelectNodes("//table[@id='table2']//tr")) 
{ 
    foreach (HtmlNode col in row.SelectNodes("//td")) 
    { 
     Response.Write(col.InnerText); 
    } 
} 

Tôi đang làm gì sai?

+2

bạn có thể mô tả những gì không hoạt động không? – GolfWolf

+0

Tôi nhận được một vòng lặp vô hạn – mpora

+1

Nó hoạt động cho tôi (tốt, không chính xác, tôi nhận được tên Mario/Jane/James lặp lại 4 lần). Lưu ý rằng '// td' _không chọn từ nút hiện tại chỉ_ (như bạn có thể mong đợi) _but từ DocumentNode_. Bạn đang sử dụng phiên bản HtmlAgilityPack nào? – agentnega

Trả lời

1

tôi phải cung cấp đầy đủ các xpath. Tôi có đầy đủ các xpath bằng cách sử dụng Firebug từ một gợi ý bởi @Coda (https://stackoverflow.com/a/3104048/1238850) và tôi đã kết thúc với mã này:

foreach (HtmlNode row in doc.DocumentNode.SelectNodes("/html/body/table/tbody/tr/td/table[@id='table2']/tbody/tr")) 
{ 
    HtmlNodeCollection cells = row.SelectNodes("td"); 
    for (int i = 0; i < cells.Count; ++i) 
    { 
     if (i == 0) 
     { Response.Write("Person Name : " + cells[i].InnerText + "<br>"); } 
     else { 
      Response.Write("Other attributes are: " + cells[i].InnerText + "<br>"); 
     } 
    } 
} 

Tôi chắc chắn nó có thể được viết theo cách tốt hơn thế này nhưng nó đang làm việc cho tôi ngay bây giờ .

2

Tại sao bạn không chỉ chọn trực tiếp số td?

foreach (HtmlNode col in doc.DocumentNode.SelectNodes("//table[@id='table2']//tr//td")) 
    Response.Write(col.InnerText); 

Cách khác, nếu bạn thực sự cần tr s riêng cho một số chế biến khác, thả // và làm:

foreach (HtmlNode row in doc.DocumentNode.SelectNodes("//table[@id='table2']//tr")) 
    foreach (HtmlNode col in row.SelectNodes("td")) 
     Response.Write(col.InnerText); 

Tất nhiên điều đó sẽ chỉ làm việc nếu td s là con trực tiếp của tr s nhưng phải là đúng không?


EDIT:

var cols = doc.DocumentNode.SelectNodes("//table[@id='table2']//tr//td"); 
for (int ii = 0; ii < cols.Count; ii=ii+2) 
{ 
    string name = cols[ii].InnerText.Trim(); 
    int age = int.Parse(cols[ii+1].InnerText.Split(' ')[1]); 
} 

Có lẽ một cách ấn tượng hơn để làm điều này với LINQ.

+0

Có Tôi muốn sử dụng từng cột để xử lý vì bạn có thể thấy cột thứ hai là một hỗn hợp của các số và văn bản, tôi muốn trích xuất con số. Trang chỉ là vòng tròn và không có kết quả sau khi tôi đã thử mã này. – mpora

3

tôi đã chạy mã và nó sẽ hiển thị chỉ Tên, đó là chính xác, bởi vì Cổ được định nghĩa sử dụng HTML không hợp lệ: <th></td> (có thể là một lỗi đánh máy).

Bằng cách này, các mã có thể được đơn giản hóa để chỉ có một vòng lặp:

foreach (var cell in doc.DocumentNode.SelectNodes("//table[@id='table2']/tr/td")) 
{ 
    Response.Write(cell.InnerText); 
} 

Dưới đây là đoạn code tôi sử dụng để kiểm tra: http://pastebin.com/euzhUAAh

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