无法使用Html Agility Pack选择节点

时间:2014-10-03 18:10:25

标签: c# html html-agility-pack

我有当前的HTML布局

<table> //table[1]
</table>
<table> //table[2]
<tbody>
   <tr>
      <td>
         <p>
            &nbsp;
         </p>
      </td>
   </tr>
   <tr>
      <td>
         <table> //table[1]//table[1]
            <tbody>
               <tr>
                  <td>
                     <p>
                        INFO 1
                     </p>
                  </td>
                  <td>
                     <p>
                        INFO 2
                     </p>
                  </td>
                  <td>
                     <p>
                        INFO 3
                     </p>
                  </td>
                  <td>
                     <p>
                        INFO 4
                     </p>
                  </td>
               </tr>
            </tbody>
         </table>
      </td>
   </tr>
   <tr>
      <td>
         <table> //table[1]//table[2]
            <tbody>
               <tr>
                  <td>
                     <p><strong>Name</strong></p>
                  </td>
                  <td>
                     <p><strong>Quantity</strong></p>
                  </td>
               </tr>
               <tr>
                  <td>
                     <p>Apples </p>
                  </td>
                  <td>10</td>
               </tr>
            </tbody>
         </table>
      </td>
   </tr>
   <tr>
      <td>
         <table>  //table[1]//table[3]
         </table>
      </td>
   </tr>
</tbody>
</table>

我正在尝试获取//table[1]//table[2]中的数据,但我仍然获得以下的空HtmlNode(System.NullReferenceException):

没有按&#39;吨&#39;工作: doc.DocumentNode.SelectSingleNode("//table[2]//tbody//tr//td//table[2]//tbody//tr");

我不确定为什么会出现这种情况,因为当我尝试获取//table[1]//table[1]的数据时,它可以正常使用此语法

有效: doc.DocumentNode.SelectSingleNode("//table[2]//tbody//tr//td//table[1]//tbody//tr");

我是否误解了索引如何与Html Agility Pack配合使用?

2 个答案:

答案 0 :(得分:1)

//table[2]返回同一个父中的第二个<table>元素,因为在XPath中:

  

[])的优先级(优先级)高于(///)。 [For Reference]

在您的情况下,每个<table>中只有一个<td>,因此Xpath表达式什么都没有返回。一种可能的解决方案是使用括号来改变优先级:

(//table[2]//tbody//tr//td//table)[2]//tbody//tr

在Xpath之上获取内部XPath <table>返回的所有<table>中的第二个//table[2]//tbody//tr//td//table元素。然后从<table>开始,继续返回后代//tbody//tr元素。

答案 1 :(得分:0)

我最终不得不以tr为基础,不知道为什么我的其他方式不起作用,但这种方式确实有效。

我基本上把我的索引移到了我桌子上方的下一个级别。因此,在第一个tbody之后,每个表都在tr / td语句中,我只是构建了我的HtmlNode来索引tr。如果扩大选择过程,Agility Pack可能会更好吗? IDK。

反正...

对于我使用的table[2]//table[1]

HtmlNode table = doc.DocumentNode.SelectSingleNode("//table[2]//tbody//tr[2]//table");
foreach (var cell in table.SelectNodes(".//tr//td/p"))
...

我选择了tr [2],因为如果你注意上面的HTML示例

,我之前有一个空白区域的tr / td

对于table[2]//table[2],我使用了

HtmlNode table = doc.DocumentNode.SelectSingleNode("//table[2]//tbody//tr[3]//table[1]");
foreach (var cell in table.SelectNodes(".//tr//td"))
...

对于任何有问题的人,请尝试将特定标记推广到更广泛的标记,从而将搜索范围扩大到更广泛的选择范围。