【问题标题】:Looping the table in c# given all the values..?给定所有值,在 c# 中循环表格..?
【发布时间】:2013-06-12 11:57:48
【问题描述】:

我有这样的桌子

<table>
  <tbody>
    <tr>
       <td>Header1</td>
       <td>Header2</td>
       <td>Header3</td>
       <td>Header4</td>
    </tr>
    <tr>
       <td>1</td>
       <td>2</td>
       <td>3</td>
       <td>4</td>
    </tr>
    <tr>
       <td>11</td>
       <td>22</td>
       <td>33</td>
       <td>44</td>
    </tr>

  </tbody>
</table>

我的代码是

var headersList = xmlDoc.XPathSelectElements("//table//tbody//tr").ToList();

但是 headerlist 给出了所有的 td 值 :-(

现在我想知道如何循环这个表。我的预期结果如下:

第一个循环的预期结果

Header1 = 1,
Header2 = 2,
Header3 = 3,
Header4 = 4,

第二次循环预期结果:

Header1 = 11
Header2 = 22
Header3 = 33
Header4 = 44

任何帮助将不胜感激

【问题讨论】:

    标签: c# xml linq-to-xml html-agility-pack xmldocument


    【解决方案1】:

    由于您无法区分标题和正文(缺少theadtbody),您需要以编程方式确定元素的数量。

    var data = @"<table>
      <tbody>
        <tr>
           <td>Header1</td>
           <td>Header2</td>
           <td>Header3</td>
           <td>Header4</td>
        </tr>
        <tr>
           <td>1</td>
           <td>2</td>
           <td>3</td>
           <td>4</td>
        </tr>
        <tr>
           <td>11</td>
           <td>22</td>
           <td>33</td>
           <td>44</td>
        </tr>
    
      </tbody>
    </table>";
    
    var xDoc = XDocument.Parse(data);
    var headerElements = xDoc.XPathSelectElements("//table//tbody//tr");
    int headerCount = headerElements.First().Descendants().Count();
    var nodes = headerElements.SelectMany(x => x.Descendants())
                              .Select(x => x.Value)
                              .ToList();
    var head = nodes.Take(headerCount).ToList();
    var body = nodes.Skip(headerCount).ToList();
    
    var pairs = new List<Tuple<string,string>>();
    
    for(var i = 0; i < body.Count; i += headerCount)
    {
        for(int j = 0; j < head.Count; j++)
        {
            pairs.Add(Tuple.Create(head[j], body[i+j]));
        }
    }
    
    foreach(var pair in pairs)
    {
        Console.WriteLine("{0} = {1}", pair.Item1, pair.Item2);
    }
    

    【讨论】:

    • 我会试试这个并告诉你
    • 算法是通用的,但如果每行的元素数量不均匀,则需要修改 for 循环来解决这个问题。
    • 是的,我做到了。只是以不同的方式采取了头部和循环。显然我不需要正文和配对列表。我以不同的方式编写了正文。总之非常感谢分享这段代码,它非常有用。
    【解决方案2】:

    使用HtmlAgilityPack(可从 NuGet 获得)解析 HTML 文档。以下是向控制台显示表格数据的示例:

    var doc = new HtmlDocument();
    doc.Load(path_to_html);
    var rows = 
          doc.DocumentNode.SelectNodes("//table/tbody/tr")
             .Select(tr => tr.SelectNodes("td").Select(td => td.InnerHtml).ToList())
             .ToList();
    

    输出:

    var headers = rows[0];
    
    // skip first row which contains headers
    foreach (var row in rows.Skip(1))
    {
        for (int i = 0; i < row.Count; i++)
            if (headers.Count > i) // you can remove this check if data is valid
                Console.WriteLine("{0} = {1}", headers[i], row[i]);
    }
    

    结果:

    Header1 = 1
    Header2 = 2
    Header3 = 3
    Header4 = 4
    
    Header1 = 11
    Header2 = 22
    Header3 = 33
    Header4 = 44
    

    如果你需要为列定义标题,那么我建议你使用thead标签:

    <table>
      <thead>
        <tr>
           <td>Header1</td>
           <td>Header2</td>
           <td>Header3</td>
           <td>Header4</td>
        </tr>
      </thead>
      <tbody>
        <tr>
           <td>1</td>
           <td>2</td>
           <td>3</td>
           <td>4</td>
        </tr>
        <tr>
           <td>11</td>
           <td>22</td>
           <td>33</td>
           <td>44</td>
        </tr>
      </tbody>
    </table>
    

    在这种情况下,解析和输出将如下所示

    var headers = doc.DocumentNode.SelectNodes("//table/thead/tr/td")
                     .Select(td => td.InnerHtml).ToList();
    var rows = 
          doc.DocumentNode.SelectNodes("//table/tbody/tr")
             .Select(tr => tr.SelectNodes("td").Select(td => td.InnerHtml).ToList())
             .ToList();
    
    foreach (var row in rows)
    {
        for(int i = 0; i < row.Count; i++)
            Console.WriteLine("{0} = {1}", headers[i], row[i]);
    }
    

    【讨论】:

    • 使用thead非常简单,但我的文件没有thead。 :-( 没有 Thead 我不能得到我的输出?
    • @user1990395 你可以使用相同的方法,但迭代第一行而不是标题集合。查看更新的答案
    • 我正在尝试,一旦成功就会通知您
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 2021-08-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多