0

我正在使用 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 等),计算每个节点的深度,并将值存储在 Dictionary 或类似物中。
  • node.ParentNode通过计数直到body达到“按需”计算每个节点的深度。

有没有办法通过使用 HtmlAgilityPack 收集的现有数据来避免这些Load

4

3 回答 3

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属性更容易。

于 2012-07-30T14:53:31.387 回答
1

你问是否有内置的NodeDepth财产或类似的东西?我很确定答案是否定的,因为计算库解析的每个节点都会产生很少得到保证的开销。由于计算节点深度很容易通过一些递归来完成,我认为他们不会在默认情况下包含它。

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

于 2012-07-30T07:33:04.897 回答
0

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

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

它应该工作。

于 2014-10-31T06:06:16.773 回答