XML配置文件读取类[DELPHI]
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
XML配置⽂件读取类[DELPHI]发现⽤INI做配置的话,实在有太多的东西难以描述,所以⾃⼰做了⼀个XML的配置⽂件存取类。
需要的同学可以直接拿去⽤,但希望尊重劳动成果,保留版权信息。
废话不多说,上代码!
1unit XMLConfig;
2{----------------------------------------------------------------------------}
3{ 这个单元⽤来处理XML配置⽂件,对配置⽂件格式有默认要求 }
4{ 格式为,只允许有⼀个root,然后root下对应配置⽂件, }
5{ 所有配置,均使⽤xml属性存取配置,属性中必须存在Name属性, }
6{ 不得单独使⽤下级Node }
7{ PS: 使⽤NativeXML库作为XML取数基本集,NativeXML请⾃⾏获取 }
8{ By Raymond.Zhang @ 2012.07.12 Mail: Acni.ray@ }
9{ Tebs Work Group }
10{----------------------------------------------------------------------------}
11interface
12uses
13 NativeXml, System.Classes, System.SysUtils, CommLib,
14 System.Generics.Collections;
15
16type
17
18 //为了⾃动释放的特性,使⽤接⼝
19{$REGION 'Interface'}
20 IConfigNode = interface
21 ['{67323F7D-9E6C-420B-BF1C-92457D829380}']
22function EnmuConfigNames: TStringList;
23function EnmuConfigValues: TStringList;
24function GetName: string;
25function GetValueByConfig(AConfig: string): string;
26function ValueWithDefault(AConfig: string; ADefualt: string):string;
27procedure DeleteConfig(const AConfig: string);
28procedure SetValueByConfig(AConfig: string; const Value: string);
29property Value[AConfig: string]: string read GetValueByConfig write SetValueByConfig; default;
30property Name: string read GetName;
31end;
32
33 IConfigNodes = interface
34 ['{56DBB6F5-BD64-4F07-A949-300877B1B787}']
35function AddConfigNode(AName: string): IConfigNode;
36function EnmuConfigNodes: TStringList;
37function GetConfigNodeByIndex(AIndex: Integer): IConfigNode;
38function GetConfigNodeByName(AName: string): IConfigNode;
39function GetConfigNodeCount: Integer;
40procedure DeleteConfig(AName: string);
41property ConfigNode[AName: string]: IConfigNode read GetConfigNodeByName; default;
42property Count: Integer read GetConfigNodeCount;
43property Nodes[AIndex: Integer]: IConfigNode read GetConfigNodeByIndex;
44end;
45
46 IRootNode = interface
47 ['{65213F85-0804-4FE1-A726-CFC0F082AC93}']
48function GetConfigsByType(AType: string): IConfigNodes;
49property Configs[AType: string]: IConfigNodes read GetConfigsByType; default;
50end;
51{$ENDREGION}
52
53 TConfigNode = class(TInterfacedObject, IConfigNode)
54private
55 FXMLNode: TXmlNode;
56function GetName: string;
57protected
58function GetValueByConfig(AConfig: string): string;
59procedure SetValueByConfig(AConfig: string; const Value: string);
60public
61constructor Create(AXmlNode: TXmlNode);
62destructor Destroy; override;
63function EnmuConfigNames: TStringList;
64function EnmuConfigValues: TStringList;
65function ValueWithDefault(AConfig: string; ADefualt: string):string;
66procedure DeleteConfig(const AConfig: string);
67property Value[AConfig: string]: string read GetValueByConfig write SetValueByConfig; default;
68property Name: string read GetName;
69end;
70
71 TConfigNodes = class(TInterfacedObject, IConfigNodes)
72private
73 FType: string;
74 FRootNode: TXmlNode;
75 FXmlNodes: TList<TXmlNode>;
76protected
77function GetConfigNodeByIndex(AIndex: Integer): IConfigNode;
78function GetConfigNodeByName(AName: string): IConfigNode;
79function GetConfigNodeCount: Integer;
80public
81constructor Create(const ARootNode: TXmlNode; const AType: string);
82destructor Destroy; override;
83function AddConfigNode(AName: string): IConfigNode;
84function EnmuConfigNodes: TStringList;
85procedure DeleteConfig(AName: string);
86property ConfigNode[AName: string]: IConfigNode read GetConfigNodeByName; default; 87property Count: Integer read GetConfigNodeCount;
88property Nodes[AIndex: Integer]: IConfigNode read GetConfigNodeByIndex;
89end;
90
91 TRootNode = class(TInterfacedObject, IRootNode)
92private
93 FRootNode: TXmlNode;
94public
95constructor Create(AXmlNode: TXmlNode);
96destructor Destroy; override;
97function GetConfigsByType(AType: string): IConfigNodes;
98end;
99
100 TXMLConfig = class(TObject)
101private
102 FAutoSave: Boolean;
103 FConfig: TNativeXml;
104 FConfigName: string;
105 FConfigPath: string;
106protected
107function GetRoot:IRootNode;
108public
109class function RegisterFileInfo(AFileInfo: IFileInfo): Boolean;
110constructor Create(ConfigName: string);
111destructor Destroy; override;
112procedure Save;
113property Root: IRootNode read GetRoot;
114property AutoSave: Boolean read FAutoSave write FAutoSave;
115end;
116
117implementation
118var
119 AppFileInfo: IFileInfo = nil;
120const
121 ConfigExt: string = '.config';
122 UnRegFileInfo: string = '⽂件接⼝未注册,⽆法获取配置⽂件路径!';
123
124{ TXMLConfig }
125
126constructor TXMLConfig.Create(ConfigName: string);
127begin
128if Assigned(AppFileInfo) then
129begin
130inherited Create;
131 FConfigName := ConfigName;
132 FConfigPath := AppFileInfo.ConfigPath + ConfigName + ConfigExt;
133 FConfig := TNativeXml.Create(nil);
134 FConfig.Charset := 'utf-8';
135 FConfig.XmlFormat := xfReadable;
136 FAutoSave := True;
137if FileExists(FConfigPath) then
138 FConfig.LoadFromFile(FConfigPath)
139else begin
140 FConfig.VersionString := '1.0';
141 := 'ConfigData';
142 Save;
143end;
144end else
145raise ERayException.Create(UnRegFileInfo);
146end;
147
148destructor TXMLConfig.Destroy;
149begin
150if FAutoSave then Save;
151 FreeAndNil(FConfig);
152inherited;
153end;
154
155function TXMLConfig.GetRoot: IRootNode;
156begin
157 Result := TRootNode.Create(FConfig.Root);
158end;
159
160class function TXMLConfig.RegisterFileInfo(AFileInfo: IFileInfo): Boolean;
161begin
162 Result := Supports(AFileInfo, IFileInfo, AppFileInfo);
163end;
164
165procedure TXMLConfig.Save;
166begin
167 FConfig.SaveToFile(FConfigPath);
168end;
169
170{ TConfigNode }
171
172constructor TConfigNode.Create(AXmlNode: TXmlNode);
173begin
174inherited Create();
175 FXMLNode := AXmlNode;
176end;
177
178procedure TConfigNode.DeleteConfig(const AConfig: string);
179begin
180 FXMLNode.AttributeByName[UTF8Encode(AConfig)].Delete;
181end;
182
183destructor TConfigNode.Destroy;
184begin
185 //这⾥不能释放Node,需要配合整个XML⼀起释放,若单独释放,会有意想不到的问题186 FXMLNode := nil;
187inherited;
188end;
189
190function TConfigNode.EnmuConfigNames: TStringList;
191var
192 I: Integer;
193begin
194 Result := TStringList.Create;
195for I := 0to FXMLNode.AttributeCount - 1do
196begin
197 Result.Add(FXMLNode.Attributes[i].NameUnicode);
198end;
199end;
200
201function TConfigNode.EnmuConfigValues: TStringList;
202var
203 I: Integer;
204begin
205 Result := TStringList.Create;
206for I := 0to FXMLNode.AttributeCount - 1do
207begin
208 Result.Add(FXMLNode.Attributes[i].ValueUnicode);
209end;
210end;
211
212function TConfigNode.GetName: string;
213begin
214 Result := FXMLNode.AttributeValueByNameWide['Name'];
215end;
216
217function TConfigNode.GetValueByConfig(AConfig: string): string;
218begin
219 Result := FXMLNode.AttributeValueByNameWide[UTF8Encode(AConfig)];
220end;
221
222procedure TConfigNode.SetValueByConfig(AConfig: string; const Value: string);
223var
224 AAttribute: TsdAttribute;
225begin
226 AAttribute := FXMLNode.AttributeByName[UTF8Encode(AConfig)];
227if Assigned(AAttribute) then
228begin
229 AAttribute.ValueUnicode := Value;
230end else
231begin
232 FXMLNode.AttributeAdd(UTF8Encode(AConfig), UTF8Encode(Value));
233end;
234 AAttribute := nil;
235end;
236
237function TConfigNode.ValueWithDefault(AConfig, ADefualt: string): string;
238begin
239 Result := Value[AConfig];
240if Result = EmptyStr then
241begin
242 Value[AConfig] := ADefualt;
243 Result := ADefualt;
244end;
245end;
246
247{ TConfigNodes }
248
249function TConfigNodes.AddConfigNode(AName: string): IConfigNode;
250var
251 AXmlNode: TXmlNode;
252begin
253 Result := GetConfigNodeByName(AName);
254if Result = nil then
255begin
256 AXmlNode := FRootNode.NodeNew(UTF8Encode(FType));
257 AXmlNode.AttributeAdd('Name',UTF8Encode(AName));
258 FXmlNodes.Add(AXmlNode);
259 Result := TConfigNode.Create(AXmlNode);
260end;
261 AXmlNode := nil;
262end;
263
264constructor TConfigNodes.Create(const ARootNode: TXmlNode; const AType: string); 265var
266 I: Integer;
267begin
268inherited Create();
269 FRootNode := ARootNode;
270 FXmlNodes := TList<TXmlNode>.Create;
271 FType := AType;
272for I := 0to ARootNode.ElementCount - 1do
273begin
274if ARootNode.Elements[i].NameUnicode = AType then
275begin
276 FXmlNodes.Add(ARootNode.Elements[i]);
277end;
278end;
279end;
280
281procedure TConfigNodes.DeleteConfig(AName: string);
282var
283 I: Integer;
284begin
285for I := 0to FXmlNodes.Count - 1do
286begin
287if FXmlNodes[i].AttributeValueByNameWide['Name'] = AName then
288begin
289 FXmlNodes[i].Delete;
290 FXmlNodes.Delete(i);
291 Exit;
292end;
293end;
294end;
295
296destructor TConfigNodes.Destroy;
297begin
298 FreeAndNil(FXmlNodes);
299inherited;
300end;
301
302function TConfigNodes.EnmuConfigNodes: TStringList;
303var
304 I: Integer;
305begin
306 Result := TStringList.Create;
307for I := 0to FXmlNodes.Count - 1do
308begin
309 Result.Add(FXmlNodes[i].AttributeValueByNameWide['Name']);
310end;
311end;
312
313function TConfigNodes.GetConfigNodeByIndex(AIndex: Integer): IConfigNode;
314begin
315 Result := TConfigNode.Create(FXmlNodes[AIndex]);
316end;
317
318function TConfigNodes.GetConfigNodeByName(AName: string): IConfigNode;
319var
320 I: Integer;
321begin
322 Result := nil;
323for I := 0to FXmlNodes.Count - 1do
324begin
325if FXmlNodes[i].AttributeValueByNameWide['Name'] = AName then
326begin
327 Result := TConfigNode.Create(FXmlNodes[i]);
328 Exit;
329end;
330end;
331end;
332
333function TConfigNodes.GetConfigNodeCount: Integer;
334begin
335 Result := FXmlNodes.Count;
336end;
337
338{ TRootNode }
339
340constructor TRootNode.Create(AXmlNode: TXmlNode);
341begin
342inherited Create();
343 FRootNode := AXmlNode;
344end;
345
346destructor TRootNode.Destroy;
347begin
348 // 不能释放,等待随主类释放
349 FRootNode := nil;
350inherited;
351end;
352
353function TRootNode.GetConfigsByType(AType: string): IConfigNodes;
354begin
355 Result := TConfigNodes.Create(FRootNode, AType);
356end;
357
358end.
因为项⽬特性,⾥⾯有注册FILEINFO的接⼝,这是我⾃⼰项⽬中的⼀个全局⽂件管理类。
若⼤家不需要的话,直接更换成⾃⼰的配置⽂件⽬录就好了。
调⽤例⼦:
1procedure TFrm1.Btn1Click(Sender: TObject);
2var
3 AServerList : TStrings ;
4 ILoginInfo: IConfigNode;
5begin
6 //获取服务器列表
7 AServerList := AppServerConfig.Root['AppServer'].EnmuConfigNodes;
8 CbxServer.Properties.Items.AddStrings(AServerList);
9 FreeAndNil(AServerList);
10 ILoginInfo := UserConfig.Root['LoginInfo'].AddConfigNode('Default');
11 //读取上次登录的⽤户名
12 TxtUserName.Text := ILoginInfo['LastUser'];
13 //读取上次登录的服务器名
14 CbxServer.Text := ILoginInfo['LastServer'];
15 ILoginInfo := nil;
16end;
配置⽂件样式:
1<?xml encoding="utf-8" version="1.0"?>
2<ConfigData>
3<LoginInfo Name="Default" LastUser="Test" LastServer="Test" LastRole=""/>
4<ReportDlgCfg Name="Default" ShowPrintDlg="0" ShowExportDlg="0" AutoCreateDir="0" OpenFile="0" LastPrinter="Microsoft XPS Document Writer"/>
5</ConfigData>。