使用HtmlAgillityPack解析HTML阅读选项标记内容

时间:2011-01-21 12:11:05

标签: html select xpath html-agility-pack

我正在尝试使用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(<select id="region" name="region">)获取值,此select位于html代码的顶部。

编辑:

我应用Darin Dimitrov的建议试试这个:

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;

我只解析前三个选项元素,因为我认为问题是select编码

optgroup tag。

<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 个答案:

答案 0 :(得分:21)

默认情况下,Html Agility Pack将<OPTION>标记视为“空”,这意味着它不需要关闭</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 :(得分:1)

您的XPath表达式:

//option

这是一条绝对路径:它从根开始遍历所有树

您需要一个相对的XPath表达式:

descendant::option

或简写

.//option

请注意:这是唯一的情况,使用.self::node()速记)开始路径非常有用。

答案 2 :(得分:0)

您应该使用:

selectNode.SelectNodes("option");

而不是:

selectNode.SelectNodes("//option");

或者您正在从HTML文档的根目录开始使用XPath表达式。