最近在arm-linux下做個項目,需要在本地記錄一些資料,日誌之類的東西.本來準備隨便用文字檔記錄下完事,突然看到了rss,於是想起了xml.自己還沒有用過xml,於是打算用xml來存放這個寫資料,算是練個手.
由於以前沒有瞭解過xml編程,所以查閱了點資料.原來目前的xml解析器一般有兩種解析的形式.一種是DOM模型的,一種是SAX2模型的.DOM模型是講xml檔案中的結構解析成一棵樹,然後再進行各種操作;而SAX2模型是類似與事件處理的方式從頭到位解析xml檔案.兩種方式各有優劣,不過在嵌入式裝置上用DOM模型的解析器似乎太耗記憶體,所以一般都用SAX2的解析器.而我使用的正是linux下的expat,是符合SAX2模型的.
好像linux都有內建expat的庫,不過我為了移植到arm板上還是去下了個源碼包.先交叉編譯通過確認可以使用了才開始學習具體的使用.在源碼包中有一個協助檔案已經很詳細的介紹了庫中每個函數的用途和入門編程.基本上看這個就夠用了.
查閱了協助發現其實只需要3,4個函數就可以搞定大部分的工作.
XML_Parser XML_ParserCreate(const XML_Char *encoding);
建立一個XML的對象.
XML_SetElementHandler(XML_Parser p, XML_StartElementHandler start, XML_EndElementHandler end);
是設定處理元素頭尾的函數.
XML_SetCharacterDataHandler(XML_Parser p,XML_CharacterDataHandler charhndl)
設定元素內文本的處理函數.
void XML_SetUserData(XML_Parser p,void *userData);
設定一個共用的資料結構給各各處理函數使用.
XML_Status XML_Parse(XML_Parser p,const char *s,int len,int isFinal);
這個是主處理函數.通過給XML_Parse對象指定一個含有xml文本的char型數組s,來解析xml.解析的過程就是在讀到某個位置就調用的處理函數來處理.比如讀到元素的頭部,就調用在XML_SetElementHandler中設定的start函數來處理.
上面描述的有些空洞,看個例子就全明白了:
要解析這樣一個XML:
<ifq name="Wang Jingtian" age="22"> a greate guy! </ifq>
顯示其中的attr和content,程式如下:
void starthandle(void *userdata, const char *el, const char **attr)
{
//解析時對xml元素頭的解析函數
int i;
for (i=0;attr[i];i+=2)
{
printf("%s=%s",attr[i],attr[i+1]);
}
}
void endhandle(void *data, const char *el)
{
//什麼也不做.
}
void chardatahandle(void *data,char *s,int len)
{
//顯示content的內容.注意s不是以空作為字串結尾的標識.要手動用len來控制.
}
int ReadXml(char *xmlbuf,int bufsize)
{
XML_Parser g_Parser=XML_ParserCreate(NULL);
XML_SetElementHandler(g_Parser, starthandle,endhandle);
XML_SetCharacterDataHandler(g_Parse,chardatahandle);
if (! XML_Parse(g_Parser, xmlbuf, bufsize, 1))
{
fprintf(stderr, "Parse error at line %d:/n%s/n",
XML_GetCurrentLineNumber(g_Parser),
XML_ErrorString(XML_GetErrorCode(g_Parser)));
return -1;
}
XML_ParserFree(g_Parser);
return 0;
}//程式大概就是這樣,但是沒有調試,不能保證正確:)
上邊就是整個處理常式,是要調用readXML,傳入xml的buf就可以解析了.基本上所有expat程式的架構都是這個樣子,稍作改動就可以用在自己的程式裡.
以上就是我對xml解析的一點點總結,能力有限,如果有什麼地方有錯誤,還請大家多多指點.歡迎大家和我交流.我的email:ifqqfi@gmail.com