hdqqq

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  35 随笔 :: 0 文章 :: 104 评论 :: 0 Trackbacks

 

现在 , 越来越多的程序使用 xml 文件作为应用程序的配置文件 , windows 平台上 , 一般的程序使用微软的 msxml 接口来读写 xml 文件 .

xml 文件原则上可以存储任意形式的数据 , 比如象点坐标 , 颜色 rgb , 矩形坐标 , 字符串 , 数值或者其他自己定义的数据结构等 . 如果 xml 需要存储结构化的数据列 , 或者存储在 xml 文件中的数据因为逻辑或者业务的原因存在结构上的嵌套包含关系 , 比如要存储某个窗口的位置 , 标题 , 坐标等情况 , 还要存储这个窗口的子窗口的相同信息 .

在情况下 , 会存在下列几个问题

1. 应用程序配置结构和 xml 读写操作过于耦合 , 如果要将不同的结构写入 xml 文件 , 需要操作 msxml 调用不同的接口 , 而一旦这些配置结构发生改变 , 将需要同时修改 xml 文件的读写代码 . 对于不同的配置结构 , 就需要写不同的 xml 读写操作 , 代码重用性不高 .

2. 对于多个数据对象和有嵌套包含关系的数据结构而言 , 还需要自己实现循环语句对 xml 文件中的对象进行读写 .

 

本文实现了一个 xml 读写和自身结构无关的类模板 , 并且支持结构嵌套 , 简化了 xml 的读写操作 , 需要 Loki for vc6 库支持 .

 

如想要存储一组 web 站点的结构 , 包括 url(string), 端口 (int), 用户名 (string), 口令 (string)

 

可以定义下面的类结构 :

 

class __app_config : public Xml_Attribute_List <TYPELIST_1( XML_ATTR_NULLTYPE )>

{

public :

       __app_config () {

              SetTagName ( _T ( "AppConfig" ));

       }

       ~ __app_config () {}

};

 

typedef Xml_Config_Node < __app_config > AppConfigRoot ;

 

class __site_info : public

Xml_Attribute_List <TYPELIST_4( XML_ATTR_CSTRING , XML_ATTR_INT , XML_ATTR_CSTRING , XML_ATTR_CSTRING )>

{

public :

       __site_info () {

              SetTagName ( _T ( "WebSite" ));

              SetAttributeName ( _T ( "url" ), _T ( "port" ), _T ( "username" ), _T ( "password" ));

       }

       ~ __site_info () {}

 

       GET_SET_ATTR4 ( url , port ,username,password, TYPELIST_4( XML_ATTR_CSTRING , XML_ATTR_INT , XML_ATTR_CSTRING , XML_ATTR_CSTRING ))

 

};

 

typedef Xml_Config_Node < __site_info > WebSiteInfoNode ;

 

 

typedef XmlConfigNodeFactory <TYPELIST_2( AppConfigRoot , WebSiteInfoNode )> NodeCreateFactory ;

 

typedef XmlConfigFile < AppConfigRoot , NodeCreateFactory > AppConfigFileBase ;

 

class AppConfigFile : public AppConfigFileBase

{

public :

       void AddSiteInfo ( LPCTSTR url , int port , LPCTSTR user , LPCTSTR pwd ) {

              WebSiteInfoNode * pnode = new WebSiteInfoNode ;

              pnode -> GetAttribute ().Set_url( url );

              pnode -> GetAttribute (). Set_port ( port );

              pnode -> GetAttribute (). Set_username ( user );

              pnode -> GetAttribute (). Set_password ( pwd );

              GetRoot (). AddChildNode ( pnode );

 

       }

 

       int GetSiteInfoCount () {

              return GetRoot (). GetChildCount ();

       }

 

       WebSiteInfoNode * GetSiteInfo ( int index ) {

              Xml_NodeData_Base * pbase = GetRoot (). GetChildNode ( index );

              if ( pbase ) {

                     WebSiteInfoNode * pnode = ( WebSiteInfoNode *) pbase ;

                     return pnode ;

              } else {

                     return NULL ;

              }

       }

 

public :

       AppConfigFile () {}

       ~ AppConfigFile () {}

      

};

 

配置信息存储和加载的代码

 

void SaveConfig ()

{

       AppConfigFile lconfigfile ;

       lconfigfile . AddSiteInfo ( "192.168.0.1" , 80 , "guest" , "hello" );

       lconfigfile . AddSiteInfo ( "192.168.0.2" , 80 , "guest" , "hello" );

       lconfigfile . AddSiteInfo ( "192.168.0.3" , 80 , "guest" , "hello" );

       lconfigfile . AddSiteInfo ( "192.168.0.4" , 80 , "test" , "hi" );

       lconfigfile . SaveToXmlFile ( "c:\\test.xml" );

}

 

void output_config ( WebSiteInfoNode * pnode )

{

       if ( pnode ) {

              cout << ( LPCTSTR ) pnode -> GetAttribute ().Get_url() << "  " ;

              cout << pnode -> GetAttribute (). Get_port () << " " ;

              cout << ( LPCTSTR ) pnode -> GetAttribute (). Get_username () << " " ;

              cout << ( LPCTSTR ) pnode -> GetAttribute (). Get_password () << endl ;

       }

}

 

void LoadConfig ()

{

       AppConfigFile lconfigfile ;

       lconfigfile . LoadFromXmlFile ( "c:\\test.xml" );

       int i , count ;

       count = lconfigfile . GetSiteInfoCount ();

       if ( count > 0 ) {

              for ( i = 0 ; i < count ; i ++) {

                     WebSiteInfoNode * pnode = lconfigfile . GetSiteInfo ( i );

                     output_config ( pnode );

              }

       }

}

 

        可以看见,在代码中,没有具体的有关xml文件的读写操作的,涉及的只是于业务相关的数据结构的定义和存取操作,同时,在业务需求发生变化或者需要添加新的业务结构时,只需要修改业务结构定义和定义新的业务结构并将其加入节点创建工厂就可以了.

 

代码下载

http://www.cppblog.com/Files/hdqqq/xml_config_file.rar

 

附加说明 :

代码中使用抽象工厂作来创建节点对象 , 对于存储于 xml 文件中的结构 , 采用 md5 hash 值作为每个结构的 id.

 

posted on 2006-02-13 16:17 hdqqq 阅读(7171) 评论(9)  编辑 收藏 引用 所属分类: c/c++

评论

# re: 一个读取xml配置文件的通用模板 2007-01-20 21:04 noname
看起来不错.
想下载源码看看. 但是连接不可用.
能否发送到邮箱lieph(AT)163(DOT)com?
谢谢  回复  更多评论
  

# re: 一个读取xml配置文件的通用模板 2007-01-21 00:04 hdqqq_
@noname
邮件已经发了,不知道cppblog这么回事,文件都不能下载了.  回复  更多评论
  

# re: 一个读取xml配置文件的通用模板 2007-01-22 16:57 dudu
@hdqqq_
我这里可以下载,你再试试。  回复  更多评论
  

# re: 一个读取xml配置文件的通用模板 2007-07-01 14:38 无心
你好,我也想下载下来看看,但是的确无法下载,能否给我也发送一份?谢谢了
year-2002@163.com  回复  更多评论
  

# re: 一个读取xml配置文件的通用模板 2007-07-01 14:49 无心
已经下载了,需要暂停一下,然后再连接就OK了,奇怪的事情
谢谢共享 :)  回复  更多评论
  

# re: 一个读取xml配置文件的通用模板 2007-09-11 17:14 abware
楼主,请问loki for vc6 在哪能下载?  回复  更多评论
  

# re: 一个读取xml配置文件的通用模板[未登录] 2007-09-11 18:00 hdqqq
我这里有,留个mail地址我发给你.  回复  更多评论
  

# re: 一个读取xml配置文件的通用模板 2007-09-12 09:07 hdqqq
loki for vc6 我已经上传了,下载地址.
http://www.cppblog.com/Files/hdqqq/lokiVC6port.zip  回复  更多评论
  

# re: 一个读取xml配置文件的通用模板 2007-09-12 14:57 abware
谢谢,学习中。
还用了汇编...我没用过汇编啊...  回复  更多评论
  


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理