【问题标题】:Parsing HTML Reading Option Tag Content with HtmlAgillityPack使用 HtmlAgillityPack 解析 HTML 读取选项标签内容
【发布时间】:2011-06-13 02:51:32
【问题描述】:

我正在尝试使用 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>

我需要解析来自&lt;select name="akt-miest" id="onoffaci"&gt;的值

例如:

<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 });
}

但我从另一个选择 (&lt;select id="region" name="region"&gt;) 中获取值,此选择位于 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;

我只解析前三个选项元素,因为我认为问题在于选择组成

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

【问题讨论】:

  • @user572844:查看我的答案以获得解决方案和解释。

标签: html select xpath html-agility-pack


【解决方案1】:

默认情况下,&lt;OPTION&gt; 标签被 Html Agility Pack 视为“空”,这意味着它不需要关闭 &lt;/OPTION&gt;。在这种情况下,结束标签被丢弃。您可以使用 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();
}

【讨论】:

  • 嗨,我试试你的代码,但它只选择前 3 个选项标签,可能是我没有显示所有 html 文件的问题。我在底部编辑了我的问题是 html 文件。
  • @user572844 - 好的,我明白你的意思了,实际上其他标签(optgroup)下还有选项,我已经相应地更新了代码,我已经替换了 //select[@id='onoffaci ']/option by //select[@id='onoffaci']//option(注意option前面的双/)
  • +1 并感谢您的回答 - 您是否知道为什么这是默认行为?还有其他标签会发生这种情况吗?
  • @AdamRackis - 是的,我愿意,请参阅此处了解更多 stackoverflow.com/questions/4218847/…stackoverflow.com/questions/5556089/…(要获得 ElementFlags 的完整列表,只需查看源代码,它是开源的)
  • 谢谢。所以,如果我只使用 HAP 来加载现有的 html,并将其移动到其他地方而不改变它,我最好删除 all 标志吗?
【解决方案2】:

您的 XPath 表达式:

//option

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

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

descendant::option

或者简写

.//option

请注意:这是唯一.self::node()简写)开始路径的情况。

【讨论】:

    【解决方案3】:

    你应该使用:

    selectNode.SelectNodes("option");
    

    代替:

    selectNode.SelectNodes("//option");
    

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

    【讨论】:

    • 不,我从选择节点开始,但我有问题,因为选择标签也包含 optgroup 标签。
    猜你喜欢
    • 2015-07-02
    • 1970-01-01
    • 2015-09-17
    • 2012-04-13
    • 2013-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多