今天有點郁悶,不想干活。整理代碼的時候,看到了這個好久之前寫的代碼,於是想整理 出來供大家拍磚。XML的解析對於.Net平台那真是太簡單不過了,感謝微軟。但對於C++語言 的XML解析就沒那麼容易了。有一個開源的XML4C是IBM的,功能強大,但代碼大的有幾M,而且 對於GB2312的支持有問題,據說能解決,但可能是我天生愚鈍,當初我花了2周時間也沒搞定 ,最後放棄,自己寫了一個。咦?還能跑起來,也能跨平台:)。 寫這個XML解析類,以功能 最簡單,最實用,最常用的功能為原則,因為只能解析,查找,沒有XML文檔生成器。如果需 要生成XMl文檔,還是自己拼湊字串吧。
此解析器的接口完全模仿XML4C的對外接 口,使用也很類似,稍有不同,對復雜部分進行了封裝。總共分3個類: CPacket、 DOMElement、DOMDocument。 DOMElement為節點類,主有有tag、level、 parent、childlist 等幾個屬性。DOMElement類主要是對XML文檔的解析,生成,對整個XML文檔 生成DOM樹。 CPacket主要是對XML文檔的封裝,提供對外的接口。
下面簡單示例一下使用方法:
1、創建DOM樹,得到XML對象:
解析分兩種,第一種是對xml string 字串的解 析,另一種是對文件的解析。對應函數分別為:
CPacket::BuiltTree(const char* pBuf,int nBufSize);
CPacket::BuiltTree(MLPCSTR pXmlPath);
使 用示例:
CPacket inPacket;
DOMElement* TransNode = NULL;
DOMElement* AccNode = NULL;
inPacket.BuiltTree(strXml.c_str (),strXml.size()); //生成DOM樹結構.
inPacket.BuiltTree ("c:\\1.xml"); //生成DOM樹結構.
2、對原有DOM 樹添加子結點:
可以通過CPacket::CreateElement(char szNodeName[]) 來創建字節點, 示例:
(1)CPacket::CreateElement("/Root/Cust/Tel")
會在 根節點下創建Root/Cust/Tel 如果存在Root和Cust節點了則不在創建,否則會創建3個節 點,Root,Cust,Tel 並且具有父子關系。
(2)CPacket::CreateElement ("Root/Cust/Tel")
會在當前節點下創建Root,Cust,Tel,至於當前節點 ,可以通過SetCurrentElement 來設置,默認根節點是當前節點.
3、節點的查找,節點的查 找,有4個函數可以用:
CPacket::SearchElement(char * szNodeName); //搜索普通節點,分絕對路徑(路徑以/開頭),相對路徑
CPacket::SearchElement(char * szNodeName,char * szProper,char * szId); //指定屬 性
CPacket::SearchNextElement(bool pMoveNext = TRUE); //當前節 點的下一個兄弟節點,參數決定向下移動當前節點,這個函數速度最快
CPacket::SearchNextElement(char *szNodeName,char *szProper = NULL,char *szId = NULL); //下一個節點
整體使用示例:
void main()
{
string strXml = "";
CPacket inPacket;
DOMElement* TransNode = NULL;
DOMElement* AccNode = NULL;
inPacket.BuiltTree (strXml.c_str(),strXml.size()); //生成DOM樹結構.
printf("% s",inPacket.GetXml(NULL).c_str());
//MessageBox(inPacket.GetXml (NULL).c_str());
AccNode = inPacket.SearchElement ("/Xml/Body/TelNums/TelNum");
if(!AccNode)
return;
inPacket.SetCurrentElement(AccNode);
while (AccNode)
{
printf("%s",AccNode->getTextContent ());
MessageBox(AccNode->getTextContent());
AccNode = inPacket.SearchNextElement(true);
}
//注意因為當前節點已經 不是根節點,因此如果是全局查找就要在節點名前加上"/" 的全局路徑
//AccNode = inPacket.SearchElement ("/TelNum","Id","1");
inPacket.ResetCurrentNode();
AccNode = inPacket.SearchElement ("TelNum","Id","1");
printf("% s",AccNode->getTextContent());
//MessageBox(AccNode- >getTextContent());
//創建XML文檔
CPacket outPacket;
outPacket.SetRootTag("Root");
AccNode = outPacket.CreateElement("/Root/Cust/Tel");
AccNode- >setTextContent("075507895461");
printf("% s",outPacket.GetXml(NULL).c_str());
//MessageBox(outPacket.GetXml (NULL).c_str());
}
當時寫的時候僅僅是為了滿足我自己使用的方 便,很多復雜功能沒有實現,代碼測試也遠遠不夠,問題很多,真有點怕誤導大家,希望大 家看後,能夠重新寫一份出來,供大家使用,有問題發郵件給我:[email protected] 原來的郵 箱[email protected] 被一個LJ給盜了。永遠BS這種渣滓。