.NET 平台操作 XML 極為便利,但 C++ 標準庫缺乏原生支援。IBM XML4C (Xerces-C) 功能強大卻體積龐大(數 MB),且對 GB2312 編碼支援棘手。作者依據「功能最精簡、最實用、最常用」原則,自行實作一套僅含三個核心類別的輕量級解析器,專注於**解析、查找、DOM 樹建立**,不支援 XML 生成(建議直接字串拼接)。
| 類別 | 職責 | 關鍵成員 |
DOMElement | 節點類別 | tag、level、parent、childlist |
DOMDocument | 文件模型,管理 DOM 樹 | 解析邏輯、樹建立 |
CPacket | 對外門面,封裝操作介面 | 建樹、查找、建立節點、序列化輸出 |
核心 API 快速參考
1. 建立 DOM 樹
// 從字串解析
CPacket::BuiltTree(const char* pBuf, int nBufSize);
// 從檔案解析
CPacket::BuiltTree(LPCTSTR pXmlPath);
範例
CPacket inPacket;
DOMElement* node = nullptr;
inPacket.BuiltTree(strXml.c_str(), strXml.size()); // 字串
inPacket.BuiltTree(_T("c:\\1.xml")); // 檔案
2. 動態建立/插入節點
// 絕對路徑(從根節點):若中間節點不存在會自動建立
CPacket::CreateElement(_T("/Root/Cust/Tel"));
// 相對路徑(從當前節點):需先 SetCurrentElement
CPacket::CreateElement(_T("Root/Cust/Tel"));
3. 節點查找(四種模式)
// 一般查找,支援絕對/相對路徑
DOMElement* SearchElement(char* szNodeName);
// 指定屬性查找:如尋找 Id="1" 的 TelNum
DOMElement* SearchElement(char* szNodeName, char* szProp, char* szId);
// 遍歷同級節點(最快):參數決定是否移動當前指標
DOMElement* SearchNextElement(bool bMoveNext = TRUE);
// 結合名稱與屬性遍歷下一個匹配節點
DOMElement* SearchNextElement(char* szNodeName, char* szProp = NULL, char* szId = NULL);
完整使用範例
void main()
{
string strXml = "<Xml><Body><TelNums><TelNum Id='1'>123</TelNum><TelNum Id='2'>456</TelNum></TelNums></Body></Xml>";
CPacket inPacket;
DOMElement* pNode = nullptr;
inPacket.BuiltTree(strXml.c_str(), strXml.size());
printf("%s", inPacket.GetXml(NULL).c_str()); // 輸出完整 XML
// 1. 絕對路徑定位父節點
pNode = inPacket.SearchElement("/Xml/Body/TelNums/TelNum");
if (!pNode) return;
inPacket.SetCurrentElement(pNode);
// 2. 遍歷所有 TelNum 同級節點
while (pNode) {
printf("%s\n", pNode->getTextContent());
pNode = inPacket.SearchNextElement(true);
}
// 3. 重置至根節點,帶屬性查找
inPacket.ResetCurrentNode();
pNode = inPacket.SearchElement("TelNum", "Id", "1");
if (pNode) printf("Found: %s\n", pNode->getTextContent());
// 4. 建立新 XML 文件
CPacket outPacket;
outPacket.SetRootTag("Root");
DOMElement* pNew = outPacket.CreateElement("/Root/Cust/Tel");
pNew->setTextContent("075507895461");
printf("%s", outPacket.GetXml(NULL).c_str());
}
已知限制與注意事項
- 編碼支援以 ASCII/UTF-8 為主,中文編碼需自行測試。
- 無 DTD/Schema 驗證、無 XPath、無命名空間完整支援。
- 程式碼為早期作品,測試覆蓋率有限,生產環境建議改用成熟庫(TinyXML2, pugixml, RapidXML)。
- 作者聯絡:
mycrolee@163.com(原信箱 mycro@163.com 已失竊)。
結語
此解析器適合嵌入式、舊專案維護或教學理解 DOM 樹結構。現代 C++ 專案強烈建議採用標準化、高效能的開源替代方案。
- 上一篇文章: 介紹 VC 輔助開發工具 VcExtend
- 下一篇文章: VC++ 五大資料庫開發技術深度對比:ODBC、DAO、OLE DB、ADO 該怎麼選?
Copyright ©
程式碼之家 All Rights Reserved