HtmlAgilityPack循环节点集合时内部Select查询总返回首条数据问题
问题根源
你代码中所有XPath查询开头的//语法,在XPath标准中代表从整个文档的根节点开始全局匹配,而非限定在当前调用方法的节点范围内。所以不管你在循环中的哪个子节点下执行查询,最终返回的永远是整个文档里第一个符合条件的元素,才会出现每次查询结果都和首次节点结果一致的问题。
修复方案
把所有XPath查询开头的//替换为.//,其中.代表当前节点的上下文,这样查询范围就会被限制在当前遍历的k-user-item节点内部。
修改后代码参考:
var nodes = w.DocumentNode.SelectNodes("//div[contains(@class, 'k-user-item')]"); List<Sales> saleList = new List<Sales>(); foreach (HtmlNode node in nodes) { // 此行可正确输出各节点的HTML // Debug.WriteLine(node.InnerHtml); string payout = node.SelectSingleNode(".//*[@class=\"k-item--buy-date\"]").InnerText; string size = node.SelectSingleNode(".//*[@class=\"k-panel-title\"]").SelectNodes(".//span")[1].InnerText; var trNodes = node.SelectNodes(".//tr"); string status = trNodes[1].SelectSingleNode(".//b").InnerText; string orderId = trNodes[2].SelectNodes(".//td")[1].SelectSingleNode(".//span").InnerHtml; string sellDate = node.SelectSingleNode(".//*[@class=\"k-panel-heading\"]").SelectNodes(".//small")[1].InnerHtml; // 补充将实例加入列表的逻辑,原代码遗漏该步骤 saleList.Add(new Sales() { Payout = payout, Size = size, Status = status, OrderId = orderId, SellDate = sellDate }); }
额外注意事项
- 替换后每个查询的范围限定在单个
k-user-item节点内,需要确认每个节点内的元素数量和你代码中写的[1]这类索引匹配,避免出现索引越界异常。 - 如果存在部分节点缺失指定类名的元素的情况,建议对
SelectSingleNode的返回结果加非空判断,避免触发空引用异常。
内容的提问来源于stack exchange,提问作者Manolo Martinez
相关产品推荐
相关产品推荐

