XML序列化数据对象(二)
XML序列化数据对象(二)---原理和构思
一.定义数据对象的XML标签结构
例如: <ObjectSerialization> <m_nA class = "int"> 5 </m_nA> <m_dB class = "double"> 5.900000 </m_dB> <m_intVector class = "IntVector"> <vectorItem0 class = "int"> 1 </vectorItem0> <vectorItem1 class = "int"> 3 </vectorItem1> <vectorItem2 class = "int"> 4 </vectorItem2> <vectorItem3 class = "int"> 7 </vectorItem3> </m_intVector> </ObjectSerialization>
第2级标签:变量名例如m_nA 标签的内容:变量值例如标签m_nA的内容是5,那么变量m_nA的值就是5 标签属性: class:变量的类型(类名),例如int,double,IntVector class的值有:int,long,char,std::string,使用typedef定义的类型,使用typedef定义的stl容器类型(std::vector,std::map,std::list,std::set)
二.变量的序列化与反序列化.使用XML序列化变量过程就是写入XML过程,反序列化过程就是读取XML过程. (每一个XML解析器的调用流程可能有区别). 现在有 intm_nA=0; intm_nB=1; 和 structCTest { doublem_dC; doublem_dD; }; CTestm_test; //序列化/反序列化的伪代码 Write_int(); Write_double(); Write_m_nA() { Write_int(m_nA); } Write_m_nB() { Write_int(m_nB); } Write_CTest() { Write_double(m_dC); Write_double(m_dD); }
三.序列化/反序列化的代码需要跟着这些变量结构变化的
现在CTest结构改变为 structCTest { doublem_dC; intm_nD; }; //伪代码 Write_CTest() { Write_double(m_dC); Write_int(m_nD); } 变量类型结构的变化,序列化/反序列化的代码也会跟需要变化,这种变化在一些复杂的数据机构中,代码修改起来是很繁琐和重复的,很容易出错.但是这种变化又是有规律的.既然有规律,就可以用代码写一个程序去固定它和规范它. 在MFC中就是使用宏来把这种变化规律来固定的. 在boost中是使用模板和宏来把这种变化规律来固定的. 我这里则写了一个程序自动生成变量的序列化/反序列化代码来固定. 也就是说变量的类型结构变化了,程序将根据类型结构的变化自动生成该变量的序列化/反序列化的代码. (这里说的非常绕口啊) 概括说一句就是:我写一个小程序,该小程序能根据变量的类型结构自动生成变量的序列化/反序列化的代码. (就是用代码来写代码,或者说在代码之上写代码,这个程序就是一个代码生成器).
四.实现原理和过程
4.1生成变量的序列化/反序列化代码所需要的信息
从点一中的变量存储在XML中的结构知道需要的信息有: A.变量名. B.变量类型的结构 C.XML的操作代码. 有了这3类信息,即可自动生成变量的序列化/反序列化代码. 其中B.变量类型的结构
4.2变量类型的结构
从点一中的变量存储在XML中的内容知道,最终写入XML标签树的树叶部分的是数字和字符.标签之间的结构则反映类型结构. 所以变量类型的结构分类有: A.基本类型:char,int,float,std::string(我这里把std::string作为基本类型,也就是字符,因为我std::string使用的非常多). B.struct和class:也就是结构体和类,结构体和类的成员层层下去,最终也是基本类型. C.typedef定义的类型:typedef定义A和typedef定义B,最终也是基本类型. D.stl定义的容器:有std::vector,std::list;std::map;std::set(我用得最多也就这几种).最终也是基本类型. 有了这些类型结构后,如何保存一个变量就很清晰了,那么生成变量的序列化/反序列化代码也就很清晰了. 代码生成器通过变量类型结构生成序列化/反序列化代码.
4.3 变量类型的结构的表示和描述
用XML描述如下:
<structure_def> <class name = "CTest"> <include file = "a" sys = "0"> </include> <include file = "b" sys = "1"> </include> </class> <basetype name = "int"> </basetype> <basetype name = "double"> </basetype> <basetype name = "long"> </basetype> <stltype name = "std::vector" typenamecount = "1"> </stltype> <stltemplate beptr = "0" beptr1 = "0" name = "IntVector" type = "std::vector" typename1 = "int"> </stltemplate> <ClassObject> <m_nA class = "int"> </m_nA> <m_dB class = "double"> </m_dB> <m_intVector class = "IntVector"> </m_intVector> </ClassObject> </structure_def> 说明: 根标签名称:structure_def: 类型标签: basetype(主要有char,std::string这些类型) class(用户定义的类) struct(用户定义的结构体) stltype(主要有std::vector,std::set) typedef(使用typedef定义的类型) stltemplate(使用typedef定义的stltype,例如typedefstd::vector<int>IntVector) 类型标签的属性: name(类型名称,基本类型,stl的一些类型,用户定义的类/结构体等的名称,CTest,STTest,IntVector等) typenamecount(stltype类型中模板参数的个数,例如std::vector模板参数个数是1,std::map模板参数个数是2) beptr(表示该类型是否为指针类型,0为否,1为是) beptr1(表示stltemplate类型中第一个模板参数是否为指针类型,1为是) beptr2(表示stltemplate类型中第二个模板参数是否为指针类型,1为是,如果有的话) type(表示stltemplate类型中的stltype类型的类名称) typename1(表示stltemplate类型中第一个模板参数类型的类名称) typename2(表示stltemplate类型中第二个模板参数类型的类名称) 变量标签:ClassObject(用于记录需要序列化的变量名称和类型),ClassObject的子项就是使用变量名的标签,变量名标签的class属性代表变量类型.
4.4通过类类型信息生成变量的序列化/反序列化代码
代码生成器提供用户定义各种类的操作和定义各种变量的操作,有了这些数据,代码生成器即可生成变量的序列化/反序列化的代码.用户把代码拷贝到自己的工程作简单的配置修改,编译即可. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |