您的位置:首页 > 其它

XML序列化数据对象(二)

2013-07-27 09:03 267 查看
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, double, long, char, std::string, 使用typedef定义的类型, 使用typedef定义的stl容器类型(std::vector, std::map, std::list, std::set)

二. 变量的序列化与反序列化.

 

      使用XML序列化变量过程就是写入XML过程, 反序列化过程就是读取XML过程.

(每一个XML解析器的调用流程可能有区别).

现在有

int m_nA = 0;

int m_nB = 1;



struct CTest

{

      double m_dC;

      double m_dD;

};

CTest m_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结构改变为

struct CTest

{

      double m_dC;

      int m_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, double, long, 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, int, double, long, float, std::string这些类型)

     class(用户定义的类)

     struct(用户定义的结构体)

     stltype(主要有std::vector, std::list, std::map, std::set)

     typedef(使用typedef定义的类型)

     stltemplate(使用typedef定义的stltype, 例如typedef std::vector<int> IntVector)

类型标签的属性: 

     name(类型名称, 基本类型, stl的一些类型, 用户定义的类/结构体等的名称, 例如int, double,  CTest,  STTest, IntVector等)

     typenamecount(stltype类型中模板参数的个数, 例如std::vector模板参数个数是1, std::map模板参数个数是2)

     beptr(表示该类型是否为指针类型, 0为否, 1为是)

     beptr1(表示stltemplate类型中第一个模板参数是否为指针类型, 0为否, 1为是)

     beptr2(表示stltemplate类型中第二个模板参数是否为指针类型, 0为否, 1为是, 如果有的话)

     type(表示stltemplate类型中的stltype类型的类名称)

     typename1(表示stltemplate类型中第一个模板参数类型的类名称)

     typename2(表示stltemplate类型中第二个模板参数类型的类名称)

变量标签: ClassObject(用于记录需要序列化的变量名称和类型), ClassObject的子项就是使用变量名的标签, 变量名标签的class属性代表变量类型.

4.4 通过类类型信息生成变量的序列化/反序列化代码

代码生成器提供用户定义各种类的操作和定义各种变量的操作, 有了这些数据, 代码生成器即可生成变量的序列化/反序列化的代码. 用户把代码拷贝到自己的工程作简单的配置修改, 编译即可.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐