XML序列化数据对象(二)

前端之家收集整理的这篇文章主要介绍了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>


标签: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.structclass:也就是结构体和类,结构体和类的成员层层下去,最终也是基本类型.

C.typedef定义的类型:typedef定义Atypedef定义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通过类类型信息生成变量的序列化/反序列化代码


代码生成器提供用户定义各种类的操作和定义各种变量的操作,有了这些数据,代码生成器即可生成变量的序列化/反序列化的代码.用户代码拷贝到自己的工程作简单的配置修改,编译即可.

原文链接:https://www.f2er.com/xml/300103.html

猜你在找的XML相关文章