【问题标题】:How to loop through all nodes without specifying node names如何在不指定节点名称的情况下遍历所有节点
【发布时间】:2016-01-07 00:44:20
【问题描述】:

我正在尝试从任何 html 文档的所有 htmlDocument 节点中获取所有 innerText。

我一直在做一些研究,但还没有找到一个解决方案来解决我如何能够遍历整个文档中的所有父节点和子节点而不必指定节点名称。

我想这样做是因为我将使用不同的 html 文档,因此此时指定节点名称对我来说不是一个选项。

【问题讨论】:

    标签: c# html html-agility-pack


    【解决方案1】:

    基于Photonic's answer,我快速搭建了一个扩展方法:

    public static class HtmlAgilityPackExtensions
    {
        public static void IterateAllNodes(
            this HtmlDocument doc, Action<HtmlNode> action)
        {
            foreach (var n in doc.DocumentNode.ChildNodes)
            {
                doIterateNode(n, action);
            }
        }
    
        private static void doIterateNode(HtmlNode node, Action<HtmlNode> action)
        {
            action?.Invoke(node);
    
            foreach (var n in node.ChildNodes)
            {
                if (n.HasChildNodes)
                {
                    doIterateNode(n, action);
                }
            }
        }
    }
    

    示例用法:

    doc.IterateAllNodes(
        node =>
        {
            if (node.Name.Equals(@"script", StringComparison.OrdinalIgnoreCase))
            {
                node.Remove();
            }
        });
    

    此示例删除所有 &lt;script&gt; 标记及其子标记。

    可以增强扩展方法,使其不仅可以使用Action&lt;HtmlNode&gt;,还可以使用Func&lt;HtmlNode, bool&gt;,以允许代理在返回false 后立即停止迭代。

    【讨论】:

      【解决方案2】:

      你也可以像这样找到所有节点:

      string fsURLAddress = "http://www.external-url-sample.com/";
      
      var loHtmlDocument = new HtmlWeb().Load(fsURLAddress);
      
      var loHTMLNodeList = loHtmlDocument.DocumentNode.Descendants().ToList();
      

      【讨论】:

        【解决方案3】:

        我现在想通了……天哪,开始太简单了,因为我不知道如何使用这些功能

        HtmlDocument htmlDoc = new HtmlDocument();
        htmlDoc.Load(MyIO.bingPathToAppDir("Test data/testHTML.html"));
        HtmlNode j = htmlDoc.DocumentNode;
        foreach (HtmlNode node in j.ChildNodes)
        {
            checkNode(node);
        }
        
        static void checkNode(HtmlNode node)
        {
            foreach (HtmlNode n in node.ChildNodes)
            {
                if (n.HasChildNodes)
                {
                    checkNode(n);
                }
                else
                {
                    Console.WriteLine(n.InnerText);
                }
            }
        }
        

        【讨论】:

          【解决方案4】:

          您可以使用以下 XPath 表达式从任意 HTML 文档中获取所有非空文本节点,而无需知道文档结构:

          //text()[normalize-space()]
          

          完整的工作控制台应用程序演示:

          var html = @"<p>
             <span>a1</span>
             <span>a2</span>
             <span>b1</span>
             <span>b2</span>
          </p>";
          var doc = new HtmlDocument();
          doc.LoadHtml(html);
          var result = doc.DocumentNode.SelectNodes("//text()[normalize-space()]");
          foreach (var r in result)
          {
              Console.WriteLine(r.InnerText);
          }
          

          Dotnetfiddle Demo

          输出:

          a1
          a2
          b1
          b2
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-01-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-08-28
            相关资源
            最近更新 更多