J'utilise la requête suivante pour analyser les données de table 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}
Comment puis-je utiliser pour chaque boucle, comment peut-on l'intégrer dans un datatable?
Je voudrais d'abord créer des colonnes en utilisant les données d'en-tête, puis utiliser un imbriqué pour chaque boucle afin de remplir les données de cellules dans la table, mais je ne sais pas comment procéder, également des modifications suggérées pour la requête LINQ ci-dessus?
Remarque : La page html contient toujours une seule table.
Étant donné le html
suivant
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())
et votre requête
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}
vous pouvez utiliser GroupBy
ou ToLookup
pour regrouper les objets par colonnes:
Dim grouped = q.ToLookup(Function(a) a.headerText)
et utilisez ce groupe pour créer un DataTable
avec les DataColumn
appropriés:
Dim dt = new DataTable()
For Each h in grouped.Select(Function(g) g.Key)
dt.Columns.Add(h)
Next
Maintenant, pour remplir le DataTable
, vous devez "faire pivoter" le groupe, car chaque groupe contient les données d'une colonne, mais nous voulons les données de chaque ligne. Utilisons une petite méthode d'assistance
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
pour remplir le DataTable
.
For Each rrow in Rotate(grouped, Function(row) row.Select(Function(e) e.CellText))
dt.Rows.Add(rrow.ToArray())
Next
Et maintenant, le DataTable
ressemblera à ceci: