如何在不指定节点名称的情况下遍历所有节点

时间:2015-10-09 07:05:41

标签: c# html html-agility-pack

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

我一直在做一些研究,但是没有找到解决方案,我可以在不必指定节点名称的情况下浏览整个文档中的所有父节点和子节点。

我想这样做是因为我将使用不同的html文档,因此此时指定节点名称不适合我。

4 个答案:

答案 0 :(得分:4)

我现在想出来了... omg它开始时很简单,因为我不知道如何使用这些功能

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);
        }
    }
}

答案 1 :(得分:3)

您可以使用以下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

答案 2 :(得分:2)

您还可以找到所有这样的节点:

string fsURLAddress = "http://www.external-url-sample.com/";

var loHtmlDocument = new HtmlWeb().Load(fsURLAddress);

var loHTMLNodeList = loHtmlDocument.DocumentNode.Descendants().ToList();

答案 3 :(得分:0)

基于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();
        }
    });

此示例删除了所有<script>标签及其子标签。

可以将扩展方法增强为不仅可以使用Action<HtmlNode>,还可以使用Func<HtmlNode, bool>来使委托在返回false后立即停止迭代。