LINQ и HTML Agility Pack заполняют анализируемые данные таблицы HTML в виде данных

datatable html-agility-pack linq vb.net

Вопрос

Я использую следующий запрос для анализа данных таблицы html.

Dim q = From table In htmldoc.DocumentNode.SelectNodes("//table[@class='Seller']").Cast(Of HtmlNode)()
                    From row In table.SelectNodes("tr").Cast(Of HtmlNode)()
                    From header In row.SelectNodes("th").Cast(Of HtmlNode)()
                    From cell In row.SelectNodes("td").Cast(Of HtmlNode)()
               Select New With {Key .Table = table.Id, Key .CellText = cell.InnerText, Key .headerText = header.InnerText}

Как я могу использовать для каждой петли, как это сделать, чтобы заполнить это в datatable?

Сначала я хотел бы создавать столбцы с использованием данных заголовка, а затем использовать вложенные для каждого цикла для заполнения данных ячейки в таблице, но я не уверен, как это сделать, а также любые предлагаемые изменения в вышеуказанном запросе LINQ?

Примечание . На странице html всегда содержится только одна таблица.

Принятый ответ

Учитывая следующий html

Dim t = <table class='Seller' id='MyTable'>
            <tr>
                <th>FooColumn</th>
                <td>Foo</td>
                <td>Another Foo</td>
            </tr>
            <tr>
                <th>BarColumn</th>
                <td>Bar</td>
                <td>Another Bar</td>
            </tr>
            <tr>
                <th>ThirdColumn</th>
                <td>Third</td>
                <td>Another Third</td>
            </tr>
        </table>

Dim htmldoc = New HtmlAgilityPack.HtmlDocument()
htmldoc.LoadHtml(t.ToString())

и ваш запрос

Dim q = From table In htmldoc.DocumentNode.SelectNodes("//table[@class='Seller']")
            From row In table.SelectNodes("tr")
                From header In row.SelectNodes("th")
                From cell In row.SelectNodes("td")
        Select New With {.Table = table.Id, .CellText = cell.InnerText, .headerText = header.InnerText}

вы можете использовать GroupBy или ToLookup для группировки объектов по столбцам:

Dim grouped = q.ToLookup(Function(a) a.headerText)

и используйте эту группировку для создания DataTable с соответствующими DataColumn s:

Dim dt = new DataTable()

For Each h in grouped.Select(Function(g) g.Key)
    dt.Columns.Add(h)
Next

Теперь для заполнения DataTable вам нужно «повернуть» группировку, поскольку каждая группа содержит данные для одного столбца, но нам нужны данные для каждой строки. Давайте используем небольшой вспомогательный метод

Function Rotate(Of T, TR)(source As IEnumerable(Of IEnumerable(Of T)), 
                          selector As Func(Of IEnumerable(Of T), IEnumerable(Of TR))) As IEnumerable(Of IEnumerable(Of TR))

    Dim result = new List(Of IEnumerable(Of TR))
    Dim enums = source.Select(Function(e) e.GetEnumerator()).ToArray()
    While enums.All(Function(e) e.MoveNext())
        result.Add(selector(enums.Select(Function(e) e.Current)).ToArray())
    End While

    Return result
End Function

для заполнения DataTable .

For Each rrow in Rotate(grouped, Function(row) row.Select(Function(e) e.CellText))
    dt.Rows.Add(rrow.ToArray())
Next 

И теперь DataTable будет выглядеть так:

введите описание изображения здесь



Related

Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow