Пакет гибкости Html — Проблема с выбором подузла

#c# #asp.net-mvc #html-agility-pack

#c# #asp.net-mvc #html-пакет гибкости

Вопрос:

Я хочу экспортировать свой план запуска Asic в iCal, и поскольку Asic не предлагают эту услугу, я решил создать небольшой scraper для своего личного использования. Что я хочу сделать, так это взять все запланированные запуски из моего плана и сгенерировать на их основе канал iCal. Я использую C # и пакет гибкости Html.

Что я хочу сделать, так это повторить все мои запланированные запуски (они являются узлами div). Затем я хочу выбрать несколько разных узлов с моими узлами запуска. Мой код выглядит следующим образом:

 foreach (var run in doc.DocumentNode.SelectSingleNode("//div[@id='scheduleTable']").SelectNodes("//div[@class='pTdBox']"))
{
    number  ;
    string date = run.SelectSingleNode("//div[@class='date']").InnerText;
    string type = run.SelectSingleNode("//span[@class='menu']").InnerHtml;
    string distance = run.SelectSingleNode("//span[@class='distance']").InnerHtml;
    string description = run.SelectSingleNode("//div[@class='description']").InnerHtml;
    ViewData["result"]  = "Dato: "   date   "<br />";
    ViewData["result"]  = "Tyep: "   type   "<br />";
    ViewData["result"]  = "Distance: "   distance   "<br />";
    ViewData["result"]  = "Description: "   description   "<br />";
    ViewData["result"]  = run.InnerHtml.Replace("<", "amp;<").Replace(">", "amp;>")   "<br />"   "<br />"   "<br />";
}
  

Моя проблема в том, что run.SelectSingleNode("//div[@class='date']").InnerText не выбирает узел с заданным XPath в пределах данного запущенного узла. Выбирается первый узел, который соответствует XPath во всем документе.

Как я могу выбрать единственный узел с заданным XPath в текущем узле?

Спасибо.

Обновить

Я попытался обновить свою строку XPath до этого:

 string date = run.SelectSingleNode(".div[@class='date']").InnerText;
  

Это должно выбрать <div class="date"></div> элемент внутри текущего узла, верно? Ну, я попробовал это, но получил эту ошибку:

Выражение должно соответствовать набору узлов. Описание: Необработанное исключение возникло во время выполнения текущего веб-запроса. Пожалуйста, просмотрите трассировку стека для получения дополнительной информации об ошибке и о том, где она возникла в коде.

Сведения об исключении: System.Xml.XPath.XPathException: Выражение должно соответствовать набору узлов.

Есть предложения?

Комментарии:

1. Я не уверен (вообще) в XPath, но не // означает ли это, что где-либо из root?

2. w3schools.com/xpath/xpath_axes.asp : Мне кажется, вам нужно что-то вроде child::div[@class='data'] , но опять же, я не знаю наверняка. Вообще.

Ответ №1:

Несколько вещей, которые помогут вам при работе с выражениями HtmlAgilityPack и XPath.

Если run является HtmlNode , то:

  1. run.SelectNodes("//div[@class='date']")

    Будет вести себя точно так же, как doc.DocumentNode.SelectNodes("//div[@class='date']")

  2. run.SelectNodes("./div[@class='date']")

    Предоставит вам все <div> узлы, которые являются дочерними элементами run узла. Он не будет искать глубже, только на самом следующем уровне глубины.

  3. run.SelectNodes(".//div[@class='date']")

    Вернет все <div> узлы с этим атрибутом класса, но не только рядом с run узлом, но и проведет углубленный поиск (во всех возможных его потомках)

Вам придется выбирать между 2. или 3., в зависимости от того, какой из них удовлетворяет вашим потребностям 🙂

Комментарии:

1. Боже, ты просто спас мне жизнь. Я просто перепутал между 1 и 3. Спасибо, чувак.

2. @Soren Со мной случилось то же самое 🙂

Ответ №2:

В XPATH // означает всех дочерних и внучатых дочерних элементов ниже текущего узла. Итак, вам нужно придумать более строгое выражение XPATH. Если вы предоставите реальный HTML-код и именно то, что вы ищете, мы можем помочь вам копать дальше.

Об ошибке, которая у вас:

.div[@class='date'] недопустимо, потому что . привязано к div . Вы могли бы использовать div[@class='date'] , или ./div[@class='date'] которые, я считаю, эквивалентны. Это потому, что . это XPATH axe, который является псевдонимом для self и означает «текущий узел».

Комментарии:

1. @Simon Mourier — Я также пытаюсь получить данные с узла, имеющего атрибут «name», но он их не принимает

2. @студент — тебе следует написать другой вопрос