使用Html Agility Pack在两个HTML标记之间获取内容

时间:2012-05-29 22:13:22

标签: c# .net html-agility-pack

我们在Word中创建了一个绝对庞大的帮助文档,这个文档用于生成更大规模且不可靠的HTM文档。使用C#和这个库,我想只在我的应用程序中的任何一点抓取并显示该文件的一部分。部分分为这样:

<!--logical section starts here -->
<div>
<h1><span style='mso-spacerun:yes'></span><a name="_Toc325456104">Section A</a></h1>
</div>
 <div> Lots of unnecessary markup for simple formatting... </div>
 .....
<!--logical section ends here -->

<div>
<h1><span style='mso-spacerun:yes'></span><a name="_Toc325456104">Section B</a></h1>
</div>

从逻辑上讲,H1标记中有一个a部分名称。我想从包含div的外部选择所有内容,直到遇到另一个h1并排除该div。

  • 每个部分名称位于<a>下的h1标记下,该标记有多个子项(每个约6个)
  • 逻辑部分标有注释
  • 实际文件中不存在这些评论

我的尝试:

var startNode = helpDocument.DocumentNode.SelectSingleNode("//h1/a[contains(., '"+sectionName+"')]");
//go up one level from the a node to the h1 element
startNode=startNode.ParentNode;

//get the start index as the index of the div containing the h1 element
int startNodeIndex = startNode.ParentNode.ChildNodes.IndexOf(startNode);

//here I am not sure how to get the endNode location. 
var endNode =?;

int endNodeIndex = endNode.ParentNode.ChildNodes.IndexOf(endNode);

//select everything from the start index to the end index
var nodes = startNode.ParentNode.ChildNodes.Where((n, index) => index >= startNodeIndex && index <= endNodeIndex).Select(n => n);

正如我无法找到关于此的文档,我不知道如何从我的起始节点到下一个h1元素。任何建议将不胜感激。

2 个答案:

答案 0 :(得分:5)

我认为这样做会发生,但它假设H1标签只出现在节头中。如果不是这种情况,您可以在后代上添加Where以检查它找到的任何H1节点上的其他过滤器。请注意,这将包括它找到的div的所有兄弟节点,直到它到达具有节名称的下一个节点。

private List<HtmlNode> GetSection(HtmlDocument helpDocument, string SectionName)
{
    HtmlNode startNode = helpDocument.DocumentNode.Descendants("div").Where(d => d.InnerText.Equals(SectionName, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
    if (startNode == null)
        return null; // section not found

    List<HtmlNode> section = new List<HtmlNode>();
    HtmlNode sibling = startNode.NextSibling;
    while (sibling != null && sibling.Descendants("h1").Count() <= 0)
    {
        section.Add(sibling);
        sibling = sibling.NextSibling;
    }

    return section;
}

答案 1 :(得分:0)

那么,你真正想要的结果是h1-Tag周围的div? 如果是,那么这应该有效。

helpDocument.DocumentNode.SelectSingleNode("//h1/a[contains(@name, '"+sectionName+"')]/ancestor::div");

也适用于SelectNodes,具体取决于您的Html。 像这样:

helpDocument.DocumentNode.SelectNodes("//h1/a[starts-with(@name,'_Toc')]/ancestor::div");

哦,在测试这个时,我注意到对我来说不起作用的是contains方法中的点,一旦我将其更改为name属性,一切正常。