HtmlAgilityPack和选择节点和子节点
希望有人能帮助我。HtmlAgilityPack和选择节点和子节点
Let's说我有一个包含多个div像这样的例子一个html文件:使用HtmlAgilityPack得到html文件
<div class="search_hit">
<span prop="name">Richard Winchester</span>
<span prop="company">Kodak</span>
<span prop="street">Arlington Road 1</span>
</div>
<div class="search_hit">
<span prop="name">Ted Mosby</span>
<span prop="company">HP</span>
<span prop="street">Arlington Road 2</span>
</div>
I'm。我需要知道的是,如何获得每个“search_hit”-div的跨度?
我首先想到的是这样的:
foreach (HtmlAgilityPack.HtmlNode node in doc.DocumentNode.SelectNodes("//div[@class='search_hit']"))
{
foreach (HtmlAgilityPack.HtmlNode node2 in node.SelectNodes("//span[@prop]"))
{
}
}
每个div都应该是一个对象附带的跨度为属性。 I. e。
public class Record
{
public string Name { get; set; }
public string company { get; set; }
public string street { get; set; }
}
,并且该列表应然后填充:
public List<Record> Results = new List<Record>();
但使用XPath i'm不是在做它应该做的子节点的搜索。它接触到它一次又一次搜索整个文档。
我的意思是我已经得到它的工作方式,我只是得到整个页面的跨度。但是,我没有跨度和divs之间的关系。意思是:我不知道哪个跨度与哪个div有关。
有人知道解决方案吗?我已经玩了很多,我现在完全混淆:)
任何帮助表示赞赏!
我下面的作品。重要的一点就是BeniBela指出在第二次调用'SelectNodes'时增加一个点。
List<Record> lstRecords=new List<Record>();
foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//div[@class='search_hit']"))
{
Record record=new Record();
foreach (HtmlNode node2 in node.SelectNodes(".//span[@prop]"))
{
string attributeValue = node2.GetAttributeValue("prop", "");
if (attributeValue == "name")
{
record.Name = node2.InnerText;
}
else if (attributeValue == "company")
{
record.company = node2.InnerText;
}
else if (attributeValue == "street")
{
record.street = node2.InnerText;
}
}
lstRecords.Add(record);
}
如果您使用//
,它将从文档开始搜索。
使用.//
搜索所有从当前节点
foreach (HtmlAgilityPack.HtmlNode node2 in node.SelectNodes(".//span[@prop]"))
或丢弃前缀完全搜索只是直接孩子:
foreach (HtmlAgilityPack.HtmlNode node2 in node.SelectNodes("span[@prop]"))
如果我这样做:foreach(Node.SelectNodes(“span [@prop]”))中的HtmlAgilityPack.HtmlNode node2 Visual Studio出现错误。 – 2013-02-21 14:00:34
什么样的错误?你也可以尝试使用'。/'前缀。 (我实际上只是猜测) – BeniBela 2013-02-21 14:05:27
我试了两个都结束了:NullReferenceException:对象引用未设置为对象的实例。 – 2013-02-21 14:07:25
首先,来看看这个:Html Agility Pack - Problem selecting subnode
这里是你的问题的完整有效的解决方案:
IList<Record> results = new List<Record>();
foreach (var node in doc.DocumentNode.SelectNodes("//div[@class='search_hit']")) {
var record = new Record();
record.Name = node.SelectSingleNode(".//span[@prop='name']").InnerText;
record.company = node.SelectSingleNode(".//span[@prop='company']").InnerText;
record.street = node.SelectSingleNode(".//span[@prop='street']").InnerText;
results.Add(record);
}
如果你读我指出你的问题,你会看到做./span[@prop='name']
是完全一样的,因为那些span
节点是div
节点的(直接)子节点。
如果span
节点没有那些prop
属性,要为它们分配取决于它们出现的顺序,你可以这样做:
foreach (var node in doc.DocumentNode.SelectNodes("//div[@class='search_hit']")) {
var spanNodes = node.SelectNodes("./span");
var record = new Record();
record.Name = spanNodes[0].InnerText;
record.company = spanNodes[1].InnerText;
record.street = spanNodes[2].InnerText;
results.Add(record);
}
可耻的是我:)
你们都是对的。
我发现了这个问题。这个NullReferenceException不停地唠叨我,所以我花了更多的时间仔细查看它。 在所有这些div之间有一个div具有相同的“class ='search-hit'”属性,但没有跨度。这就是为什么它在第二个循环中通过一个错误。
foreach (HtmlAgilityPack.HtmlNode node in doc.DocumentNode.SelectNodes("//span[@prop]/ancestor::div[@class='search_hit']"))
{
Record rec = new Record();
foreach (HtmlAgilityPack.HtmlNode node2 in node.SelectNodes(".//span[@prop]"))
{
}
rList.Results.Add(rec);
}
上面的代码正在工作。
谢谢你们的时间和帮助!
我用过那个。 class convert id
HtmlNodeCollection nodes = dokuman.DocumentNode.SelectNodes("//div[@id='search_hit']//span[@prop]");
for (int i = 0; i < nodes .Count; i++)
{
var record = new Record();
record.Name = links[i].InnerText; results.Add(record); }
请参阅我对解析代码的方法(完整工作解决方案)的回答。 – 2013-02-22 07:16:58