Анализ содержимого тега опции чтения HTML с помощью HtmlAgillityPack - PullRequest
3 голосов
/ 21 января 2011

Я пытаюсь использовать HtmlAgilityPack для разбора HTML, но у меня возникли проблемы.

Пример документа HTML:

<tr>
  <td class="css_lokalita" colspan="4">
    <select id="region" name="region">
      <option value="0"  selected>Všetky regiony</option>
      <optgroup>Banskobystrický kraj</optgroup>
      <option value="k_1"  style="color: #000000; font-weight:bold;">Banskobystrický kraj</option>
      <option value="1">&nbsp;&nbsp;&nbsp;Banská Bystrica</option>
          .
          .
          .
      <option value="174">&nbsp;&nbsp;&nbsp;CZ - Ústecký kraj</option>
      <option value="175">&nbsp;&nbsp;&nbsp;CZ - Zlínský kraj</option>     
    </select>
  </td>
</tr>

<tr>
  <td class="css_sfotkou"  colspan="4">
    <input type="checkbox" name="foto" value="1" id="foto" />
    <label for="foto">Iba používatelia s fotkou</label>
  </td>
</tr>

<tr>
  <td class="css_miestnost" colspan="4">
    <select name="akt-miest" id="onoffaci">
      <option value="a_0">Všetci</option>
          .
          .
          .
      <optgroup label="Záľuby a záujmy">
        <option value="m_1419307">&nbsp;&nbsp;&nbsp;Bez Lásky</option>
          .
          .
          .
        <option value="m_1108016">&nbsp;&nbsp;&nbsp;Drum N Bass</option>
      </optgroup>
    </select>
  </td>
</tr>

Мне нужно значение разбора от <select name="akt-miest" id="onoffaci">

Например:

<option value="**a_0**">**Všetci**</option>

Мне нужно получить значение **a_0** и текст **Všetci**.

Итак, я вначале пытаюсь получить доступ по Id:

var selectNode = htmlDoc.GetElementbyId("onoffaci");

Затем с помощью Xpath выберите все опционные узлы.

var nodes = selectNode.SelectNodes("//option");

И получить значения:

foreach (var node in nodes)
{
    string roomName = node.NextSibling.InnerText;
    string roomId = node.Attributes["value"].Value;
    rooms.Add(new Room { RoomId = roomId, RoomName = roomName });
}

Но я получаю значения из другого выбора (<select id="region" name="region">), этот выбор находится в верхней части HTML-кода.

РЕДАКТИРОВАНИЕ:

Я применяю совет Дарина Димитрова, попробуйте это:

HtmlNode selectNode = htmlDoc.GetElementbyId("onoffaci");

var nodes = selectNode.SelectNodes("option");

foreach (var node in nodes)
{
    string roomName = node.NextSibling.InnerText;
    string roomId = node.Attributes["value"].Value;
    rooms.Add(new Room { RoomId = roomId, RoomName = roomName });
}

return rooms;

Я анализирую только первые три элемента option, потому что думаю, что проблема состоит в том, что select состоящий

тег optgroup.

<select name="akt-miest" id="onoffaci">
  <option value="a_0">Všetci</option>
  <option value="a_1">Iba prihlásení</option>
  <option value="a_5" selected="selected">Teraz na Pokeci</option>
  <optgroup label="Hlavné miestnosti">
    <option value="m_13">&nbsp;&nbsp;&nbsp;Bez záväzkov</option>
    <option value="m_9">&nbsp;&nbsp;&nbsp;Do pohody</option>
    <option value="m_39">&nbsp;&nbsp;&nbsp;Dámsky klub</option>
  </optgroup>
  .
  .
  .

Я пытаюсь выбрать все следующие узлы с этим

var nodes = selectNode.SelectNodes("option::*");

Но я получаю эту ошибку: xpath has an invalid token.

Я хотел бы получить доступ ко всем дочерним элементам selectNode:

HtmlNode selectNode = htmlDoc.GetElementbyId("onoffaci");

РЕДАКТИРОВАТЬ # 2:

Вот все это html-файл, из которого мне нужны теги параметров разбора.

http://hotfile.com/dl/98442053/577b556/source.html

Ответы [ 3 ]

21 голосов
/ 21 января 2011

По умолчанию тег <OPTION> обрабатывается Html Agility Pack как «пустой», что означает, что ему не нужно закрывать </OPTION>. В этом случае закрывающий тег отбрасывается. Вы можете изменить это поведение, используя коллекцию HtmlNode.ElementFlags.

Вот код, который должен делать то, что вы хотите:

HtmlDocument doc = new HtmlDocument();
HtmlNode.ElementsFlags.Remove("option");
doc.LoadHtml(yourHtml);

foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//select[@id='onoffaci']//option"))
{
    Console.WriteLine("Value=" + node.Attributes["value"].Value);
    Console.WriteLine("InnerText=" + node.InnerText);
    Console.WriteLine();
}
1 голос
/ 21 января 2011

Ваше выражение XPath:

//option

Это абсолютный путь: он пересекает все дерево , начиная с корня .

Вам необходимо относительное выражение XPath:

descendant::option

Или сокращение

.//option

Обратите внимание: это только случай, когда путь начинается с .(self::node() сокращение) полезно.

0 голосов
/ 21 января 2011

Вы должны использовать:

selectNode.SelectNodes("option");

вместо:

selectNode.SelectNodes("//option");

или вы запускаете выражение XPath из корня HTML-документа.

...