c# - WebDriver puede encontrar elementos usando xpath, Html Agility Pack no puede
visual-studio-2010 html-agility-pack (1)
Continuamente he tenido problemas con Html Agility Pack; mis consultas XPath solo funcionan cuando son extremadamente simples:
//*[@id=''some_id'']
o
//input
Sin embargo, cada vez que se vuelven más complicados, Html Agility Pack no puede manejarlo. Aquí hay un ejemplo que demuestra el problema, estoy usando WebDriver para navegar a Google y devolver el origen de la página, que se pasa a Html Agility Pack, y tanto WebDriver como HtmlAgilityPack intentan localizar el elemento / nodo (C #):
//The XPath query
const string xpath = "//form//tr[1]/td[1]//input[@name=''q'']";
//Navigate to Google and get page source
var driver = new FirefoxDriver(new FirefoxProfile()) { Url = "http://www.google.com" };
Thread.Sleep(2000);
//Can WebDriver find it?
var e = driver.FindElementByXPath(xpath);
Console.WriteLine(e!=null ? "Webdriver success" : "Webdriver failure");
//Can Html Agility Pack find it?
var source = driver.PageSource;
var htmlDoc = new HtmlDocument { OptionFixNestedTags = true };
htmlDoc.LoadHtml(source);
var nodes = htmlDoc.DocumentNode.SelectNodes(xpath);
Console.WriteLine(nodes!=null ? "Html Agility Pack success" : "Html Agility Pack failure");
driver.Quit();
En este caso, WebDriver localizó con éxito el elemento, pero Html Agility Pack no lo hizo.
Lo sé, lo sé, en este caso es muy fácil cambiar el xpath a uno que funcione: // ingrese [@ name = ''q''] , pero eso solo solucionará este ejemplo específico, que no es el punto, Necesito algo que exactamente o al menos refleje el comportamiento del motor xpath de WebDriver, o incluso los complementos FirePath o FireFinder para Firefox.
Si WebDriver puede encontrarlo, ¿por qué no puede Html Agility Pack encontrarlo también?
El problema con el que te estás encontrando es con el elemento FORM. HTML Agility Pack maneja ese elemento de manera diferente : de manera predeterminada, nunca informará que tiene hijos.
En el ejemplo particular que proporcionó, esta consulta encuentra el elemento de destino:
.//div/div[2]/table/tr/td/table/tr/td/div/table/tr/td/div/div[2]/input
Sin embargo, esto no es así, así que está claro que el elemento de formulario está tropezando con el analizador:
.//form/div/div[2]/table/tr/td/table/tr/td/div/table/tr/td/div/div[2]/input
Ese comportamiento es configurable, sin embargo. Si coloca esta línea antes de analizar el HTML, el formulario le dará nodos secundarios:
HtmlNode.ElementsFlags.Remove("form");