XML文件解析流程

引言

expat是使用C语言编写的XML解析器,采用stream的方式解析XML文件,首先需要向解析器注册callback函数,在传入文档进行解析的时候,对于解析器能够识别的部分,就会去调用适当的callback动作进行解析。

被解析的xml文件是被分块传入解析器的,这样expat就能够解析较大的xml文件,而不需要将整个xml文件整个加载到内存中去。

具体的使用流程
  • 创建解析器
XML_Parser XML_ParserCreate(const XML_Char* encoding)
//创建一个新的解析器,并返回一个解析器句柄
  • 为开始和结束设置handler
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);

解析器创建之后,stream需要先去设置callback,XML_SetElementHandler函数用来设置开始和结束标签的handlers

第一个参数是parser的操作句柄,第二个和第三个参数是callback函数用于解析到<></>

typedef void (*XML_StartElementHandler) (void *userData, const XML_Char *name, const XML_Char **atts);
//第一个参数需要使用函数XML_SetUserData(XML_Parser parser,void *p)
//后边的两个参数为name 和 atts
例如有一个XML文档
<feed version="2.0" ctxt-id="9212" template-id="default" feed-type="ftti">
</feed>
name返回的值就是feed
atts为指针数组atts[0] = "version" , atts[1] = "2.0"
typedef void (*XML_EndElementHandler) (void *userData, const XML_Char *name);
这个函数返回的name也是feed,处理标签结束。
  • 设置文本buffer块handler
XML_SetCharacterDataHandler(XML_Parser p,XML_characterDataHandler charhnd1)
//这个函数用来处理一个<></>之间的字段回调,
//回调函数原型
typedef void (*XML_CharacterDataHandler)(void *userData, const XML_Char *s, int len);
这里的XML_CHAR *s是一块buffer的指针
<title>天气</title>
<summary>2808时至2908时,陕西中南部、山西西南部、河南中南部、湖北北部、四川中
东部、重庆西部和北部、贵州西部等地的部分地区有大雨或暴雨,河南南部、湖北北部等地局部
有大暴雨。【点击“更多”查询其他城市天气】</summary>
//以上就是指针指向的全部内容
传入字符开始解析Parse
int XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
/*XML_Parse函数用来实时侧传入字符解析Parse,第二个参数是用户指定的buffer指针,第三个参数是buffer中实际内容的字节数,最后的参数代表这块buffer是否已经结束
(例如每次需要读取到内存中的buffer比较小,就可以采用循环读取的方式,把文件中读出来的buffer都给parser中,在文件读取结束之前,isFinal的参数为FALSE,反之为TRUE)。*/
    
//这样会造成的问题就是,XML_CharacterDataHandler一次返回的不是一个完成的charData,这样就会连续的调用两次XML_CharacterDataHandler,再将两次返回的结果拼接起来。
开始解析parse的另一种方法
void *XML_GetBuffer(XML_Parser p,int len)

int XML_ParseBuffer(XML_Parser p,int len, int isFinal)
    
//使用示例
void *buff = ::XML_GetBuffer(parser, BUFF_SIZE);
if (buff == nullptr) {
    MODEM_CTRLLOGE("failed in call to XML_GetBuffer");
    return -1;
}

int bytes_read = ::fread(buff, 1, BUFF_SIZE, file);
if (bytes_read < 0) {
    MODEM_CTRLLOGE("failed to read");
    return -1;
}

XML_Status status = ::XML_ParseBuffer(parser, bytes_read, bytes_read == 0);
if (status == XML_STATUS_OK) {
    MODEM_CTRLLOGE("%s", ::XML_ErrorString(::XML_GetErrorCode(parser)));
    mParsingStatus = ERROR_MALFORMED;
    return -1;
}

cacution:

XML_ParserReset(XML_Parser parser, const XML_Char *encodingname)
解析完一次xml文件之后,最好调用本函数完成重置xml
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值