我有当前的HTML布局
<table> //table[1]
</table>
<table> //table[2]
<tbody>
<tr>
<td>
<p>
</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配合使用?
答案 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"))
...
对于任何有问题的人,请尝试将特定标记推广到更广泛的标记,从而将搜索范围扩大到更广泛的选择范围。