xmlcfg.pp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. {
  2. $Id$
  3. This file is part of the Free Component Library
  4. Implementation of TXMLConfig class
  5. Copyright (c) 1999 - 2001 by Sebastian Guenther, [email protected]
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {
  13. TXMLConfig enables applications to use XML files for storing their
  14. configuration data
  15. }
  16. {$MODE objfpc}
  17. {$H+}
  18. unit XMLCfg;
  19. interface
  20. {off $DEFINE MEM_CHECK}
  21. uses
  22. {$IFDEF MEM_CHECK}MemCheck,{$ENDIF}
  23. Classes, DOM, XMLRead, XMLWrite;
  24. type
  25. {"APath" is the path and name of a value: A XML configuration file is
  26. hierachical. "/" is the path delimiter, the part after the last "/"
  27. is the name of the value. The path components will be mapped to XML
  28. elements, the name will be an element attribute.}
  29. TXMLConfig = class(TComponent)
  30. private
  31. FFilename: String;
  32. procedure SetFilename(const AFilename: String);
  33. protected
  34. doc: TXMLDocument;
  35. FModified: Boolean;
  36. fDoNotLoad: boolean;
  37. procedure Loaded; override;
  38. function FindNode(const APath: String; PathHasValue: boolean): TDomNode;
  39. public
  40. constructor Create(const AFilename: String); overload;
  41. constructor CreateClean(const AFilename: String);
  42. destructor Destroy; override;
  43. procedure Clear;
  44. procedure Flush; // Writes the XML file
  45. function GetValue(const APath, ADefault: String): String;
  46. function GetValue(const APath: String; ADefault: Integer): Integer;
  47. function GetValue(const APath: String; ADefault: Boolean): Boolean;
  48. procedure SetValue(const APath, AValue: String);
  49. procedure SetDeleteValue(const APath, AValue, DefValue: String);
  50. procedure SetValue(const APath: String; AValue: Integer);
  51. procedure SetDeleteValue(const APath: String; AValue, DefValue: Integer);
  52. procedure SetValue(const APath: String; AValue: Boolean);
  53. procedure SetDeleteValue(const APath: String; AValue, DefValue: Boolean);
  54. procedure DeletePath(const APath: string);
  55. procedure DeleteValue(const APath: string);
  56. property Modified: Boolean read FModified;
  57. published
  58. property Filename: String read FFilename write SetFilename;
  59. end;
  60. // ===================================================================
  61. implementation
  62. uses SysUtils;
  63. constructor TXMLConfig.Create(const AFilename: String);
  64. begin
  65. inherited Create(nil);
  66. SetFilename(AFilename);
  67. end;
  68. constructor TXMLConfig.CreateClean(const AFilename: String);
  69. begin
  70. inherited Create(nil);
  71. fDoNotLoad:=true;
  72. SetFilename(AFilename);
  73. end;
  74. destructor TXMLConfig.Destroy;
  75. begin
  76. if Assigned(doc) then
  77. begin
  78. Flush;
  79. doc.Free;
  80. end;
  81. inherited Destroy;
  82. end;
  83. procedure TXMLConfig.Clear;
  84. var
  85. cfg: TDOMElement;
  86. begin
  87. // free old document
  88. doc.Free;
  89. // create new document
  90. doc := TXMLDocument.Create;
  91. cfg :=TDOMElement(doc.FindNode('CONFIG'));
  92. if not Assigned(cfg) then begin
  93. cfg := doc.CreateElement('CONFIG');
  94. doc.AppendChild(cfg);
  95. end;
  96. end;
  97. procedure TXMLConfig.Flush;
  98. begin
  99. if Modified then
  100. begin
  101. WriteXMLFile(doc, Filename);
  102. FModified := False;
  103. end;
  104. end;
  105. function TXMLConfig.GetValue(const APath, ADefault: String): String;
  106. var
  107. Node, Child, Attr: TDOMNode;
  108. NodeName: String;
  109. PathLen: integer;
  110. StartPos, EndPos: integer;
  111. begin
  112. Result:=ADefault;
  113. PathLen:=length(APath);
  114. Node := doc.DocumentElement;
  115. StartPos:=1;
  116. while True do begin
  117. EndPos:=StartPos;
  118. while (EndPos<=PathLen) and (APath[EndPos]<>'/') do inc(EndPos);
  119. if EndPos>PathLen then break;
  120. SetLength(NodeName,EndPos-StartPos);
  121. Move(APath[StartPos],NodeName[1],EndPos-StartPos);
  122. StartPos:=EndPos+1;
  123. Child := Node.FindNode(NodeName);
  124. if not Assigned(Child) then exit;
  125. Node := Child;
  126. end;
  127. if StartPos>PathLen then exit;
  128. SetLength(NodeName,PathLen-StartPos+1);
  129. Move(APath[StartPos],NodeName[1],length(NodeName));
  130. Attr := Node.Attributes.GetNamedItem(NodeName);
  131. if Assigned(Attr) then
  132. Result := Attr.NodeValue;
  133. end;
  134. function TXMLConfig.GetValue(const APath: String; ADefault: Integer): Integer;
  135. begin
  136. Result := StrToIntDef(GetValue(APath, IntToStr(ADefault)),ADefault);
  137. end;
  138. function TXMLConfig.GetValue(const APath: String; ADefault: Boolean): Boolean;
  139. var
  140. s: String;
  141. begin
  142. if ADefault then
  143. s := 'True'
  144. else
  145. s := 'False';
  146. s := GetValue(APath, s);
  147. if AnsiCompareText(s,'TRUE')=0 then
  148. Result := True
  149. else if AnsiCompareText(s,'FALSE')=0 then
  150. Result := False
  151. else
  152. Result := ADefault;
  153. end;
  154. procedure TXMLConfig.SetValue(const APath, AValue: String);
  155. var
  156. Node, Child: TDOMNode;
  157. NodeName: String;
  158. PathLen: integer;
  159. StartPos, EndPos: integer;
  160. begin
  161. Node := Doc.DocumentElement;
  162. PathLen:=length(APath);
  163. StartPos:=1;
  164. while True do begin
  165. EndPos:=StartPos;
  166. while (EndPos<=PathLen) and (APath[EndPos]<>'/') do inc(EndPos);
  167. if EndPos>PathLen then break;
  168. SetLength(NodeName,EndPos-StartPos);
  169. Move(APath[StartPos],NodeName[1],EndPos-StartPos);
  170. StartPos:=EndPos+1;
  171. Child := Node.FindNode(NodeName);
  172. if not Assigned(Child) then
  173. begin
  174. Child := Doc.CreateElement(NodeName);
  175. Node.AppendChild(Child);
  176. end;
  177. Node := Child;
  178. end;
  179. if StartPos>PathLen then exit;
  180. SetLength(NodeName,PathLen-StartPos+1);
  181. Move(APath[StartPos],NodeName[1],length(NodeName));
  182. if (not Assigned(TDOMElement(Node).GetAttributeNode(NodeName))) or
  183. (TDOMElement(Node)[NodeName] <> AValue) then
  184. begin
  185. TDOMElement(Node)[NodeName] := AValue;
  186. FModified := True;
  187. end;
  188. end;
  189. procedure TXMLConfig.SetDeleteValue(const APath, AValue, DefValue: String);
  190. begin
  191. if AValue=DefValue then
  192. DeleteValue(APath)
  193. else
  194. SetValue(APath,AValue);
  195. end;
  196. procedure TXMLConfig.SetValue(const APath: String; AValue: Integer);
  197. begin
  198. SetValue(APath, IntToStr(AValue));
  199. end;
  200. procedure TXMLConfig.SetDeleteValue(const APath: String; AValue,
  201. DefValue: Integer);
  202. begin
  203. if AValue=DefValue then
  204. DeleteValue(APath)
  205. else
  206. SetValue(APath,AValue);
  207. end;
  208. procedure TXMLConfig.SetValue(const APath: String; AValue: Boolean);
  209. begin
  210. if AValue then
  211. SetValue(APath, 'True')
  212. else
  213. SetValue(APath, 'False');
  214. end;
  215. procedure TXMLConfig.SetDeleteValue(const APath: String; AValue,
  216. DefValue: Boolean);
  217. begin
  218. if AValue=DefValue then
  219. DeleteValue(APath)
  220. else
  221. SetValue(APath,AValue);
  222. end;
  223. procedure TXMLConfig.DeletePath(const APath: string);
  224. var
  225. Node: TDomNode;
  226. begin
  227. Node:=FindNode(APath,false);
  228. if (Node=nil) or (Node.ParentNode=nil) then exit;
  229. Node.ParentNode.RemoveChild(Node);
  230. FModified := True;
  231. end;
  232. procedure TXMLConfig.DeleteValue(const APath: string);
  233. var
  234. Node: TDomNode;
  235. StartPos: integer;
  236. NodeName: string;
  237. begin
  238. Node:=FindNode(APath,true);
  239. if (Node=nil) then exit;
  240. StartPos:=length(APath);
  241. while (StartPos>0) and (APath[StartPos]<>'/') do dec(StartPos);
  242. NodeName:=copy(APath,StartPos+1,length(APath)-StartPos);
  243. if (not Assigned(TDOMElement(Node).GetAttributeNode(NodeName))) then exit;
  244. TDOMElement(Node).RemoveAttribute(NodeName);
  245. FModified := True;
  246. end;
  247. procedure TXMLConfig.Loaded;
  248. begin
  249. inherited Loaded;
  250. if Length(Filename) > 0 then
  251. SetFilename(Filename); // Load the XML config file
  252. end;
  253. function TXMLConfig.FindNode(const APath: String;
  254. PathHasValue: boolean): TDomNode;
  255. var
  256. NodePath: String;
  257. StartPos, EndPos: integer;
  258. PathLen: integer;
  259. begin
  260. Result := doc.DocumentElement;
  261. PathLen:=length(APath);
  262. StartPos:=1;
  263. while (Result<>nil) do begin
  264. EndPos:=StartPos;
  265. while (EndPos<=PathLen) and (APath[EndPos]<>'/') do inc(EndPos);
  266. if (EndPos>PathLen) and PathHasValue then exit;
  267. if EndPos=StartPos then break;
  268. SetLength(NodePath,EndPos-StartPos);
  269. Move(APath[StartPos],NodePath[1],length(NodePath));
  270. Result := Result.FindNode(NodePath);
  271. StartPos:=EndPos+1;
  272. if StartPos>PathLen then exit;
  273. end;
  274. Result:=nil;
  275. end;
  276. procedure TXMLConfig.SetFilename(const AFilename: String);
  277. var
  278. cfg: TDOMElement;
  279. begin
  280. {$IFDEF MEM_CHECK}CheckHeapWrtMemCnt('TXMLConfig.SetFilename A '+AFilename);{$ENDIF}
  281. if FFilename = AFilename then exit;
  282. FFilename := AFilename;
  283. if csLoading in ComponentState then
  284. exit;
  285. if Assigned(doc) then
  286. begin
  287. Flush;
  288. doc.Free;
  289. end;
  290. doc:=nil;
  291. if FileExists(AFilename) and (not fDoNotLoad) then
  292. ReadXMLFile(doc,AFilename);
  293. if not Assigned(doc) then
  294. doc := TXMLDocument.Create;
  295. cfg :=TDOMElement(doc.FindNode('CONFIG'));
  296. if not Assigned(cfg) then begin
  297. cfg := doc.CreateElement('CONFIG');
  298. doc.AppendChild(cfg);
  299. end;
  300. {$IFDEF MEM_CHECK}CheckHeapWrtMemCnt('TXMLConfig.SetFilename END');{$ENDIF}
  301. end;
  302. end.
  303. {
  304. $Log$
  305. Revision 1.6 2004-11-05 22:32:28 peter
  306. * merged xml updates from lazarus
  307. }