Html Agility Pack循环遍历表行和列

时间:2013-02-19 22:25:03

标签: c# .net html-agility-pack

我有一张这样的表

<table border="0" cellpadding="0" cellspacing="0" id="table2">
    <tr>
        <th>Name
        </th>
        <th>Age
        </th>
    </tr>
        <tr>
        <td>Mario
        </td>
        <th>Age: 78
        </td>
    </tr>
            <tr>
        <td>Jane
        </td>
        <td>Age: 67
        </td>
    </tr>
            <tr>
        <td>James
        </td>
        <th>Age: 92
        </td>
    </tr>
</table>

并希望使用HTML Agility Pack来解析它。我试过这段代码无济于事:

foreach (HtmlNode row in doc.DocumentNode.SelectNodes("//table[@id='table2']//tr"))
{
    foreach (HtmlNode col in row.SelectNodes("//td"))
    { 
        Response.Write(col.InnerText); 
    }
}

我做错了什么?

4 个答案:

答案 0 :(得分:4)

我运行代码并且只显示名称,这是正确的,因为 Ages 是使用无效的HTML定义的:<th></td>(可能一个错字)。

顺便说一下,代码可以简化为只有一个循环:

foreach (var cell in doc.DocumentNode.SelectNodes("//table[@id='table2']/tr/td"))
{
    Response.Write(cell.InnerText);
}

以下是我用来测试的代码:http://pastebin.com/euzhUAAh

答案 1 :(得分:3)

为什么不直接选择td

foreach (HtmlNode col in doc.DocumentNode.SelectNodes("//table[@id='table2']//tr//td"))
    Response.Write(col.InnerText);

或者,如果您确实需要tr分别进行其他处理,请删除//并执行:

foreach (HtmlNode row in doc.DocumentNode.SelectNodes("//table[@id='table2']//tr"))
    foreach (HtmlNode col in row.SelectNodes("td"))
        Response.Write(col.InnerText);

当然,只有当tdtr的直接子女,但它们应该是,对吗?


编辑:

var cols = doc.DocumentNode.SelectNodes("//table[@id='table2']//tr//td");
for (int ii = 0; ii < cols.Count; ii=ii+2)
{
    string name = cols[ii].InnerText.Trim();
    int age = int.Parse(cols[ii+1].InnerText.Split(' ')[1]);
}

使用LINQ可能有更令人印象深刻的方法。

答案 2 :(得分:1)

我必须提供完整的xpath。我从@Coda(https://stackoverflow.com/a/3104048/1238850)的建议中使用Firebug得到了完整的xpath,我最终得到了这段代码:

foreach (HtmlNode row in doc.DocumentNode.SelectNodes("/html/body/table/tbody/tr/td/table[@id='table2']/tbody/tr"))
{
    HtmlNodeCollection cells = row.SelectNodes("td");
    for (int i = 0; i < cells.Count; ++i)
    {
        if (i == 0)
        { Response.Write("Person Name : " + cells[i].InnerText + "<br>"); }
        else {
            Response.Write("Other attributes are: " + cells[i].InnerText + "<br>"); 
        }
    }
}

我相信它可以写得比这更好,但它现在对我有用。

答案 3 :(得分:0)

我为此做了一个项目:

        private List<PhrasalVerb> ExtractVerbsFromMainPage(string content)
    {
        var verbs =new List<PhrasalVerb>(); ;
        HtmlDocument doc = new HtmlDocument();
        doc.LoadHtml(content);
        var rows = doc.DocumentNode.SelectNodes("//table[@class='idioms-table']//tr");
        rows.RemoveAt(0); //remove header
        foreach (var row in rows)
        {
            var cols = row.SelectNodes("td");
            verbs.Add(new PhrasalVerb { 
            Uid = Guid.NewGuid(),
            Name = cols[0].InnerHtml,
            Definition = cols[1].InnerText,
            Count =int.TryParse(cols[2].InnerText,out _) == true ? Convert.ToInt32(cols[2].InnerText) : 0
            });
        }
        return verbs;
    }