C# Html Agility Pack在表格行和列之间循环

C# Html Agility Pack在表格行和列之间循环,c#,.net,html-agility-pack,C#,.net,Html Agility Pack,我有一张这样的桌子 名称 年龄 马里奥 年龄:78 简 年龄:67 詹姆斯 年龄:92 并希望使用HTML Agility Pack来解析它。我已尝试此代码,但无效: foreach (HtmlNode row in doc.DocumentNode.SelectNodes("//table[@id='table2']//tr")) { foreach (HtmlNode col in row.SelectNodes("//td")) { Response.

我有一张这样的桌子


名称
年龄
马里奥
年龄:78
简
年龄:67
詹姆斯
年龄:92
并希望使用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); 
    }
}

我做错了什么?

为什么不直接选择
td
s

foreach (HtmlNode col in doc.DocumentNode.SelectNodes("//table[@id='table2']//tr//td"))
    Response.Write(col.InnerText);
或者,如果您确实需要将
tr
s单独用于其他处理,请放下
/
,然后执行以下操作:

foreach (HtmlNode row in doc.DocumentNode.SelectNodes("//table[@id='table2']//tr"))
    foreach (HtmlNode col in row.SelectNodes("td"))
        Response.Write(col.InnerText);
当然,只有当
td
s是
tr
s的直接子对象时,这才有效,但它们应该是,对吗


编辑:

var cols=doc.DocumentNode.SelectNodes(//table[@id='table2']//tr//td”);
对于(int ii=0;ii

使用LINQ可能有一种更令人印象深刻的方法。我已经运行了代码,它只显示名称,这是正确的,因为年龄是使用无效的HTML定义的:
(可能是打字错误)

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

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

下面是我用来测试的代码:

我必须提供完整的xpath。我从@Coda()的建议中使用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>"); 
        }
    }
}
foreach(doc.DocumentNode.SelectNodes中的HtmlNode行(“/html/body/table/tbody/tr/td/table[@id='table2']/tbody/tr”))
{
HtmlNodeCollection cells=row.SelectNodes(“td”);
对于(int i=0;i”);}
否则{
Write(“其他属性为:“+cells[i].InnerText+”
”; } } }

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

我用这个做了同样的项目:

        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;
    }
private List ExtractVerbsFromMainPage(字符串内容)
{
变量动词=新列表();
HtmlDocument doc=新的HtmlDocument();
doc.LoadHtml(内容);
var rows=doc.DocumentNode.SelectNodes(“//table[@class='idioms-table']//tr”);
rows.RemoveAt(0);//删除标头
foreach(行中的变量行)
{
var cols=row.SelectNodes(“td”);
动词.Add(新短语)
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
});
}
返回动词;
}

你能描述一下什么不起作用吗?我得到了一个无限循环它对我起作用(嗯,不完全是这样,我得到的名字马里奥/简/詹姆斯重复了4次)。请注意,“//td”并不仅仅从当前节点中选择(正如您可能期望的那样),而是从DocumentNode中选择。你使用的是什么版本的HtmlAgilityPack?嗯,看起来像你的.NET版本。您是否通过NuGet获得HtmlAgilityPack?您是对的,这是版本:1.4.6.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;
    }