如何在HTML树中获取节点的深度?

时间:2012-07-30 07:28:53

标签: html tree html-agility-pack

我正在使用HtmlAgilityPack来解析和分析HTML页面,我需要知道每个节点的“深度” - 距Body节点的距离。示例(“深度”属性仅用于说明目的):

<html>
  <head></head>
  <body depth="0"> 
    <div depth="1">
      <ul depth="2">
        <li depth="3">
          <p depth="4">foo</p>
        </li>
        <li depth="3">
          <p depth="4">bar</p>
        </li>
      </ul>
    </div>
  </body>
</html>

我正试图避免两个明显的解决方案:

  • 扫描HTML树(DFS,BFS等),计算每个节点的深度,并将值存储在字典或类似字体中。
  • 通过计算node.ParentNode直到达到body来“按需”计算每个节点的深度。

有没有办法通过某种方式使用HtmlAgilityPack在Load收集的现有数据来避免这些?

3 个答案:

答案 0 :(得分:3)

据我所知,AgilityPack不存储节点的深度。

如果你想得到所有节点的深度,假设它更容易编写,例如从根节点开始并通过递归调用当前节点子节点来增加深度的递归方法。

对于单个节点的深度计算,您可以使用HtmlNode.XPath属性,并计算此值中的斜杠数(/)。这将是节点深度。在您的情况下,您应首先计算<body>节点的深度,然后从愿望节点的深度中减去此值以获得相对深度

var bodyDepth = doc.DocumentNode
    .SelectSingleNode("//body")
    .XPath
    .Count(c => c == '/');
var paragraphDepth = doc.DocumentNode
    .SelectSingleNode("//p")
    .XPath
    .Count(c => c == '/');
var result = paragraphDepth - bodyDepth;

这会给你4,但我不确定这比迭代ParentNode属性更容易。

答案 1 :(得分:1)

您在询问是否有内置NodeDepth属性或类似内容?我非常肯定答案是否定的,因为计算出由库解析的每个节点都会产生很少需要保证的开销。由于通过一些递归很容易计算节点深度,我认为它们不会包含默认值。

为什么要避免使用明显的解决方案?

答案 2 :(得分:0)

HtmlAgilityPack不会给出深度细节。我们可以使用&#39; /&#39;的计数从XPath变量中获取它。上面提供的字符。我们不需要遍历父母以获取详细信息。

 foreach (HtmlNode rootNode in document.DocumentNode.Descendants())
            {
                levels.Add(rootNode.XPath.Count(x => x == '/'));
            }

它应该有用。