以文本方式查看主题 - 中文XML论坛 - 专业的XML技术讨论区 (http://bbs.xml.org.cn/index.asp) -- 『 XML基础 』 (http://bbs.xml.org.cn/list.asp?boardid=1) ---- [转帖]用Expat處理你的XML資料(1) (http://bbs.xml.org.cn/dispbbs.asp?boardid=1&rootid=&id=59934) |
-- 作者:emmali808 -- 发布时间:3/14/2008 12:55:00 PM -- [转帖]用Expat處理你的XML資料(1) 用Expat處理你的XML資料(1) By Sam .... 2006/07/07 當你的程式之間需要傳遞資料時,你會怎麼做?譬如說設定檔資料,使用一個最簡單的型式: 『id := value』 那如果設定值很複雜又有層次呢?我甚至還看過透過網路把整個二進位資料結構memory複製到網路去,由接受端宣告一個一模一樣的資料結構在memcpy......(當然,看到這種程式要我處理我會有想自殺的感覺...)。 其實XML是一個很好的規範,他的可擴充性讓程式可以自己去處理自己要的資料,也不會因為多了一個欄位讓天下大亂(我的世界就處在混亂中...ㄏㄏ)。但是要你面對XML這類的複雜結構時,我想很多人看到就感到害怕吧。還好這個世界甚麼不多,Open Source的library最多...ㄏㄏ,Expat是一個很不錯的XML parser library,原則上他是一個C library,而且可以在許多平台使用(好啦...有win32版本...不過我沒用過),Expat是一個stream導向的parser library,也就是說他會從data buffer一直讀進資料然後遇到不同的狀態改變做不同的處理。 經過一番google搜尋後發現Expat的文章不多,只有看到一篇在xml.com的介紹文章,當然expat也有不少wrapper library,譬如Python、Perl、Tcl、C++....等等,你可以直接去使用你習慣的語言的wrapper。這篇文章只是抱持著研究的精神的小小介紹,這裡我們使用C++語言來實作一個簡單的xml parser吧。 使用Expat很簡單,首先當然你必須include相關的header file,Expat只會將兩個header file放進你的系統,分別是expat.h與expat_external.h(這裡以Expat2.0.0為例)。其實你只要加入expat.h,而expat_external.h會自動被加入。所以當然你必須有: #include <expat.h> 在你要使用Expat library的程式碼中。因為這裡我使用C++語言,因此我定義一個自己的類別"MyParser" class MyParser { public: MyParser(string fname); virtual ~MyParser(); } 先不要緊張,這目前是一個do-nothing的類別,我在建構式的地方傳入一個XML檔案名稱的參數,我也將parser的動作在初始階段完成,讓我們看看建構式的內容。Expat需要一個XML_Parser的instance在整個parsing階段,因此我們第一步便要宣告一個XML_Parser然後建立它: XML_Parser parser; parser = XML_ParserCreate(NULL); if (!parser) { cout << "create XML_Parser error" << endl; return 0; } Expat使用callback function來處理狀態改變的動作,所以當你需要對某些tag做處理的時候你必須要設定相關的處理函式,這裡我們只對最簡單的型式做處理,因此我只設定start tag、end tag與default handler: ::XML_SetUserData(parser, this); ::XML_SetElementHandler(parser, expatStart, expatEnd); ::XML_SetDefaultHandler(parser, expatHandler); 你可以使用this指標將自己傳給expat當成UserData;再來我們必須在類別內宣告相關的member function,因此我們的類別便宣告成: class MyParser { public: MyParser(string fname); virtual ~MyParser(); static void expatStart(void *data, const XML_Char *el, const XML_Char **attr); static void expatEnd(void *data, const XML_Char *el); static void expatHandler(void *data, const XML_Char *s, int len); } 你可以看到為了讓Expat的C library當成callback function我們將其宣告成static的member function,而當你要用類別內的成員變數或函式時,你不能直接呼叫或使用(沒忘記static吧),因此這個時候我們在XML_SetUserData(parser, this)做的動作便派上用場,你可以看到expatStart、expatEnd與expatHandler中第一個不定指標參數void *data便會是你在XML_SetUserData時傳入的第二個參數。因此假設你在這3個callback function中要使用一個類別函式"do_something()"時,你可以這樣做: ((MyParser *)data)->do_something(); 這樣一來,我們基本的宣告便完成,可以開始餵資料給XML_Parser了 file = fopen(fname.c_str(), "r"); do { len = fread(buf, 1, sizeof(buf), file); done = len < sizeof(buf); if (!XML_Parse(parser, buf, len, done)) done = 1; } while (!done); ::XML_ParserFree(parser); fclose(file); 當然最後不要忘了釋放掉我們宣告的parser與關閉檔案。一個最簡單的Expat動作流程就是這麼簡單.......待續 |
-- 作者:emmali808 -- 发布时间:3/14/2008 12:57:00 PM -- 先占一下,原文的网址:http://joepasscheng.googlepages.com/expat-1 |
W 3 C h i n a ( since 2003 ) 旗 下 站 点 苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》 |
46.875ms |