使用HTMLAgilityPack选择所有DOM元素

时间:2014-03-21 22:38:25

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

我一直在寻找类似的问题并在线搜索,但我似乎无法找到解决方案。我要做的是按顺序选择所有DOM元素(等),然后将它们放入arraylist或其他东西。

目前我有

public void Parse()
    {
        HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();

        // There are various options, set as needed
        //htmlDoc.OptionFixNestedTags = true;

        // filePath is a path to a file containing the html
        htmlDoc.Load("Test.html");

        // Use:  htmlDoc.LoadHtml(xmlString);  to load from a string (was htmlDoc.LoadXML(xmlString)

        // ParseErrors is an ArrayList containing any errors from the Load statement
        if (htmlDoc.ParseErrors != null && htmlDoc.ParseErrors.Count() > 0)
        {
            Console.WriteLine("There was an error parsing the HTML file");
        }
        else
        {
            if (htmlDoc.DocumentNode != null)
            {
                htmlDoc.DocumentNode.Descendants();

                Console.WriteLine("document node not null");
                //HtmlAgilityPack.HtmlNode bodyNode = htmlDoc.DocumentNode.SelectSingleNode("//body");

                foreach (HtmlNode node in htmlDoc.DocumentNode.Descendants())
                {
                    Console.WriteLine(node.Name);
                }
            }
        }
    }

代码输出节点的名称(html,title,image等),但它将结束标记输出为“#text”。我认为这是因为标签以“/”开头如何才能正确读出所有DOM元素?

2 个答案:

答案 0 :(得分:1)

我怀疑你看到的#text元素是换行符而不是结束标记。例如这个html输入:

<div>
    <a href="http://example.org"></a>
</div>

使用您的代码将输出:

div
#text   <- line break between <div> and <a>
a
#text  <- line break between </a> and </div>

您可以使用此XPath查询来获取那些不是纯文本节点的元素(跳过那些不必要的换行符):

foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//*"))
{
    Console.WriteLine(node.Name);
}

XPath意味着,选择具有任何名称(*)的当前元素的所有后代。

答案 1 :(得分:0)

“#text”是文本节点的名称,而结束标记不表示为DOM中的任何唯一标识。

<div><span>foo</span> bar</div>

会给你一棵树

div
   span
      #text:foo
   #text:bar