Html agility xpath 获取以下节点如果
Html agility xpath get following node if
我有一个 html 文档结构如下:
<h3><a name="sect55">55</a></h3>
<p></p>
<p class="choice"><a href="#sect325"></a></p>
<h3><a name="sect56"></a></h3>
<p></p>
<p class="choice"><a href="#sect222"></a></p>
<h3><a name="sect57"></a></h3>
<p></p>
<p class="choice"><a href="#sect164"></a></p>
<p class="choice"><a href="#sect109"></a></p>
<p class="choice"><a href="#sect308"></a></p>
我想在一个单独的列表中检索所有节点,直到下一部分,所以直到下一部分 <h3>
。
目前我正在使用:
for (int paragraph = xx; paragraph <= yy; paragraph++)
{
nameActual = "sect" + paragraph;
nameNext = "sect" + (paragraph + 1);
HtmlNodeCollection NodeOfParagraph = doc.DocumentNode.SelectNodes(String.Format("//h3[a[@name='{0}']]/following-sibling::p[following::h3/a[@name='{1}']]", nameActual, nameNext));
//Multiples actions on my NodeOfParagraph
}
所以我 select 我的第一个 <h3>
拥有 <a>
我正在寻找的价值,然后我 select 所有 <p>
节点拥有我的下一个值 <a>
的后续节点。
它有效,但需要很长时间,我想是因为它会针对每个节点测试所有其他节点的值。
如何提高查询性能?
您可以执行以下操作:
- 找到所有部分定义并将它们存储在列表中
- 遍历节定义
- 并通过在查询中指定下一节的确切名称来获取本节与下一节(或文档末尾,如果没有更多节定义)之间的所有节点
var doc = new HtmlDocument();
doc.Load(@"path\to\file.html");
var sects = doc.DocumentNode.SelectNodes("//h3[a[starts-with(@name, 'sect')]]");
for (var index = 0; index < sects.Count; index ++)
{
var isLast = (index == sects.Count - 1);
var xpath = ".//following-sibling::p";
if (!isLast)
xpath += string.Format("[following-sibling::h3[1][a/@name = '{0}']]", sects[index + 1].SelectSingleNode("./a").Attributes["name"].Value);
var collection = sects[index].SelectNodes(xpath);
}
这样做的好处是:
- 不尝试查找不存在的节号
- 使用上下文节点(以
./
开始查询)以便不搜索文档中不必要的部分
- 停在下一个
h3
(h3[1]
),这样就不会搜索文档中不必要的部分
- 只搜索兄弟姐妹而不搜索后代(
following-sibling::
而不是 following::
)
我有一个 html 文档结构如下:
<h3><a name="sect55">55</a></h3>
<p></p>
<p class="choice"><a href="#sect325"></a></p>
<h3><a name="sect56"></a></h3>
<p></p>
<p class="choice"><a href="#sect222"></a></p>
<h3><a name="sect57"></a></h3>
<p></p>
<p class="choice"><a href="#sect164"></a></p>
<p class="choice"><a href="#sect109"></a></p>
<p class="choice"><a href="#sect308"></a></p>
我想在一个单独的列表中检索所有节点,直到下一部分,所以直到下一部分 <h3>
。
目前我正在使用:
for (int paragraph = xx; paragraph <= yy; paragraph++)
{
nameActual = "sect" + paragraph;
nameNext = "sect" + (paragraph + 1);
HtmlNodeCollection NodeOfParagraph = doc.DocumentNode.SelectNodes(String.Format("//h3[a[@name='{0}']]/following-sibling::p[following::h3/a[@name='{1}']]", nameActual, nameNext));
//Multiples actions on my NodeOfParagraph
}
所以我 select 我的第一个 <h3>
拥有 <a>
我正在寻找的价值,然后我 select 所有 <p>
节点拥有我的下一个值 <a>
的后续节点。
它有效,但需要很长时间,我想是因为它会针对每个节点测试所有其他节点的值。
如何提高查询性能?
您可以执行以下操作:
- 找到所有部分定义并将它们存储在列表中
- 遍历节定义
- 并通过在查询中指定下一节的确切名称来获取本节与下一节(或文档末尾,如果没有更多节定义)之间的所有节点
var doc = new HtmlDocument();
doc.Load(@"path\to\file.html");
var sects = doc.DocumentNode.SelectNodes("//h3[a[starts-with(@name, 'sect')]]");
for (var index = 0; index < sects.Count; index ++)
{
var isLast = (index == sects.Count - 1);
var xpath = ".//following-sibling::p";
if (!isLast)
xpath += string.Format("[following-sibling::h3[1][a/@name = '{0}']]", sects[index + 1].SelectSingleNode("./a").Attributes["name"].Value);
var collection = sects[index].SelectNodes(xpath);
}
这样做的好处是:
- 不尝试查找不存在的节号
- 使用上下文节点(以
./
开始查询)以便不搜索文档中不必要的部分 - 停在下一个
h3
(h3[1]
),这样就不会搜索文档中不必要的部分 - 只搜索兄弟姐妹而不搜索后代(
following-sibling::
而不是following::
)