Obtener tablas específicas con Html Agility Pack

c# html-agility-pack xpath

Pregunta

Estoy teniendo problemas para obtener algunas tablas específicas con HTML Agility Pack. Tampoco puedo cambiar el HTML real, por lo que no puedo usar otras ID o Clases ni nada.

¿Puede alguien mostrarme cómo accedería a cada tabla individual de lo siguiente?

<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>

Ahora mismo si tuviera que llamar al siguiente

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

Yo pasaría por todo. Quiero poder acceder a las tablas de manera diferente para correlacionar donde estoy almacenando los datos.

He intentado mirar algo como

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

pero el uso de un índice no parece funcionar, cuando intento especificar una tabla con él, todavía se lee en todas las tablas o en ninguna.

Lo mismo se aplica a esto, o bien no funciona en absoluto o obtiene todo.

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

Estoy usando el paquete NuGet de HTML Agility Pack 1.4.9

EDITAR:

Mi intento de obtener SOLAMENTE la Tabla 1 - los contenidos de A Ambos dan excepciones nulas o endcodingfound finalizadas.

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

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

Respuesta aceptada

El error está en su segunda llamada, el "// tr / td" volverá al elemento raíz. Su indexador es la solución correcta para la primera parte de su problema, la segunda puede solucionarse especificando que desea navegar desde donde se encuentra:

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

No estoy seguro de qué más está pasando, pero al ampliar su tabla de prueba a este código , lo siguiente simplemente funciona en mi prueba. Podría significar que necesitas compartir un poco más de contexto.

Este es el documento que utilicé para las pruebas:

<!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>

Y este es el código para extraer los valores que buscas:

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

Muestra:

introduzca la descripción de la imagen aquí

Actualizar

Ok, tomé tu HTML real y también obtengo una NullReference. Debe haber algo que confunda enormemente el paquete de agilidad, no estoy seguro de por qué. Sin embargo, algunos experimentos con la API de Linq parecen funcionar, espero que pueda ser una alternativa para ti:

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


Related

Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué