我正在尝试从此布局中的表中选择元素:
<tbody>
<tr class="header">
<th colspan="4">Tier 1</th>
</tr>
<tr>
<td><a>First Thing</a></td>
<td><a>Second Thing</a></td>
<td><a>Third Thing</a></td>
<td></td>
</tr>
<tr>
<td><a>Fourth Thing</a></td>
<td><a>Fifth Thing</a></td>
<td><a>Sixth Thing</a></td>
<td></td>
</tr>
<tr class="header">
<th colspan="4">Tier 2</th>
</tr>
<tr>
<td><a>First Thing</a></td>
<td><a>Second Thing</a></td>
<td><a>Third Thing</a></td>
<td></td>
</tr>
<tr>
<td><a>Fourth Thing</a></td>
<td><a>Fifth Thing</a></td>
<td><a>Sixth Thing</a></td>
<td></td>
</tr>
我想选择&#34; tr class = header&#34;之间的所有值。标签。我需要这样做5次(实际桌子上有6层,这里没有列出,因为它太长了)然后最后我需要从最后一个标题中选择到桌子的底部。
我应该指出,我在C#MVC中使用Agility Pack,所以xpaths似乎是要走的路
到目前为止,我已经能够使用&#34; // tr [@class =&#39; header&#39;] // th&#34;来隔离标题。
主要问题似乎是我想要的节点是彼此的兄弟姐妹,而不是那些会使遍历变得容易的孩子。
最终游戏是我想在我的数据结构中为所有第1层元素赋值1,所有第2层元素值为2等,以便以后进行比较。
答案 0 :(得分:1)
首先 - 你需要扩展方法来按层分割行:
public static IEnumerable<IEnumerable<T>> SplitBy<T>(
this IEnumerable<T> source, Func<T, bool> separator)
{
List<T> batch = new List<T>();
using (var iterator = source.GetEnumerator())
{
while (iterator.MoveNext())
{
if (separator(iterator.Current) && batch.Any())
{
yield return batch;
batch = new List<T>();
}
batch.Add(iterator.Current);
}
}
if (batch.Any())
yield return batch;
}
现在第一步将是查询层(每个层将包含几个tr
个节点):
HtmlDocument doc = new HtmlDocument();
doc.Load(path_to_html);
var tiers = doc.DocumentNode.SelectNodes("//tr")
.SplitBy(tr => tr.HasAttributes &&
tr.Attributes["class"].Value == "header");
第二步是从每一层提取数据
var result = from t in tiers
let tier = t.First().SelectSingleNode("th").InnerText
from a in t.Skip(1).SelectMany(tr => tr.SelectNodes("td/a"))
select new {
Tier = tier,
Value = a.InnerText
};
结果是
[
{ Tier: "Tier 1", Value: "First Thing" },
{ Tier: "Tier 1", Value: "Second Thing" },
{ Tier: "Tier 1", Value: "Third Thing" },
{ Tier: "Tier 1", Value: "Fourth Thing" },
{ Tier: "Tier 1", Value: "Fifth Thing" },
{ Tier: "Tier 1", Value: "Sixth Thing" },
{ Tier: "Tier 2", Value: "First Thing" },
{ Tier: "Tier 2", Value: "Second Thing" },
{ Tier: "Tier 2", Value: "Third Thing" },
{ Tier: "Tier 2", Value: "Fourth Thing" },
{ Tier: "Tier 2", Value: "Fifth Thing" },
{ Tier: "Tier 2", Value: "Sixth Thing" }
]