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>
根标签: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的操作代码.
其中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>
说明:
类型标签:
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通过类类型信息生成变量的序列化/反序列化代码
代码生成器提供用户定义各种类的操作和定义各种变量的操作,有了这些数据,代码生成器即可生成变量的序列化/反序列化的代码.用户把代码拷贝到自己的工程作简单的配置修改,编译即可.
原文链接:https://www.f2er.com/xml/300103.html