Ottieni tabelle specifiche con Html Agility Pack

c# html-agility-pack xpath

Domanda

Sto riscontrando problemi nell'ottenere alcuni tavoli specifici con HTML Agility Pack. Non posso neanche modificare l'HTML effettivo, quindi non posso usare altri ID o Classi o altro.

Qualcuno può mostrarmi come accedere a ogni singola tabella di seguito?

<table class="newTable">
      //table 1 contents
    <table border="0" cellpadding="3" cellspacing="2" width="100%">
         //table 1 - A contents
    </table>
</table>
<table border="0" cellpadding="0" cellspacing="0" class="newTable">
     //table 2 contents
    <table width="100%" border="0" cellspacing="2" cellpadding="0">
        //table 2 - A contents
    </table>
    <table width="100%" border="0" cellspacing="2" cellpadding="0">
       //table 2 - B contents
    </table>
    <table width="100%" cellspacing="2" cellpadding="0">
       //table 2 - C contents
    </table>
</table>
<table>
     //table 3 contents
</table>

In questo momento se dovessi chiamare il seguente

HtmlNode table = doc.DocumentNode.SelectSingleNode("//table");
foreach (var cell in table.SelectNodes("//tr/td"))
{
     string someVariable = cell.InnerText
}

Vorrei passare attraverso tutto. Voglio poter accedere alle tabelle in modo diverso per correlare dove sto memorizzando i dati.

Ho provato a guardare qualcosa di simile

doc.DocumentNode.SelectNodes("//table[1]");

ma l'uso di un indice non sembra funzionare, quando provo a specificare una tabella con esso, continua a leggere in tutte le tabelle o nessuna.

La stessa cosa vale per questo, o non funziona affatto o ottiene tutto.

foreach (var cell in table.SelectNodes("//table").Skip(some_number))
{
     string someVariable = cell.InnerText
}

Sto usando il pacchetto NuGet di HTML Agility Pack 1.4.9

MODIFICARE:

Il mio tentativo di ottenere SOLO la Tabella 1 - I contenuti di A. Entrambi forniscono eccezioni null o endcoding.

HtmlNode table = doc.DocumentNode.SelectSingleNode("//table/tr/td/table[1]");

HtmlNode table = doc.DocumentNode.SelectSingleNode("//table[1]/tr/td/table[1]");

Risposta accettata

L'errore è con la tua seconda chiamata, il "// tr / td" tornerà all'elemento root. Il tuo indicizzatore è la soluzione corretta per la prima parte del tuo problema, il secondo può essere risolto specificando che vuoi navigare da dove ti trovi:

HtmlNode table = doc.DocumentNode.SelectSingleNode("//table[1]");
foreach (var cell in table.SelectNodes(".//tr/td")) // **notice the .**
{
     string someVariable = cell.InnerText
}

Non sono sicuro di cos'altro sta succedendo, ma estendendo la tabella di test a questo codice , quanto segue funziona solo sul mio test. Potrebbe voler dire che devi condividere un po 'più di contesto.

Questo è il documento che ho usato per i test:

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    <table class="newTable">
        <tr>
            <td>
                <table border="0" cellpadding="3" cellspacing="2" width="100%">
                    <tr><td>
                        //table 1 - A contents
                    </td></tr>
                </table>
            </td>
        </tr>

    </table>
    <table border="0" cellpadding="0" cellspacing="0" class="newTable">
        <tr>
            <td>
                //table 2 contents
                <table width="100%" border="0" cellspacing="2" cellpadding="0">
                    <tr>
                        <td>
                            //table 2 - A contents
                        </td>
                    </tr>
                </table>
                <table width="100%" border="0" cellspacing="2" cellpadding="0">
                    <tr>
                        <td>
                            //table 2 - B contents
                        </td>
                    </tr>
                </table>
                <table width="100%" cellspacing="2" cellpadding="0">
                    <tr>
                        <td>
                            //table 2 - C contents
                        </td>
                    </tr>
                </table>
            </td>
        </tr>
    </table>
    <table>
        <tr>
            <td>
                //table 3 contents
            </td>
        </tr>
    </table>
</body>
</html>

E questo il codice per estrarre i valori che stai cercando:

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(text);

var node1A = doc.DocumentNode.SelectSingleNode("//table[1]//table[1]");
string content1A = node1A.InnerText;
Console.WriteLine(content1A);

var node2C = doc.DocumentNode.SelectSingleNode("//table[2]//table[3]");
string content2C = node2C.InnerText;
Console.WriteLine(content2C);

Spettacoli:

inserisci la descrizione dell'immagine qui

Aggiornare

Ok, ho preso il tuo vero codice HTML e ho anche un NullReference. Deve esserci qualcosa che confonde enormemente l'Agility Pack, non so perché. Alcuni esperimenti con l'API di Linq sembrano funzionare, spero che possa essere un'alternativa per voi:

var table = doc.DocumentNode.DescendantsAndSelf("table").Skip(1).First().Descendants("table").First();
var tds   = table.Descendants("td");


Related

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é