LINQ und HTML Agility Pack füllen die analysierten HTML-Tabellendaten in eine Datentabelle

datatable html-agility-pack linq vb.net

Frage

Ich verwende die folgende Abfrage, um HTML-Tabellendaten zu analysieren.

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}

Wie kann ich für jede Schleife verwenden, wie kann man diese in eine Datentabelle füllen?

Ich würde zuerst Spalten mit den Kopfdaten erstellen, dann verwenden Sie eine verschachtelte für jede Schleife, um die Zellendaten in der Tabelle zu füllen, aber ich bin mir nicht sicher, wie, auch irgendwelche vorgeschlagenen Änderungen in der obigen LINQ-Abfrage?

Hinweis : Die HTML-Seite enthält immer nur eine Tabelle.

Akzeptierte Antwort

Angesichts der folgenden 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())

und deine Anfrage

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}

Sie können GroupBy oder ToLookup , um die Objekte nach Spalten zu gruppieren:

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

und verwenden Sie diese Gruppierung, um eine DataTable mit den entsprechenden DataColumn zu erstellen:

Dim dt = new DataTable()

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

DataTable die DataTable zu füllen, müssen Sie nun die Gruppierung "rotieren", da jede Gruppe die Daten für eine Spalte enthält, aber wir wollen die Daten für jede Zeile. Lassen Sie uns eine kleine Hilfsmethode verwenden

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

um die DataTable zu füllen.

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

Und jetzt sieht die DataTable so aus:

Bildbeschreibung hier eingeben



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum