代码自动生成工具(三)-Xml读表代码自动生成工具
2018-01-18 10:48
471 查看
之前提到了一个工具类XmlReader
这里我们实现一个可以对Xml文件,自动生成其对应的读表代码。
本工具需要boost库支持,本人用的是1.55.0。
首先人为约定两个xml结点属性名称的保留关键字:pk=“”,rk=“”。
pk的值是本结点的某一个字段的名字,用来表示本结点在其父结点中,采用map来管理,键值就是该字段的值。
rk的值是本结点中某两个同类型的字段的名字,这两个字段用来表示一个闭区间,使得本结点在其父结点中,采用rangmap来管理,区间的起始值和终止值,就是这两个字段所填的值。
没有配置键的情况下,子节点在父结点中采用vector管理。
pk或rk 在相同结构路径下,只需要配置一次就可以,不需要每个节点都配置。
对于字段的数据类型,采用正则表达式判断识别,如果同一个字段,即出现整数,又出现浮点数,则按浮点数处理;即出现数字,又出现字符串,按字符串处理;如果同一个字段,出现不能兼容的两种类型,比如同时有数字和时间,按字符串处理。
这里首先定义Xml中支持的几种列类型:XmlMemberType:包括整数,小数,浮点数,字符串,时间戳,子结构等等
列主键的类型
xml结构成员的定义,包括名字,类型,是否是主键
xml结构的定义,包含结构名称,结构成员列表
整个xml文件:包括文件名,包名,结构列表
xml文件解析类,读取文件文本内容,使用EBNF范式,分析文件内容,按相应配置(命名空间,文件路径等),解析生成相应的XmlFile对象,
具体的代码生成包含两部分功能:
void ParseXml2LoaderH(const XmlParse& xmlParse)
void ParseXml2LoaderCpp(const XmlParse& xmlParse)
void ParseXml2HelperH(const XmlParse& xmlParse)
void ParseXml2HelperCpp(const XmlParse& xmlParse)
传入一个解析好的XmlParse对象,生成具体代码
Loader生成对应的读取代码,使用boost::ptree读取xml文件,转成相应的数据结构。
Helper生成一个空的辅助类,用于需要对数据重新组织的情况,比如配置中是按某个id列作为主键,存成一个map,提供查找,但是实际逻辑中还需要按某个名称列作为索引,再提供一个map,用于提供按名称查找(或者模糊查找),这时候就需要手动再提供一个新的查找函数,就可以写在helper中
main函数涉及两个小功能:
一个是遍历输入参数,解析名命名空间,待处理的xml文件,代码生成路径
一个是迭代每一个待处理的xml文件名,传入XmlParse解析,然后对解析完的结果,逐个生成相应代码
完整的代码,比较长,这里就不贴了
给一个生成后的代码的示例吧:
xml文件:
生成的代码:
放上完整工程的下载链接
工程中的boost库的路径为作者本机的路径,VS编译时请选择Release,重新配置boost库的include路径和lib路径
这里我们实现一个可以对Xml文件,自动生成其对应的读表代码。
本工具需要boost库支持,本人用的是1.55.0。
首先人为约定两个xml结点属性名称的保留关键字:pk=“”,rk=“”。
pk的值是本结点的某一个字段的名字,用来表示本结点在其父结点中,采用map来管理,键值就是该字段的值。
rk的值是本结点中某两个同类型的字段的名字,这两个字段用来表示一个闭区间,使得本结点在其父结点中,采用rangmap来管理,区间的起始值和终止值,就是这两个字段所填的值。
没有配置键的情况下,子节点在父结点中采用vector管理。
pk或rk 在相同结构路径下,只需要配置一次就可以,不需要每个节点都配置。
对于字段的数据类型,采用正则表达式判断识别,如果同一个字段,即出现整数,又出现浮点数,则按浮点数处理;即出现数字,又出现字符串,按字符串处理;如果同一个字段,出现不能兼容的两种类型,比如同时有数字和时间,按字符串处理。
这里首先定义Xml中支持的几种列类型:XmlMemberType:包括整数,小数,浮点数,字符串,时间戳,子结构等等
enum XmlMemberType { XMT_init = 0, // 未初始化的 XMT_uint32, // 无符号整数 XMT_int32, // 整数 XMT_float, // 浮点数 XMT_datetime, // 年-月-日 时:分:秒表示的时间 XMT_time, // 时:分:秒表示的时间 XMT_rang, // int-int这样的两个数字表示的区间值 XMT_string, // 字符串 XMT_child, // 子结构 XMT_unknow, // 非法的类型(同一个字段出现了两种不能互相兼容的类型) XMT_count, };
列主键的类型
enum XmlMemberKey { XMK_pk = 0, // 主键 XMK_rang, // 范围主键 XMK_normal, // 普通成员 };
xml结构成员的定义,包括名字,类型,是否是主键
class XmlMember { public: XmlMember(); XmlMember(const XmlMember &other); XmlMember& operator = (const XmlMember &other); void Init(); std::string m_Name; // xml结构字段名称 XmlMemberType m_Type; // xml结构字段类型 XmlMemberKey m_Key; // xml结构字段是否作为主键使用 };
xml结构的定义,包含结构名称,结构成员列表
class XmlStruct { public: XmlStruct(); XmlStruct(const XmlStruct &other); XmlStruct& operator = (const XmlStruct &other); void Init(); const XmlMember* GetPrimaryKey() const; std::vector<const XmlMember*> GetRangKey() const; std::string m_Name; // 结构名称 std::map<std::string, XmlMember> m_Members; // 结构字段列表 };
整个xml文件:包括文件名,包名,结构列表
class XmlFile { public: XmlFile(); XmlFile(const XmlFile &other); XmlFile& operator = (const XmlFile &other); void Init(); std::string m_FileName; // xml文件名(不带扩展名) std::string m_Package; // xml包名xxx.xxx.xxx std::map<std::string, XmlStruct> m_Structs; // xml结构列表 };
xml文件解析类,读取文件文本内容,使用EBNF范式,分析文件内容,按相应配置(命名空间,文件路径等),解析生成相应的XmlFile对象,
class XmlParse { public: XmlParse(); ~XmlParse(); bool ParseFile(const char* fullPathName); private: bool ParseXml(const char* expr); void ParseXmlStruct(const char* start, const char* end); void ParseXmlStructEnd(const char* start, const char* end); void ParseXmlStructEnd1(const char* start, const char* end); void ParseXmlStructEnd2(const char* start, const char* end); void ParseXmlMemberName(const char* start, const char* end); void ParseXmlMemberValue(const char* start, const char* end); public: // 解析完毕的xml文件信息列表 std::map<std::string, XmlFile> m_Files; private: // 解析时,临时xml文件内容对象 common::tool::FileData m_FileData; // 解析时,临时xml文件对象 XmlFile m_TempFile; // 解析时,临时xml结构对象 XmlStruct m_TempStruct; // 解析时,临时xml结构成员对象 XmlMember m_TempMember; // 用于判断结构父子关系的栈 std::stack<std::string> m_ChildName; // xml文件解析工具输入参数 public: std::string m_NameSpace; // 自定义命名空间 bool m_ThreadSpecific; // 是否需要线程本地表格数据 std::vector<std::string> m_XmlFileName; // 待处理的xml文件列表 std::string m_LoaderPath; // loader输出cpp代码路径 std::string m_HelperPath; // helper输出cpp代码路径 };
具体的代码生成包含两部分功能:
void ParseXml2LoaderH(const XmlParse& xmlParse)
void ParseXml2LoaderCpp(const XmlParse& xmlParse)
void ParseXml2HelperH(const XmlParse& xmlParse)
void ParseXml2HelperCpp(const XmlParse& xmlParse)
传入一个解析好的XmlParse对象,生成具体代码
Loader生成对应的读取代码,使用boost::ptree读取xml文件,转成相应的数据结构。
Helper生成一个空的辅助类,用于需要对数据重新组织的情况,比如配置中是按某个id列作为主键,存成一个map,提供查找,但是实际逻辑中还需要按某个名称列作为索引,再提供一个map,用于提供按名称查找(或者模糊查找),这时候就需要手动再提供一个新的查找函数,就可以写在helper中
main函数涉及两个小功能:
一个是遍历输入参数,解析名命名空间,待处理的xml文件,代码生成路径
一个是迭代每一个待处理的xml文件名,传入XmlParse解析,然后对解析完的结果,逐个生成相应代码
完整的代码,比较长,这里就不贴了
给一个生成后的代码的示例吧:
xml文件:
<Tests> <Node id="10000" pk="id"> <Time begin="2018-1-18 00:00:00" end="2018-1-18 23:59:59" rk="begin;end" num="1"/> <Time begin="2018-1-19 00:00:00" end="2018-1-19 23:59:59" num="1"/> <Time begin="2018-1-20 00:00:00" end="2018-1-20 23:59:59" num="1"/> </Node> <Node id="10001"> <Time begin="2018-1-18 00:00:00" end="2018-1-18 23:59:59" num="1"/> <Time begin="2018-1-19 00:00:00" end="2018-1-19 23:59:59" num="1"/> <Time begin="2018-1-20 00:00:00" end="2018-1-20 23:59:59" num="1"/> </Node> </Tasks>
生成的代码:
#ifndef __TestsXmlLoader_h__ #define __TestsXmlLoader_h__ #include <string> #include <vector> #include <map> #include "rangmap.h" namespace common { namespace xml { class Tests { public: class Node { public: class Time { public: Time(); Time(const Time& other); Time& operator=(const Time& other); ~Time(); time_t m_begin; time_t m_end; unsigned int m_num; }; public: Node(); Node(const Node& other); Node& operator=(const Node& other); ~Node(); void AddTime(time_t begin, time_t end, const Time& val); const Time* GetTime(time_t key) const; common::tool::rangmap<time_t, Time> m_Time; unsigned int m_id; }; public: Tests(); Tests(const Tests& other); Tests& operator=(const Tests& other); ~Tests(); void AddNode(unsigned int key, const Node& val); const Node* GetNode(unsigned int key) const; std::map<unsigned int, Node> m_Node; }; class TestsXmlLoader { public: TestsXmlLoader() { } ~TestsXmlLoader() { } bool LoadFile(const char* szPath); bool ReloadFile(const char* szPath); const Tests& GetTests() const; private: Tests m_Tests; }; } } #endif
放上完整工程的下载链接
工程中的boost库的路径为作者本机的路径,VS编译时请选择Release,重新配置boost库的include路径和lib路径
相关文章推荐
- SSH开源自动生成代码工具,可自动生成action、service、form、dao、model、vo、sqlmap.xml、.hbm.xml、test等
- SSH开源自动生成代码工具,可自动生成action、service、form、dao、model、vo、sqlmap.xml、.hbm.xml、test等
- android findview 自动生成工具 xml布局文件自动转换类模板代码工具
- [C#]一步一步开发自己的自动代码生成工具之四:简单三层代码模板实例Model层
- 2016.7.14 generator基于注解和基于xml自动生成代码的区别
- 微信小程序前端快速生成工具,让机器自动写代码
- 配置generatorConfig.xml自动生成的代码的sql书写问题
- ibatis - 自动代码生成工具abator 使用介绍
- 代码自动生成工具 MyGeneration
- ibatis代码自动生成工具ibator
- 【Mybatis】自动生成代码工具
- 代码自动生成工具(二)-miniproto的c++库实现
- mybatis自动生成代码工具(Mybatis-generator)
- 代码自动生成工具,2小时搞定智能硬件产品Demo
- 代码自动生成(二)数据库表字段生成mybaties 映射配置文件**mapper.xml
- Mybatis 自动生成代码工具
- [C#]一步一步开发自己的自动代码生成工具之五:DAL层模板
- Maven Web项目使用MyBatis_Generator_1.3.1自动生成javabean,dao,mapper.xml代码
- ibatis - 自动代码生成工具abator 使用介绍
- JAVA中Mybatis连接oracle数据库自动生成代码工具