首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 解析 HTML 產生 DOM TreeView:使用 MSHTML 遞迴建構樹狀結構

     編輯:關於C語言

需求背景

在開發瀏覽器嵌入應用、HTML 編輯器、爬蟲分析工具時,常需將 HTML 文件的 DOM 結構視覺化為 TreeView。本文示範使用 mshtml (Microsoft HTML Object Library) 走訪 DOM 節點,遞迴建構 Windows Forms TreeView。

核心實作

using System;
using System.Windows.Forms;
using mshtml; // 參考: Microsoft HTML Object Library
using AxSHDocVw; // WebBrowser ActiveX

public class DomTreeBuilder
{
    private TreeView _treeView;
    private string _pathString = "0";

    public DomTreeBuilder(TreeView treeView)
    {
        _treeView = treeView;
    }

    // 遞迴插入 DOM 節點
    private void InsertDomNodes(IHTMLDOMNode parentNode, TreeNode treeNode)
    {
        if (!parentNode.hasChildNodes()) return;

        IHTMLDOMChildrenCollection children = (IHTMLDOMChildrenCollection)parentNode.childNodes;
        int siblingIndex = 0;

        for (int i = 0; i < children.length; i++)
        {
            IHTMLDOMNode childNode = (IHTMLDOMNode)children.item(i);
            string nodePath = _pathString + "," + siblingIndex++;
            
            TreeNode childTreeNode = treeNode.Nodes.Add($"{childNode.nodeName}_{nodePath}");
            
            string prevPath = _pathString;
            _pathString = nodePath;
            InsertDomNodes(childNode, childTreeNode);
            _pathString = prevPath;
        }
    }

    // WebBrowser DocumentComplete 事件處理
    public void OnDocumentComplete(object sender, DWebBrowserEvents2_DocumentCompleteEvent e)
    {
        _pathString = "0";
        _treeView.Nodes.Clear();

        IHTMLDocument3 doc = (IHTMLDocument3)((WebBrowser)sender).Document.DomDocument;
        IHTMLDOMNode rootDomNode = (IHTMLDOMNode)doc.documentElement;

        TreeNode root = _treeView.Nodes.Add($"HTML_{_pathString}");
        InsertDomNodes(rootDomNode, root);
        _treeView.ExpandAll();
    }
}

介面說明

介面用途
IHTMLDOMNodeDOM 節點基底介面,提供 nodeName、childNodes、hasChildNodes()
IHTMLDOMChildrenCollection子節點集合,支援 length、item(index)
IHTMLDocument3文件介面,提供 documentElement (根元素 <html>)

使用方式

public partial class MainForm : Form
{
    private DomTreeBuilder _builder;

    public MainForm()
    {
        InitializeComponent();
        _builder = new DomTreeBuilder(domTreeView);
        webBrowser.DocumentCompleted += _builder.OnDocumentComplete;
    }

    private void btnNavigate_Click(object sender, EventArgs e)
    {
        webBrowser.Navigate("https://example.com");
    }
}

節點類型識別

nodeName 回傳值對照:

  • 元素節點:標籤名(如 "DIV"、"A"、"IMG")
  • 文字節點:"#text"
  • 註解節點:"#comment"
  • 文件節點:"#document"
  • Doctype:"DOCTYPE"

進階擴充:顯示屬性與樣式

private void InsertDomNodes(IHTMLDOMNode parentNode, TreeNode treeNode)
{
    if (!parentNode.hasChildNodes()) return;

    var children = (IHTMLDOMChildrenCollection)parentNode.childNodes;
    for (int i = 0; i < children.length; i++)
    {
        var child = (IHTMLDOMNode)children.item(i);
        string displayName = child.nodeName;

        // 若為元素節點,顯示 id/class
        if (child.nodeType == 1) // NodeType.Element
        {
            var elem = (IHTMLElement)child;
            if (!string.IsNullOrEmpty(elem.id)) displayName += $" id={elem.id}";
            if (!string.IsNullOrEmpty(elem.className)) displayName += $" class={elem.className}";
        }
        // 文字節點顯示前 30 字
        else if (child.nodeType == 3) // NodeType.Text
        {
            string text = child.nodeValue?.Trim();
            if (!string.IsNullOrEmpty(text))
                displayName += $": \"{text.Substring(0, Math.Min(30, text.Length))}...\"";
        }

        TreeNode tn = treeNode.Nodes.Add(displayName);
        InsertDomNodes(child, tn);
    }
}

現代替代方案

AngleSharp + WPF TreeView

using AngleSharp.Dom;
using AngleSharp.Html.Parser;

public void BuildTree(IElement element, TreeViewItem parent)
{
    var item = new TreeViewItem { Header = element.TagName };
    parent.Items.Add(item);

    foreach (var child in element.ChildNodes)
    {
        if (child is IElement el) BuildTree(el, item);
        else if (child is IText txt && !string.IsNullOrWhiteSpace(txt.Text))
            item.Items.Add(new TreeViewItem { Header = $"#text: {txt.Text.Substring(0, 30)}" });
    }
}

// 使用
var parser = new HtmlParser();
var doc = await parser.ParseDocumentAsync(htmlString);
BuildTree(doc.DocumentElement, treeViewRoot);

部署提醒

  • mshtml.dll 需目標機器安裝 IE 或 Edge (IE 模式)
  • 專案勾選 Embed Interop Types = True 可避免部署 Primary Interop Assembly
  • 64 位元應用需確認 mshtml 為 64 位元版本,或設定 Prefer 32-bit
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved