现在
				,
				越来越多的程序使用
				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.