WebDriver может найти элемент, используя xpath, Html Agility Pack не может - PullRequest
3 голосов
/ 25 мая 2011

У меня постоянно были проблемы с 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 тоже не может его найти?

1 Ответ

8 голосов
/ 25 мая 2011

Проблема, с которой вы сталкиваетесь, связана с элементом 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");
...