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

C# 開發 RSS 新聞閱讀器完整教學:XML 解析與 TreeView 顯示

     編輯:關於C語言

專案目標

建立一個 Windows Forms 應用程式,輸入 RSS 連結,解析 XML 內容,以樹狀結構顯示頻道標題與新聞項目,點選新聞標題自動開啟瀏覽器跳轉原文連結。

RSS 結構分析

標準 RSS 2.0 架構:

<rss version="2.0">
  <channel>
    <title>頻道名稱</title>
    <link>頻道連結</link>
    <description>頻道描述</description>
    <item>
      <title>新聞標題</title>
      <link>新聞連結</link>
      <description>新聞摘要</description>
      <pubDate>發布時間</pubDate>
    </item>
    ... 多個 item ...
  </channel>
</rss>

資料模型設計

public class RssFeed
{
    public Channel Channel { get; set; }
}

public class Channel
{
    public string Title { get; set; }
    public string Link { get; set; }
    public string Description { get; set; }
    public List<Item> Items { get; set; } = new List<Item>();
}

public class Item
{
    public string Title { get; set; }
    public string Link { get; set; }
    public string Description { get; set; }
    public DateTime PubDate { get; set; }
}

採用強型別類別取代原文 struct + Hashtable,支援 LINQ 查詢與資料繫結。

UI 佈局

  • TextBox txtUrl:輸入 RSS 連結
  • Button btnLoad:觸發載入
  • TreeView tvRss:顯示頻道與新聞階層
  • WebBrowser / Label:(選用) 顯示新聞摘要

核心解析邏輯

使用 XmlDocument 載入與查詢

private RssFeed LoadRssFeed(string url)
{
    var feed = new RssFeed();
    var doc = new XmlDocument();
    doc.Load(url); // 直接支援 http/https

    XmlNode channelNode = doc.SelectSingleNode("/rss/channel");
    if (channelNode == null) throw new Exception("無效的 RSS 格式");

    feed.Channel = new Channel
    {
        Title = channelNode.SelectSingleNode("title")?.InnerText ?? "",
        Link = channelNode.SelectSingleNode("link")?.InnerText ?? "",
        Description = channelNode.SelectSingleNode("description")?.InnerText ?? ""
    };

    foreach (XmlNode itemNode in channelNode.SelectNodes("item"))
    {
        feed.Channel.Items.Add(new Item
        {
            Title = itemNode.SelectSingleNode("title")?.InnerText ?? "",
            Link = itemNode.SelectSingleNode("link")?.InnerText ?? "",
            Description = itemNode.SelectSingleNode("description")?.InnerText ?? "",
            PubDate = DateTime.TryParse(itemNode.SelectSingleNode("pubDate")?.InnerText, out var dt) ? dt : DateTime.MinValue
        });
    }
    return feed;
}
  • XmlDocument.Load(string) 直接支援 URL,內部自動處理 HTTP 請求。
  • SelectSingleNode/SelectNodes 使用 XPath,程式碼簡潔且容錯 (節點不存在回傳 null)。

綁定至 TreeView

private void BindToTreeView(RssFeed feed)
{
    tvRss.BeginUpdate();
    tvRss.Nodes.Clear();

    var channelNode = new TreeNode(feed.Channel.Title) { Tag = feed.Channel.Link };
    tvRss.Nodes.Add(channelNode);

    foreach (var item in feed.Channel.Items)
    {
        var itemNode = new TreeNode(item.Title)
        {
            Tag = item.Link,           // 儲存連結供點選時使用
            ToolTipText = item.Description // 滑鼠停留顯示摘要
        };
        channelNode.Nodes.Add(itemNode);
    }

    channelNode.ExpandAll();
    tvRss.EndUpdate();
}

節點點選開啟瀏覽器

private void tvRss_AfterSelect(object sender, TreeViewEventArgs e)
{
    if (e.Node.Tag is string url && Uri.IsWellFormedUriString(url, UriKind.Absolute))
    {
        try { Process.Start(new ProcessStartInfo(url) { UseShellExecute = true }); }
        catch (Exception ex) { MessageBox.Show($"無法開啟連結: {ex.Message}"); }
    }
}

UseShellExecute = true 確保使用系統預設瀏覽器,支援 .NET Core / .NET 5+。

完整表單程式碼

public partial class MainForm : Form
{
    public MainForm() { InitializeComponent(); }

    private async void btnLoad_Click(object sender, EventArgs e)
    {
        string url = txtUrl.Text.Trim();
        if (string.IsNullOrEmpty(url)) return;

        btnLoad.Enabled = false;
        Cursor = Cursors.WaitCursor;

        try
        {
            // 非同步載入避免 UI 凍結
            var feed = await Task.Run(() => LoadRssFeed(url));
            BindToTreeView(feed);
        }
        catch (Exception ex)
        {
            MessageBox.Show($"載入失敗: {ex.Message}", "錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        finally
        {
            btnLoad.Enabled = true;
            Cursor = Cursors.Default;
        }
    }

    // ... LoadRssFeed, BindToTreeView, tvRss_AfterSelect 方法
}

常見問題與解決方案

問題原因解決
載入時 UI 凍結同步網路 I/O 阻塞 UI 執行緒使用 Task.Run + await 非同步載入
中文顯示亂碼RSS 未宣告 encoding 或編碼不符XmlDocument 自動偵測 BOM/宣告;若失敗可先 HttpClient 下載字串指定 Encoding.UTF8 再 LoadXml
部分節點缺失RSS 格式不標準 (如 Atom、RDF)擴充解析邏輯支援多種命名空間,或改用 SyndicationFeed (.NET Framework 內建)
HTTPS 憑證錯誤伺服器憑證不受信任開發環境可暫時忽略:ServicePointManager.ServerCertificateValidationCallback = (a,b,c,d) => true;

擴充功能建議

  • 加入 ContextMenuStrip:右鍵複製連結、標記已讀、匯出 OPML。
  • 整合 WebView2 控制項:應用程式內直接瀏覽全文。
  • 本地快取:使用 SQLite 或 JSON 儲存已讀狀態與離線閱讀。
  • 定時自動重新整理:Timer 背景檢查新文章並通知 (Toast/系統匣)。

參考資源

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved