Analisi dell'HTML con HTML Agility Pack e Linq

c# html-agility-pack html-parsing linq

Domanda

Ho il seguente codice HTML

(..)
<tbody>
 <tr>
  <td class="name"> Test1 </td>
  <td class="data"> Data </td>
  <td class="data2"> Data 2 </td>
 </tr>
 <tr>
  <td class="name"> Test2 </td>
  <td class="data"> Data2 </td>
  <td class="data2"> Data 2 </td>
 </tr>
</tbody>
(..)

Le informazioni che ho sono il nome => quindi "Test1" e "Test2". Quello che voglio sapere è come posso ottenere i dati che sono in "data" e "data2" in base al nome che ho.

Attualmente sto usando:

(..)
<tbody>
 <tr>
  <td class="name"> Test1 </td>
  <td class="data"> Data </td>
  <td class="data2"> Data 2 </td>
 </tr>
 <tr>
  <td class="name"> Test2 </td>
  <td class="data"> Data2 </td>
  <td class="data2"> Data 2 </td>
 </tr>
</tbody>
(..)

Ma ottengo {"Object reference not set to an instance of an object."} Quando provo a cercare nei data

Risposta accettata

Per quanto riguarda il tuo tentativo, hai due problemi con il tuo codice:

  1. ChildNodes è strano - restituisce anche nodi di testo di spazi bianchi, che non hanno attributi di class (ovviamente non possono avere attributi).
  2. Come ha commentato James Walford, gli spazi intorno al testo sono significativi, probabilmente vorresti tagliarli.

Con queste due correzioni, i seguenti lavori:

var data =
      from tr in doc.DocumentNode.Descendants("tr")
      from td in tr.Descendants("td").Where(x => x.Attributes["class"].Value == "name")
     where td.InnerText.Trim() == "Test1"
    select tr;

Risposta popolare

Ecco il modo XPATH - hmmm ... tutti sembrano essersi dimenticati del potere XPATH e concentrarsi esclusivamente su C # XLinq, in questi giorni :-)

Questa funzione ottiene tutti i valori dei dati associati a un nome:

public static IEnumerable<string> GetData(HtmlDocument document, string name)
{
    return from HtmlNode node in
        document.DocumentNode.SelectNodes("//td[@class='name' and contains(text(), '" + name + "')]/following-sibling::td")
        select node.InnerText.Trim();
}

Ad esempio, questo codice eseguirà il dump di tutti i dati "Test2":

public static IEnumerable<string> GetData(HtmlDocument document, string name)
{
    return from HtmlNode node in
        document.DocumentNode.SelectNodes("//td[@class='name' and contains(text(), '" + name + "')]/following-sibling::td")
        select node.InnerText.Trim();
}



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché