HtmlAgilityPack |Неправильно извлеченные узлы таблицы - PullRequest
1 голос
/ 24 января 2012

Привет, я только что зарегистрировался на этом сайте, потому что мне нужна помощь.

Я хочу получить результаты с сайта nyaa.eu.

В основном:

  • Узел таблицы называется <table class="tlist">
  • Каждый узел строки называется <tr class="tlistrow">, иногда это также 'доверенный список пользователей * и т. Д.
  • Узлы, которые я пытаюсь получить: <td class="tlistname"> <td class="tlistsize"> <td class="tlistsn"> and <td class="tlistln">

Во-первых, я получаю таблицу, которая содержит всю информацию о торрентах:

HtmlNode hnTable = doc.DocumentNode.SelectSingleNode("//table[@class='tlist']");

Итак, следующая вещь - получение всех строк, которые содержат tlistrow в атрибуте класса:

HtmlNodeCollection hncRows = hnTable.SelectNodes("//tr[contains(@class,'tlistrow')]");

И, наконец, проблема в том, что когда я читаю каждый узел, он всегда один и тот же:

foreach (HtmlNode row in hncRows)
{
    foreach (HtmlNode child in row.ChildNodes)
    {
        if (child.SelectSingleNode("//td[@class='tlistname']") != null)
        {
            MessageBox.Show("Something found!\n\n" + child.SelectSingleNode("//td[@class='tlistname']").InnerText);
            break;
        }
    }
}

Текст, отображаемый в окне сообщения, всегда один и тот же, похоже, он выбирает только один узел несколько раз.

Как мне это исправить или если я делаю что-то не так, поправьте меня.

Ответы [ 2 ]

1 голос
/ 24 января 2012
    foreach (HtmlNode child in row.ChildNodes)
    {
        if (child.SelectSingleNode("//td[@class='tlistname']") != null)
        {
            MessageBox.Show("Something found!\n\n" + child.SelectSingleNode("//td[@class='tlistname']").InnerText);
            break;
        }
    }

Вам необходимо понять разницу между относительными выражениями XPath и абсолютными выражениями XPath .

Относительное выражение XPath оценивается (имея в качестве исходного узла контекста) определенный узел в документе XML.

Абсолютное выражение XPath оценивается по всему документу XML (имеющему в качестве начального контекстного узла документ-узел).

Любое выражение XPath, начинающееся с символа /, является абсолютным выражением XPath.

Исходя из предоставленного кода, вы хотите использовать относительное выражение XPath с начальным контекстным узлом, записываемым в переменную с именем child.

Проблема в том, что выражение, которое вы используете:

//td[@class='tlistname'] 

начинается с / и поэтому является абсолютным выражением XPath.

Это, переданное методу SelectSingleNode(), всегда выбирает первый элемент td во всем XML-документе, который имеет атрибут class со строковым значением "tlistname."

Решение : Используйте относительное выражение XPath, например:

.//td[@class='tlistname'] 
0 голосов
/ 24 января 2012

// XPath в выражении будет искать совпадения в любом месте документа.Удалите это, когда вам это не нужно.

Итак, попробуйте что-то вроде:

HtmlNode hnTable = doc.DocumentNode.SelectSingleNode("//table[@class='tlist']"); 
HtmlNodeCollection hncRows = hnTable.SelectNodes("/tr[contains(@class,'tlistrow')]");
foreach (HtmlNode row in hncRows)
{
    foreach (HtmlNode child in row.ChildNodes)
    {
        if (child.SelectSingleNode("/td[@class='tlistname']") != null)
        {
            MessageBox.Show("Something found!\n\n" + child.SelectSingleNode("/td[@class='tlistname']").InnerText);
            break;
        }
    }
}
...