Хтмладжилитипак | Неправильно извлеченные узлы таблицы

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

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

В основном:

  • Узел таблицы называется <table class="tlist">
  • Каждый узел строки называется <tr class="tlistrow">, иногда это "доверенный 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;
        }
    }
}

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

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


person Konrad Piesiak    schedule 23.01.2012    source источник


Ответы (2)


    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'] 
person Dimitre Novatchev    schedule 24.01.2012
comment
Ура, это было самое простое решение, которое я когда-либо видел. Большое спасибо! На самом деле я никогда не читал о XPath, поэтому я потерпел неудачу... - person Konrad Piesiak; 25.01.2012
comment
@KonradPiesiak: Добро пожаловать. XPath — удивительный, мощный и элегантный язык (и эти качества усиливаются в версиях 2.0 и 3.0). Это заслуживает систематического изучения. - person Dimitre Novatchev; 25.01.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;
        }
    }
}
person D'Arcy Rittich    schedule 23.01.2012