expat使用解析XML文件

皇甫宇定
2023-12-01

expat库下载可以从https://sourceforge.net/projects/expat/files/expat/下载,下载完毕后就是配置安装,不再赘述。使用到的函数有:

XML_Parse(XML_Parser parser, const char *s, int len, int isFinal);

XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start, XML_EndElementHandler end);

其中XML_SetElementHandler函数使用时候需要设置两个回调函数,原型如下:

typedef void (XMLCALL *XML_StartElementHandler) (void *userData, const XML_Char *name,  const XML_Char **atts);

typedef void (XMLCALL *XML_EndElementHandler) (void *userData,const XML_Char *name);

注意:使用expat解析XML文件时候,一定要注意整个文本中只能有一个主根节点(即示例中html),在使用XML_Parse函数进行解析的时候,一定要注意还有剩余部分需要解析的时候,不能将isFinal置1,否则在继续解析的时候,会产生异常(failed to parser : parsing finished)但是仍会执行之后的程序,如果在isFinal置1的时候,结尾没有主根节点的结束符号,会产生异常(failed to parser : no element found);
且如果有非主节点的结点缺失,会报异常(failed to parser : mistouched tag),且异常会直接退出;

expat解析会解析两种情况,两种情况一种是类似于<xxx param1="value1" param2="value2"...>的begin形式另外一种就是类似</a>的end形式,通过函数

XMLPARSEAPI(void) XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start, XML_EndElementHandler end);

执行begin形式和end形式的函数调用,对于前者会调用XML_StartElementHandler函数,后者调用XML_EndElementHandler
两个函数如下且两个函数均需自定义:
typedef void (XMLCALL *XML_StartElementHandler) (void *userData,
                                                 const XML_Char *name,
                                                 const XML_Char **atts);

typedef void (XMLCALL *XML_EndElementHandler) (void *userData,
                                               const XML_Char *name); 

XML_StartElementHandler和XML_EndElementHandler函数指针有一个共同点,就是都有userData指针和name指针,userData可以通过XML_SetUserData函数来进行设定,而name则是解析器解析过程中获取到的标识符,其中begin端和end端并非需要一一对应,只要解析器解析到begin端就会执行XML_StartElementHandler 指向的函数,与之对应end端亦然,两者的不同之处在于const XML_Char **atts,该参数指的就是begin端的param1="value1" param2="value2"...部分,其中atts[0]为param部分,atts[1]为value部分。且该部分不会存在于end端,故end端没有该参数。
 

关于expat解析过程对节点的操作及其注意事项:

<!-- xxx -->    注释
<xxx>        节点开始(调用XML_StartElementHandler)
</xxx>        节点结束(调用XML_EndElementHandler)
<xxx/>        节点开始+结束(先调用XML_StartElementHandler,再调用XML_EndElementHandler)

解析过程中,每次进行解析是以 (>) 作为开始解析的标志的,如果发生信息流截断,如:
"<html><!--jjjj--><head></head><body><a target= \"_blank\" href=\"www.la"
"bfan.com\"> this is labfan</a></body></html>

则在解析过程中,会将 (<a target= \"_blank\" href=\"www.la)保存下来结合到    (bfan.com\">)之前然后进行解析!!!

 类似资料: