WebDriver может найти элемент, используя xpath, Html Agility Pack не может

c# html-agility-pack visual-studio-2010 webdriver xpath

Вопрос

У меня постоянно возникали проблемы с Html Agility Pack; мои запросы XPath работают только когда они чрезвычайно просты:

//*[@id='some_id']

или

//input

Однако, в любое время, когда они становятся более сложными, Html Agility Pack не может справиться с этим. Вот пример, демонстрирующий проблему: я использую WebDriver для перехода к Google и возвращаю источник страницы, который передается в Html Agility Pack, и как WebDriver, так и HtmlAgilityPack пытаются найти элемент / узел (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();

В этом случае WebDriver успешно разместил элемент, но Html Agility Pack этого не сделал.

Я знаю, я знаю, в этом случае очень просто изменить xpath на тот, который будет работать: // input [@ name = 'q'] , но это только исправит этот конкретный пример, а это не так, Мне нужно что-то, что будет точно или, по крайней мере, близко отражать поведение движка xpath WebDriver или даже дополнения FirePath или FireFinder для Firefox.

Если WebDriver может его найти, то почему Html Agility Pack не может найти его?

Принятый ответ

Проблема, с которой вы сталкиваетесь, связана с элементом FORM. HTML Agility Pack обрабатывает этот элемент по-разному - по умолчанию он никогда не сообщит, что у него есть дети.

В конкретном примере, который вы указали, этот запрос находит целевой элемент:

.//div/div[2]/table/tr/td/table/tr/td/div/table/tr/td/div/div[2]/input

Однако этого не происходит, поэтому ясно, что элемент формы отключает парсер:

.//form/div/div[2]/table/tr/td/table/tr/td/div/table/tr/td/div/div[2]/input

Однако это поведение настраивается. Если вы поместите эту строку до разбора HTML, форма даст вам дочерние узлы:

HtmlNode.ElementsFlags.Remove("form");


Related

Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow