HtmlAgilityPack e selezionando Nodi e Sottonodes

Spero che qualcuno possa aiutarmi.

Diciamo che ho un documento html che contiene più div come questo esempio:

Richard Winchester Kodak Arlington Road 1
Ted Mosby HP Arlington Road 2

Sto usando HtmlAgilityPack per ottenere il documento html. Quello che ho bisogno di sapere è come posso ottenere gli span per ogni “search_hit” -div?

Il mio primo pensiero è stato qualcosa del genere:

 foreach (HtmlAgilityPack.HtmlNode node in doc.DocumentNode.SelectNodes("//div[@class='search_hit']")) { foreach (HtmlAgilityPack.HtmlNode node2 in node.SelectNodes("//span[@prop]")) { } } 

Ogni div dovrebbe essere un object con gli span inclusi come proprietà. I. e.

 public class Record { public string Name { get; set; } public string company { get; set; } public string street { get; set; } } 

E questo elenco sarà riempito allora:

 public List Results = new List(); 

Ma l’XPATH che sto usando non sta facendo una ricerca nel sottonodo come dovrebbe. Sembra che ricerchi l’intero documento ancora e ancora.

Voglio dire, l’ho già fatto funzionare in questo modo che ho ottenuto solo gli span dell’intera pagina. Ma poi non ho alcuna relazione tra gli span e le div. Mezzi: non so più quale intervallo è correlato a quale div.

Qualcuno conosce una soluzione? Ho già giocato così tanto che ora sono completamente confuso 🙂

Qualsiasi aiuto è apprezzato!

Il seguente funziona per me. Il bit importante è proprio come BeniBela ha notato di aggiungere un punto in seconda chiamata a “SelectNodes”.

 List lstRecords=new List(); 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); } 

Se si utilizza // , viene avviata la ricerca dal documento.

Usa .// per cercare tutto dal nodo corrente

  foreach (HtmlAgilityPack.HtmlNode node2 in node.SelectNodes(".//span[@prop]")) 

Oppure rilasciare il prefisso interamente per cercare solo i bambini diretti:

  foreach (HtmlAgilityPack.HtmlNode node2 in node.SelectNodes("span[@prop]")) 

Prima di tutto, dai un’occhiata a questo: Html Agility Pack – Problema nella selezione del sottonodo

Ecco una soluzione completa per la tua domanda:

 IList results = new List(); 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); } 

Se leggi la domanda che ti ho indicato, vedrai che fare ./span[@prop='name'] è esattamente la stessa, dal momento che i nodes di span sono figli (diretti) del nodo div .


Se i nodes di span non hanno questi attributi, e vuoi assegnarli a seconda dell’ordine in cui appaiono, puoi fare:

 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); } 

Mi vergogno 🙂

Tutti voi avete ragione.

Ho trovato il problema. Questa NullReferenceException continuava a tormentarmi, così ho passato più tempo a guardarlo nei dettagli. Tra tutte quelle div c’era un div con lo stesso attributo “class =” search-hit “” ma senza gli span all’interno. Ecco perché si verifica un errore nel secondo ciclo.

 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); } 

Il codice sopra sta funzionando.

Grazie ragazzi per il vostro tempo e il vostro aiuto!

L’ho usato. ID conversione di class

  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); }