1.还是看项目,如果需要面向对象的,不适用expat
2.但是如果需要边解析边修改值,可以用expat
1、下载expat(expat-2.2.9)库:http://distfiles.macports.org/expat/
2、tar jxvf expat-2.4.1.tar.bz2
cd expat-2.4.1/
/configure
3、./configure --without-tests --without-examples --prefix= /home/yun/project/lib/bluez/expat-2.2.9/install --host= arm-none-linux-gnueabi
4、cd xmlwf
5、make clean
6、make
7、返回上一级目录
8、make
9、make install
XML_ParserCreate ------Create a new parser object.
XML_SetElementHandler ------ Set handlers for start and end tags.
XML_SetCharacterDataHandler ------Set handler for text.
XML_Parse ------ Pass a buffer full of document to the parser
1.先创建一个句柄
2.再调用XML_SetElementHandler(XML_Parser parser,
XML_StartElementHandler start,
XML_EndElementHandler end),
这二个回调分别是对应于解析<>和</>, 下面分别详细介绍这个2个回调函数。
①第一个参数userData, 可以由函数XML_SetUserData(XML_Parser parser, void *p)设置
②举例说明第二个和第三个参数:
<feed version=“2.0” ctxt-id=“9212” template-id=“default” feed-type=“ftti”>
那么StartElementHandler回调返回的name就是标签"feed", **atts是一个指针数组,分别指向标签的一组属性,atts[0]就是"version", atts[1]就是"2.0", 以此类推
就是处理标签结束的,name就是"feed”了,这个回调一般是用户设置自己的状态机的。
typedef void (XMLCALL *XML_CharacterDataHandler) (void *userData,
const XML_Char *s,
int len);
Buffer的指针,如果你单步DEBUG后,你会发现expat用的就是你传入的那块Buffer(这块Buffer下面讲解),比如解析下面的XML:
<title>天气</title>
<summary>28日08时至29日08时,陕西中南部、山西西南部、河南中南部、湖北北部、四川中
东部、重庆西部和北部、贵州西部等地的部分地区有大雨或暴雨,河南南部、湖北北部等地局部
有大暴雨。【点击“更多”查询其他城市天气】</summary>
第二个参数buffer的指针指向的内容是:(只是没有了<title>)
天气</title>
<summary>28日08时至29日08时,陕西中南部、山西西南部、河南中南部、湖北北部、四川中
东部、重庆西部和北部、贵州西部等地的部分地区有大雨或暴雨,河南南部、湖北北部等地局部
有大暴雨。【点击“更多”查询其他城市天气】</summary>
所以要根据第三个参数len来确定正确的数据。
XML_SetElementHandler(XML_Parser p,
XML_StartElementHandler start,
XML_EndElementHandler end);
typedef void
(*XML_StartElementHandler)(void *userData,
const XML_Char *name,
const XML_Char **atts);
typedef void
(*XML_EndElementHandler)(void *userData,
const XML_Char *name);
前面已经介绍过
①第二个参数是用户指定的Buffer指针
②第三个是这块Buffer中实际内容的字节数,比如要解析的XML文件太大,但内存比较吃紧,Buffer比较小,则可以循环读取文件,然后丢给Parser
③最后参数代表是否这块Buffer已经结束,在文件读取结束前,isFinal参数为FALSE,反之为TRUE。
你的应用程序将释放user_data使用的所有内存-
在某些时候,如果你不确定前后2次XML是否一样的情况下,比如网络上投递的XML,在一次解析后最好调用一次本函数,否则会出现意料之外的结果。比如前后两次XML完全一样,可这你并不知情,那么XML_Parse()会返回失败。
如果expat不能为buffer分配足够的空间,它将返回一个空字符。这将不得不再每次调用XML_ParseBuffer函数之前先调用这个函数。一个通常的用法像这样子
for (;;) {
int bytes_read;
void *buff = XML_GetBuffer(p, BUFF_SIZE);
if (buff == NULL) { /* handle error */ } //expat不能为buffer分配足够的空间
bytes_read = read(docfd, buff, BUFF_SIZE);
if (bytes_read < 0) { /* handle error */ }
if (! XML_ParseBuffer(p, bytes_read, bytes_read == 0)) { /* handle parse error */ }
if (bytes_read == 0) break;
}
#include <stdio.h>
#include "expat.h"
#pragma warning(disable:4996)
#define XML_FMT_INT_MOD "l"
static void XMLCALL startElement(void *userData, const char *name, const char **atts)
{
int i;
int *depthPtr = (int *)userData;
for (i = 0; i < *depthPtr; i++)
printf(" ");
printf(name);
*depthPtr += 1;
for(i=0;atts[i]!=0;i+=2)
{
printf(" %s=%s",atts[i],atts[i+1]);
}
printf("\n");
}
static void XMLCALL endElement(void *userData, const char *name)
{
int *depthPtr = (int *)userData;
*depthPtr -= 1;
}
int main(int argc, char *argv[])
{
char buf[BUFSIZ]; //创建8192,也就是2页的缓冲区
XML_Parser parser = XML_ParserCreate(NULL);//创建XML分析器
int done; int depth = 0;
XML_SetUserData(parser, &depth);
XML_SetElementHandler(parser, startElement, endElement);
FILE* pFile= argc<2 ?stdin : fopen(argv[1],"rb");//没参数就打印到屏幕,有参数就以流的方式打开文件,以读二进制的方式打开
do
{ int len = (int)fread(buf, 1, sizeof(buf), pFile);
done = len < sizeof(buf);
if (XML_Parse(parser, buf, len, done) == XML_STATUS_ERROR)
{
fprintf(stderr,"%s at line %" XML_FMT_INT_MOD "u\n",
XML_ErrorString(XML_GetErrorCode(parser)),
XML_GetCurrentLineNumber(parser));
return 1;
}
}
while (!done);
XML_ParserFree(parser);//释放解析器使用的内存
fclose(pFile);
return 0;
}