使用html敏捷包

时间:2016-10-31 19:51:13

标签: html vb.net winforms xpath html-table

我使用以下代码将html文件中的html表解析为数据集:

Public Function GetDataSet(html As String) As DataSet
Dim ds As DataSet = New DataSet
Dim htmldoc As New HtmlAgilityPack.HtmlDocument
htmldoc.LoadHtml(html)
Dim tables = htmldoc.DocumentNode.SelectNodes("//table/tr") _
                                 .GroupBy(Function(x) x.ParentNode)
For i As Integer = 0 To tables.Count - 1
    Dim rows = tables(i).ToList()
    ds.Tables.Add(String.Format("Table {0}", i))
    Dim headers = rows(0).Elements("th").Select(Function(x) x.InnerText.Trim).ToList()
    For Each Hr In headers
        ds.Tables(i).Columns.Add(Hr)
    Next
    For j As Integer = 1 To rows.Count - 1
        Dim row = rows(j)
        Dim dr = row.Elements("td").Select(Function(x) x.InnerText.Trim).ToArray()
        ds.Tables(i).Rows.Add(dr)
    Next
Next
Return ds
End Function

它工作正常。但是当<Table>标记之前的<tr>标记内放置标记时,表格未被解析

简单示例:

<html> <head><title>Test</title></head> <body> <div>Contents:</div> <table> <tr> <th>Column1</th> <th>Column2</th> </tr> <tr> <td>1</td> <td>11</td> </tr> <tr> <td>2</td> <td>22</td> </tr> </table> <table> <tbody> <tr> <th>Column1</th> <th>Column2</th> <th>Column3</th> </tr> <tr> <td>a</td> <td>aa</td> <td>aaa</td> </tr> <tr> <td>b</td> <td>bb</td> <td>bbb</td> </tr> </tbody> </table> <table> <div> <tr> <th>Column1</th> <th>Column2</th> <th>Column3</th> </tr> <tr> <td>a</td> <td>aa</td> <td>aaa</td> </tr> <tr> <td>b</td> <td>bb</td> <td>bbb</td> </tr> </div> </table> </body> </html>

在此示例中,仅解析第一个表。

我的问题是如何忽略以下代码行中<Table>代码和<tr>代码之间的任何代码:

Dim tables = htmldoc.DocumentNode.SelectNodes("//table/tr") _
                             .GroupBy(Function(x) x.ParentNode)

将解析所有表格。

1 个答案:

答案 0 :(得分:2)

您可以使用//从所有后代中进行选择:

Dim rows = htmldoc.DocumentNode.SelectNodes("//table//tr");

同样根据您的要求,最好根据第一个祖先table对结果进行分组,因为tr的父级可能是tbodythead并且您需要对表中的行进行分组:

Dim tables = htmldoc.DocumentNode.SelectNodes("//table//tr") _
                    .GroupBy(Function(x) x.Ancestors("table").First())