Cómo seleccionar una tabla que contenga cierta palabra clave - c # - xpath - htmlagilitypack

c# html-agility-pack keyword select xpath

Pregunta

Tengo que recopilar información de una página de producto que no tiene ninguna clase o ID. Estoy usando htmlagilitypack y c # 4.0.

Hay muchas tablas en este código fuente de la página del producto. La tabla de precios contiene la cadena "KDV". Así que me gustaría obtener esta tabla "KDV" que contiene la tabla. Cómo puedo hacer eso ?

El xpath a continuación seleccionaría todas las tablas por ejemplo

string srxPathOfCategory = "//table";
var selectedNodes = myDoc.DocumentNode.SelectNodes(srxPathOfCategory);

El siguiente código selecciona la tabla pero a partir de la mayoría de la tabla externa. Necesito seleccionar la mayoría de la tabla interna que contiene esa cadena dada

//table[contains(., ' KDV')]

c #, xpath, htmlagilitypack

Respuesta aceptada

El siguiente código selecciona la tabla pero a partir de la mayoría de la tabla externa. Necesito seleccionar la mayoría de la tabla interna que contiene esa cadena dada

Uso :

//table
    [not(descendant::table) 
   and 
     .//text()[contains(., ' KDV')]
    ]

Esto selecciona cualquier table en el documento XML que no tiene un descendiente de table , y que tiene un descendiente de nodo de texto que contiene la cadena " KDV" .

En general, la expresión anterior podría seleccionar muchos de estos elementos de table .

Si solo desea seleccionar uno de ellos (por ejemplo, el primero), use esta expresión XPath. Observe los corchetes :

   (//table
        [not(descendant::table) 
       and 
         .//text()[contains(., ' KDV')]
        ]
    )[1]

Recuerde : si desea seleccionar el primer elemento someName en el documento, usar esto (como en la respuesta actualmente aceptada) es incorrecto:

//someName[1]

Esta es la segunda pregunta más frecuente en XPath (después de cómo seleccionar elementos con nombres sin prefijo en un documento XML con un espacio de nombres predeterminado).

La expresión anterior en realidad selecciona cualquier elemento someName en el documento, que es el primer elemento secundario de su padre, inténtelo.

El motivo de este comportamiento no intuitivo se debe a que el operador XPath [] tiene una mayor prioridad (prioridad) que el // pseudooperador.

La expresión correcta que realmente selecciona solo el primer elemento someName (en cualquier documento XML), si existe, es:

(//someName)[1]

Aquí, los paréntesis se utilizan para anular explícitamente la prioridad del operador XPath predeterminado.


Respuesta popular

Puede haber una manera más eficiente de hacerlo. De todos modos, este es el código completo que he usado para su caso y funciona para mí:

        HtmlDocument doc = new HtmlDocument();
        string url = "http://www.pratikev.com/fractalv33/pratikEv/pages/viewProduct.jsp?pInstanceId=3138821";
        using (var response = (WebRequest.Create(url).GetResponse()))
        {
            doc.LoadHtml(new StreamReader(response.GetResponseStream()).ReadToEnd());
        }
        /*There is an bug in the xpath used here. Should have been 
          (//table/tr/td/font[contains(.,'KDV')])[1]/ancestor::table[2] 
          See Dimitre's answer for an explanation and an alternative / 
          more generic / (needless to say) better approach */
        string xpath = "//table/tr/td/font[contains(.,'KDV')][1]/ancestor::table[2]"; 
        HtmlNode table = doc.DocumentNode.SelectSingleNode(xpath);


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é