使用expat开发xml分析器

前端之家收集整理的这篇文章主要介绍了使用expat开发xml分析器前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
expat下载地址:http://sourceforge.net/projects/expat/ @H_502_1@
互联网发得展很快,都是源自于使用了超文本的表达方式。比如你查看一篇文章,看到不懂的关键字,就可以通过链接去查看它的内容,看完之后再回来接着看原来的东西,这样比较适合学习的方式。使用HTML标记的文本,是结构化储存的,这样的表达方式才可以实现超级连接。由于HTML具有超强的表达能力,也就在互联网上生存下来,那么人们就会想到能不能使用这种方式来保存所有需要保存的内容呢?慢慢地就开发XML标记语言,用来保存任意想保存的内容。由于XML具有HTML同样的功能,并且不限定标记,这样就可以表达所有的东西了。并且XML是基于树形结构的,想表达的信息就可以采用归类树的方式来组织内容了,这样能产生灵活可变的内容管理方式。比如在第二人生里采用参数配置文件,也是选择XML来保存的,并且使用expat的XML解析器来实现这方面的内容。接着下来,我们就来了解一下expat是什么东东,又是怎么样调用它来解析XML文件的。

expat是使用C编写的XML解释器,采用流的方式来解析XML文件,并且基于事件通知型来调用分析到的数据,并不需要把所有XML文件全部加载到内存里,这样可以分析非常大的XML文件。由于expat库是由XML的主要负责人James Clark来实现的,因此它是符合W3C的XML标准的。

使用expat库是非常简单的,只需要了解四个函数,就可以达到80%的功能了,看来设计这个库还是比较好的。那么需要了解那四个函数呢?这四个函数如下:
XML_ParserCreate 创建一个XML分析器。
XML_SetElementHandler 设置处理标记开始和结束的处理函数
XML_SetCharacterDataHandler 设置处理不同字符集的数据。
XML_Parse 分析给出的缓冲区XML数据。
通过调用上面四个函数就可以实现expat调用了,使用它就是这么方便简单的。
@H_502_1@
CODE @H_502_1@

@H_502_1@
[cpp] view plain copy
@H_502_1@ @H_502_1@ @H_502_1@
  1. //无双loveunix.net转载请保留出处
  2. #include<cstdlib>
  3. #include<fstream>
  4. #include<iostream>
  5. #include<cstring>
  6. #include<string>
  7. #include<expat.h>
  8. usingnamespacestd;
  9. #defineXML_MMSC_LISTEN_PORT"MMSC_LISTEN_PORT"
  10. #defineXML_CLIENT_LISTEN_PORT"CLIENT_LISTEN_PORT"
  11. #defineXML_MMSC_FROMADDR"MMSC_FROMADDR"
  12. #defineXML_MMSC_IPADDR"MMSC_IPADDR"
  13. #defineXML_MMSC_ROOT"MMSC_ROOT"
  14. #defineXML_MMSC_PORT"MMSC_PORT"
  15. #defineXML_MMSC_LOGIN_NAME"MMSC_LOGIN_NAME"
  16. #defineXML_MMSC_LOGIN_PWD"MMSC_LOGIN_PWD"
  17. #defineXML_MMSC_VASP_ID"MMSC_VASP_ID"
  18. #defineXML_MMSC_VAS_ID"MMSC_VAS_ID"
  19. #defineXML_MMS_SUBMIT_REPEATTIME"MMS_SUBMIT_REPEATTIME"
  20. enumCONF_TYPE{EM_UNUSE=0,
  21. EM_LSN_MMSC_PORT,EM_LSN_CLN_PORT,EM_SENDREPEAT,
  22. EM_MMSC_IP,EM_MMSC_PORT,EM_MMSC_ROOT,
  23. EM_FROM,EM_VASPID,EM_VASID,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> EM_AUTHNAME,EM_AUTHPWD
  24. };
  25. structXML_MMSCConfInfo{
  26. intDepth;
  27. intElement;
  28. intMMSC_LISTEN_PORT;
  29. intCLIENT_LISTEN_PORT;
  30. charMMSC_FROMADDR[50];
  31. charMMSC_IPADDR[16];
  32. charMMSC_ROOT[255];
  33. intMMSC_PORT;
  34. charMMSC_LOGIN_NAME[255];
  35. charMMSC_LOGIN_PWD[255];
  36. charMMSC_VASP_ID[255];
  37. charMMSC_VAS_ID[255];
  38. intMMS_SUBMIT_REPEATTIME;
  39. };
  40. staticintGetID(constchar*name){
  41. if(!stricmp(name,XML_MMSC_LISTEN_PORT))returnEM_LSN_MMSC_PORT;
  42. returnEM_LSN_CLN_PORT;
  43. returnEM_FROM;
  44. returnEM_MMSC_IP;
  45. returnEM_MMSC_ROOT;
  46. returnEM_MMSC_PORT;
  47. returnEM_AUTHNAME;
  48. returnEM_AUTHPWD;
  49. returnEM_VASPID;
  50. returnEM_VASID;
  51. returnEM_SENDREPEAT;
  52. returnEM_UNUSE;
  53. }
  54. intSetElementValue(XML_MMSCConfInfo&Conf,char*Value)
  55. {
  56. boolHasQoute=false;
  57. char*pstart=strchr(Value,'"');
  58. char*pend;
  59. if(!pstart){
  60. pstart=Value;
  61. pend=pstart;
  62. }
  63. else{
  64. pend=strchr(++pstart,'"');
  65. if(!pend)return-1;
  66. HasQoute=true;
  67. intlen=pend-pstart;
  68. switch(Conf.Element){
  69. caseEM_LSN_MMSC_PORT:
  70. Conf.MMSC_LISTEN_PORT=atoi(pstart);
  71. break;
  72. caseEM_LSN_CLN_PORT:
  73. Conf.CLIENT_LISTEN_PORT=atoi(pstart);
  74. break;
  75. caseEM_SENDREPEAT:
  76. Conf.MMS_SUBMIT_REPEATTIME=atoi(pstart);
  77. caseEM_MMSC_IP:
  78. if(!HasQoute)return-1;
  79. strncpy(Conf.MMSC_IPADDR,pstart,len>sizeof(Conf.MMSC_IPADDR)
  80. ?sizeof(Conf.MMSC_IPADDR):len);
  81. caseEM_MMSC_PORT:
  82. Conf.MMSC_PORT=atoi(pstart);
  83. caseEM_MMSC_ROOT:
  84. strncpy(Conf.MMSC_ROOT,153); background-color:inherit; font-weight:bold">sizeof(Conf.MMSC_ROOT)?
  85. sizeof(Conf.MMSC_ROOT):len);
  86. caseEM_FROM:
  87. strncpy(Conf.MMSC_FROMADDR,153); background-color:inherit; font-weight:bold">sizeof(Conf.MMSC_FROMADDR)?
  88. sizeof(Conf.MMSC_FROMADDR):len);
  89. caseEM_VASPID:
  90. strncpy(Conf.MMSC_VASP_ID,153); background-color:inherit; font-weight:bold">sizeof(Conf.MMSC_VASP_ID)?
  91. sizeof(Conf.MMSC_VASP_ID):len);
  92. caseEM_VASID:
  93. strncpy(Conf.MMSC_VAS_ID,153); background-color:inherit; font-weight:bold">sizeof(Conf.MMSC_VAS_ID)?
  94. sizeof(Conf.MMSC_VAS_ID):len);
  95. caseEM_AUTHNAME:
  96. strncpy(Conf.MMSC_LOGIN_NAME,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> len>sizeof(Conf.MMSC_LOGIN_NAME)?
  97. sizeof(Conf.MMSC_LOGIN_NAME):len);
  98. caseEM_AUTHPWD:
  99. strncpy(Conf.MMSC_LOGIN_PWD,153); background-color:inherit; font-weight:bold">sizeof(Conf.MMSC_LOGIN_PWD)?
  100. sizeof(Conf.MMSC_LOGIN_PWD):len);
  101. default:
  102. return0;
  103. staticvoidXMLCALL
  104. xmlstart(void*data,87); background-color:inherit; font-weight:bold">char*el,87); background-color:inherit; font-weight:bold">char**attr)
  105. XML_MMSCConfInfo*pmmscinf=(XML_MMSCConfInfo*)data;
  106. for(inti=0;attr[i];i++){
  107. pmmscinf->Element=GetID(attr[i]);
  108. SetElementValue(*pmmscinf,attr[i+1]);
  109. pmmscinf->Element=GetID(el);
  110. pmmscinf->Depth++;
  111. xmlend(char*el)
  112. ((XML_MMSCConfInfo*)data)->Element=EM_UNUSE;
  113. ((XML_MMSCConfInfo*)data)->Depth--;
  114. voidXMLCALL
  115. parsedata(void*userData,153); background-color:inherit; font-weight:bold">constXML_Char*s,intlen)
  116. {
  117. stringstr;
  118. str.assign(s,len);
  119. SetElementValue(*(XML_MMSCConfInfo*)userData,str.c_str());
  120. /**
  121. *@brief解析MMSC配置文件
  122. *
  123. *@return-1失败0成功
  124. **/
  125. intParseMMSCConf(XML_MMSCConfInfo&Conf,87); background-color:inherit; font-weight:bold">char*FileName)
  126. memset(&Conf,sizeof(XML_MMSCConfInfo));
  127. ifstreamifs(FileName,ios::in|ios::binary);
  128. if(!ifs)
  129. char*buf;
  130. intlen;
  131. ifs.seekg(0,ios::end);
  132. len=ifs.tellg();
  133. buf=newchar[len];
  134. if(buf)
  135. ifs.read(buf,len);
  136. ifs.close();
  137. if(!buf)
  138. intdone=0;
  139. interr=0;
  140. XML_Parserparser=XML_ParserCreate(NULL);
  141. if(!parser){
  142. cerr<<"Couldn'tallocatememoryforparser"<<endl;
  143. XML_SetElementHandler(parser,xmlstart,xmlend);
  144. XML_SetUserData(parser,&Conf);
  145. XML_SetCharacterDataHandler(parser,parsedata);
  146. if(XML_Parse(parser,buf,len,done)
  147. ==XML_STATUS_ERROR){
  148. cerr<<XML_ErrorString(XML_GetErrorCode(parser))<<"atline"
  149. <<XML_GetCurrentLineNumber(parser)<<endl;
  150. err=1;
  151. ifs.close();
  152. XML_ParserFree(parser);
  153. returnerr;
  154. staticSerialize(constXML_MMSCConfInfo&Conf)
  155. printf("XML_MMSCConfInfois:/n"
  156. "/tDepth:%d/tElement:%d/n"
  157. "/tMSC_LISTEN_PORT:%d/tCLIENT_LISTEN_PORT:%d/n"
  158. "/tMMSC_FROMADDR:[%s]MMSC_IPADDR:[%s]tMMSC_PORT:%d/n"
  159. "/tMMSC_ROOT:[%s]/tMSC_LOGIN_NAME:[%s]/tMMSC_LOGIN_PWD:[%s]/n"
  160. "/tMMSC_VASP_ID:[%s]/tMMSC_VAS_ID:[%s]/tMMS_SUBMIT_REPEATTIME:%d/n",108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> Conf.Depth,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> Conf.Element,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> Conf.MMSC_LISTEN_PORT,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> Conf.CLIENT_LISTEN_PORT,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> Conf.MMSC_FROMADDR,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> Conf.MMSC_IPADDR,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> Conf.MMSC_PORT,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> Conf.MMSC_ROOT,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> Conf.MMSC_LOGIN_NAME,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> Conf.MMSC_LOGIN_PWD,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> Conf.MMSC_VASP_ID,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> Conf.MMSC_VAS_ID,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> Conf.MMS_SUBMIT_REPEATTIME);
  161. voidmain()
  162. test();
  163. XML_MMSCConfInfoConf;
  164. ParseMMSCConf(Conf,"conf.xml");
  165. Serialize(Conf);
  166. }
@H_502_1@ @H_502_1@
xml文件内容如下
CODE @H_502_1@

[xhtml] view plain copy
@H_502_1@ @H_502_1@ @H_502_1@
  1. <?xmlversion="1.0"encoding="gb2312"?>
  2. <mmscconf>
  3. MMSC_LISTEN_PORT>8801</>
  4. CLIENT_LISTEN_PORT>8902
  5. MMSC_FROMADDR>"+8613821113111/TYPE=PLMN"MMSC_IPADDR>"172.16.65.187"MMSC_ROOT>"/"MMSC_PORT>9000MMSC_LOGIN_NAME>"nan"MMSC_LOGIN_PWD>"whuang"MMSC_VASP_ID>"999999"MMSC_VAS_ID>"9999"MMS_SUBMIT_REPEATTIME>3>
@H_502_1@ @H_502_1@
使用expat时不会帮助检查xml语法 所以你必须保证要分析的xml文件是对的 @H_502_1@
expat默认只支持
UTF-8
UTF-16
ISO-8859-1
US-ASCII


其它的字符集需要自己定义
UnknownEncodingHandler
的实现

不然分析器会报错 @H_502_1@
中文版 @H_502_1@
[cpp] copy
@H_502_1@ @H_502_1@ @H_502_1@
    中文xml文件的处理或是其它非标准编码xml文件的处理
  1. expat内建只支持utf-8ucs2us-asciiiso8859-1编码
  2. 其它的编码必须设置XML_SetUnknownEncodingHandler
  3. CODE
  4. /*
  5. *=====================================================================================
  6. *
  7. *Filename:getinfo.cpp
  8. *Description:使用expat开发xml例子程序,包括中文xml的支持
  9. *Version:1.0
  10. *Created:2004-03-1715:17:34中国标准时间
  11. *Revision:none
  12. *Author:无双[lizl@yztelecom.com]
  13. *Company:www.loveunix.net
  14. *
  15. *=====================================================================================
  16. */
  17. #include<cstdlib>
  18. #include<fstream>
  19. #include<iostream>
  20. #include<cstring>
  21. #include<string>
  22. #include<windows.h>
  23. #include<expat.h>
  24. namespacestd;
  25. #defineXML_MMSC_LISTEN_PORT"MMSC_LISTEN_PORT"
  26. #defineXML_CLIENT_LISTEN_PORT"CLIENT_LISTEN_PORT"
  27. #defineXML_MMSC_FROMADDR"MMSC_FROMADDR"
  28. #defineXML_MMSC_IPADDR"MMSC_IPADDR"
  29. #defineXML_MMSC_ROOT"MMSC_ROOT"
  30. #defineXML_MMSC_PORT"MMSC_PORT"
  31. #defineXML_MMSC_LOGIN_NAME"MMSC_LOGIN_NAME"
  32. #defineXML_MMSC_LOGIN_PWD"MMSC_LOGIN_PWD"
  33. #defineXML_MMSC_VASP_ID"MMSC_VASP_ID"
  34. #defineXML_MMSC_VAS_ID"MMSC_VAS_ID"
  35. #defineXML_MMS_SUBMIT_REPEATTIME"MMS_SUBMIT_REPEATTIME"
  36. EM_LSN_MMSC_PORT,
  37. EM_MMSC_IP,
  38. EM_FROM,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> EM_AUTHNAME,EM_AUTHPWD
  39. };
  40. structXML_MMSCConfInfo{
  41. intDepth;
  42. intElement;
  43. intMMSC_LISTEN_PORT;
  44. intCLIENT_LISTEN_PORT;
  45. charMMSC_FROMADDR[50];
  46. charMMSC_IPADDR[16];
  47. charMMSC_ROOT[255];
  48. intMMSC_PORT;
  49. charMMSC_LOGIN_NAME[255];
  50. charMMSC_LOGIN_PWD[255];
  51. charMMSC_VASP_ID[255];
  52. charMMSC_VAS_ID[255];
  53. intMMS_SUBMIT_REPEATTIME;
  54. };
  55. intConvertFromUTF8(char*strout,87); background-color:inherit; font-weight:bold">intstroutlen,87); background-color:inherit; font-weight:bold">char*Text,87); background-color:inherit; font-weight:bold">intTextLen)
  56. {
  57. //转换utf-8编码到gb2312,linux下使用iconv函数可以直接转换,
  58. //在win下需要先转换到ucs2再从ucs2转换到utf-8
  59. WCHARWCharBuf[_MAX_PATH];
  60. LPWSTRpTransBuf=WCharBuf;
  61. intTransBufLen=_MAX_PATH;
  62. if(TextLen>=_MAX_PATH){
  63. TransBufLen=TextLen;
  64. pTransBuf=WCHAR[TransBufLen];
  65. if(!pTransBuf)
  66. return0;
  67. }
  68. intlength=MultiByteToWideChar(CP_UTF8,Text,TextLen,
  69. pTransBuf,TransBufLen);
  70. length=WideCharToMultiByte(CP_ACP,pTransBuf,length,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> strout,stroutlen,NULL,NULL);
  71. if(pTransBuf!=WCharBuf)
  72. delete[]pTransBuf;
  73. returnlength;
  74. }
  75. char*name){
  76. returnEM_LSN_MMSC_PORT;
  77. returnEM_LSN_CLN_PORT;
  78. returnEM_FROM;
  79. returnEM_MMSC_IP;
  80. returnEM_MMSC_ROOT;
  81. returnEM_MMSC_PORT;
  82. returnEM_AUTHNAME;
  83. returnEM_AUTHPWD;
  84. returnEM_VASPID;
  85. returnEM_VASID;
  86. returnEM_SENDREPEAT;
  87. returnEM_UNUSE;
  88. char*Value)
  89. {
  90. false;
  91. '"');
  92. char*pend;
  93. if(!pstart){
  94. pstart=Value;
  95. pend=pstart;
  96. else{
  97. pend=strchr(++pstart,'"');
  98. return-1;
  99. HasQoute=true;
  100. intlen=pend-pstart;
  101. switch(Conf.Element){
  102. caseEM_LSN_MMSC_PORT:
  103. Conf.MMSC_LISTEN_PORT=atoi(pstart);
  104. break;
  105. caseEM_LSN_CLN_PORT:
  106. Conf.CLIENT_LISTEN_PORT=atoi(pstart);
  107. break;
  108. caseEM_SENDREPEAT:
  109. Conf.MMS_SUBMIT_REPEATTIME=atoi(pstart);
  110. caseEM_MMSC_IP:
  111. return-1;
  112. strncpy(Conf.MMSC_IPADDR,153); background-color:inherit; font-weight:bold">sizeof(Conf.MMSC_IPADDR)
  113. ?sizeof(Conf.MMSC_IPADDR):len);
  114. caseEM_MMSC_PORT:
  115. Conf.MMSC_PORT=atoi(pstart);
  116. caseEM_MMSC_ROOT:
  117. strncpy(Conf.MMSC_ROOT,153); background-color:inherit; font-weight:bold">sizeof(Conf.MMSC_ROOT)?
  118. sizeof(Conf.MMSC_ROOT):len);
  119. caseEM_FROM:
  120. strncpy(Conf.MMSC_FROMADDR,153); background-color:inherit; font-weight:bold">sizeof(Conf.MMSC_FROMADDR)?
  121. sizeof(Conf.MMSC_FROMADDR):len);
  122. caseEM_VASPID:
  123. strncpy(Conf.MMSC_VASP_ID,153); background-color:inherit; font-weight:bold">sizeof(Conf.MMSC_VASP_ID)?
  124. sizeof(Conf.MMSC_VASP_ID):len);
  125. caseEM_VASID:
  126. strncpy(Conf.MMSC_VAS_ID,153); background-color:inherit; font-weight:bold">sizeof(Conf.MMSC_VAS_ID)?
  127. sizeof(Conf.MMSC_VAS_ID):len);
  128. caseEM_AUTHNAME:
  129. strncpy(Conf.MMSC_LOGIN_NAME,248); line-height:18px; margin:0px!important; padding:0px 3px 0px 10px!important"> len>sizeof(Conf.MMSC_LOGIN_NAME)?
  130. sizeof(Conf.MMSC_LOGIN_NAME):len);
  131. caseEM_AUTHPWD:
  132. strncpy(Conf.MMSC_LOGIN_PWD,153); background-color:inherit; font-weight:bold">sizeof(Conf.MMSC_LOGIN_PWD)?
  133. sizeof(Conf.MMSC_LOGIN_PWD):len);
  134. default:
  135. return0;
  136. /*----------------------------------------------------------------------
  137. *xml解析函数,0); background-color:inherit">*以下参数说明
  138. *data是使用XML_SetUserData设置的参数,expat不进行处理,会把它交给用户回调函数处理
  139. *el是元素名
  140. *attr是属性-值列表,样子为attr[0]=attr[1],最后一个是NULL
  141. *----------------------------------------------------------------------*/
  142. voidXMLCALL
  143. xmlstart(char**attr)
  144. //当碰到xml元素的开始标志时会调用这个函数,可以看打印显示的结果
  145. printf("startelement:
@H_502_1@ @H_502_1@
sax原理 @H_502_1@
sax是Simple API for XML @H_502_1@
Megginson采用Java语言开发的,之后SAX很快在Java开发者中流行起来。SAN项目现在负责管理其原始API的开发工作,这是一种公开的、开放源代码软件。不同于其他大多数XML标准的是,SAX没有语言开发商必须遵守的标准SAX参考版本。因此,SAX的不同实现可能采用区别很大的接口。不过,所有的这些实现至少有一个特性是完全一样的,这就是事件驱动。 事件驱动的文档解析 在SAX解析器装载XML文件时,它遍历文件文档并在其主机应用程序中产生事件(经由回调函数、指派函数或者任何可调用平台完成这一功能)表示这一过程。这样,编写SAX应用程序就如同采用最现代的工具箱编写GUI程序。 大多数SAX实现都会产生以下若干类型的事件: * 在文档的开始和结束时触发文档处理事件。 * 在文档内每一XML元素接受解析的前后触发元素事件。任何元数据通常都由单独的事件交付。 * 在处理文档的DTD或Schema时产生DTD或Schema事件。 * 错误事件用来通知主机应用程序解析错误。 显而易见,在处理文档时你最关心的就是元素事件了。通常,SAX解析器会向你的主机应用程序提供包含元素信息的事件参数;在最低程度下也会提供元素的名字。具体取决于你的特定实现,可以定义不同类型的元素事件代表不同类型元素的处理。例如,注释元素(它可能包含主机应用程序的处理指令)就经常在接受处理时产生特殊的事件。 @H_502_1@ @H_502_1@ 原文链接:https://www.f2er.com/xml/299489.html

猜你在找的XML相关文章