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

C++Builder 6 中掌握 XML 操作:從 DOM 解析到實戰應用

     編輯:VC 教學

前言:為何 XML 在 C++Builder 中顯得「難用」?

許多開發者初次接觸 C++Builder 的 TXMLDocument 組件時,都會感到困惑:明明 VB / C# 操作 MSXML DOM 極為順手,為何在 C++Builder 中卻處處碰壁?核心原因在於思維慣性——VCL 的類設計直觀易懂,而 MSXML 是基於 COM 的介面導向模型,方法命名、錯誤處理、生命週期管理與 VCL 風格截然不同。本文將以一個「日程提醒」小程式為例,手把手帶你跨過這道坎。

一、XML 解析模型選擇:SAX vs DOM

  • SAX (Simple API for XML):事件驅動、單向流式讀取,記憶體佔用極低,適合超大文件,但無法隨機存取、修改困難。
  • DOM (Document Object Model):一次性將整個 XML 載入記憶體構建樹狀結構,支援隨機存取、增刪改查,適合中小型配置文件。C++Builder 的 TXMLDocument 正是封裝 MSXML DOM 實現。

二、範例 XML 結構設計

<?xml version="1.0" encoding="GB2312"?>
<VTip>
  <Tip>
    <Mode>0</Mode>
    <Time>2003/4/25 08:01:46</Time>
    <Content>洗衣服</Content>
  </Tip>
  <Tip>
    <Mode>1</Mode>
    <Time>2003/4/25 17:30:00</Time>
    <Content>陪女朋友吃飯</Content>
  </Tip>
</VTip>

採用 GB2312 編碼避免中文亂碼;結構扁平化,無屬性、無命名空間,降低解析複雜度。

三、核心操作完整代碼實現

1. 載入與啟動文件

// XMLDoc 為 TXMLDocument 元件實例
XMLDoc->LoadFromFile(WideString(ExtractFilePath(Application->ExeName) + "Tip.xml"));
XMLDoc->Active = true;
FillList(); // 刷新 UI 列表

2. 讀取並填充 ListView (FillList)

void __fastcall TfrmMain::FillList()
{
    lstMain->Items->BeginUpdate();
    lstMain->Items->Clear();

    _di_IXMLNode root = XMLDoc->DocumentElement; // 取得根節點 <VTip>
    _di_IXMLNodeList tips = root->ChildNodes;    // 取得所有 <Tip> 節點集合

    for (int i = 0; i < tips->Count; ++i) {
        _di_IXMLNode tip = tips->Get(i);         // 第 i 個 <Tip>
        _di_IXMLNodeList fields = tip->ChildNodes; // Mode, Time, Content

        TListItem *item = lstMain->Items->Add();
        item->Caption = "";
        item->ImageIndex = fields->Get(0)->GetText().ToInt() + 5; // Mode 決定圖示
        item->SubItems->Add(fields->Get(1)->GetText());           // Time
        item->SubItems->Add(fields->Get(2)->GetText());           // Content
    }
    lstMain->Items->EndUpdate();
}

關鍵點:_di_IXMLNode 是介面智慧指標,自動管理參考計數,無需手動 Release;ChildNodes 返回 IXMLNodeList,支援索引與迭代。

3. 新增任務節點

bool __fastcall TfrmMain::AddTask(int mode, TDateTime &date, TDateTime &time, AnsiString content)
{
    _di_IXMLNode root = XMLDoc->DocumentElement;
    _di_IXMLNode tip = root->AddChild("Tip");           // 建立 <Tip>

    _di_IXMLNode n = tip->AddChild("Mode");
    n->SetText(WideString(mode));

    n = tip->AddChild("Time");
    n->SetText(WideString(date.DateString() + " " + time.TimeString()));

    n = tip->AddChild("Content");
    n->SetText(WideString(content));

    return true; // 記得稍後呼叫 XMLDoc->SaveToFile() 持久化
}

4. 刪除指定節點

void __fastcall TfrmMain::DeleteSelected()
{
    int idx = lstMain->Selected->Index;
    _di_IXMLNode root = XMLDoc->DocumentElement;
    if (root->ChildNodes->Delete(idx) != -1) { // 返回被刪除節點索引,-1 表示失敗
        lstMain->Items->Delete(idx);           // 同步更新 UI
    }
}

四、常見坑點與最佳實踐

  1. 編碼一致性:XML 宣告編碼、原始碼檔案編碼、資料庫/檔案實際編碼必須三統一,建議統一用 UTF-8 並加 BOM。
  2. 介面指標生命週期:_di_IXMLNode 離開作用域自動釋放,切勿手動 Release() 或轉為裸指標長期持有。
  3. 命名空間處理:若 XML 帶命名空間,需用 AddChildNS、GetChildNodes 等帶 NS 後綴的方法。
  4. 大文件效能:超過 10MB 建議改用 SAX 或 IXMLReader 流式讀取。
  5. 錯誤處理:所有 DOM 操作皆可能拋出 EXMLDocError,外層務必 try/__finally 保護。

五、進階:持久化與多執行緒

// 儲存變更
XMLDoc->SaveToFile(WideString(ExtractFilePath(Application->ExeName) + "Tip.xml"));

// 多執行緒安全:每個執行緒建立獨立 TXMLDocument 實例,或使用 Critical Section 保護共用實例
// MSXML DOM 物件本身非執行緒安全(Free-threaded Marshaler 除外)

六、總結

掌握 TXMLDocument 核心在於理解「介面導向」與「樹狀節點操作」兩大思維。通過本文的完整增刪改查範例,你已具備在 C++Builder 中駕馭 XML 配置文件、資料交換的實戰能力。下一步可嘗試 XPath 查詢、XSLT 轉換或 Schema 驗證,進一步釋放 XML 的威力。

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