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}

어떻게 이것을 각 루프에 사용하여 이것을 데이터 테이블에 채울 수 있습니까?

먼저 열 머리글 데이터를 사용하여 다음 테이블의 셀 데이터를 채우기 위해 각 루프에 대한 중첩 된 사용하지만 위의 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)

이 그룹을 사용하여 적절한 DataColumn 을 사용하여 DataTable 을 만듭니다.

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 은 다음과 같습니다.

여기에 이미지 설명을 입력하십시오.




아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.