Sign in Join
Wiki copytemporary

xmlconf: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11Unit XMLConf provides the TXMLConfig component. It uses a TXMLDocument object to do the work of reading and writing the XMLfile, but descends directly from TComponent.
22
33##### Disclaimer
44
55This documentation is not authoritative, it is based on the usual process of (1) examining the source code (2) experimentation (3) pondering "I wonder if that is what the author had in mind ?"
66
77## Configuration
88
99##### property Filename: String (published)
1010
1111The file name of the xml file. Setting the filename to a different name:
1212
1313- Flushes the current xml file.
1414- Frees the xmldocument object
1515- If *Filename* exists and *StartEmpty* is false:
1616 - A new xmldocument is created by reading the file, which must have the same root element as *RootName* otherwise an exception is raised.
1717 - Otherwise, a new xmldocument object is created with root element *RootName*
1818
1919*I have not checked this by experiment, but it appears that an empty xmldocument is created (in memory) when the component is created, and this can be modified. However, it cannot be saved until it has a file name - there is no default file name - hence all modifications will inevitably be lost when the file name is set.*
2020
2121##### property StartEmpty: Boolean (published)
2222
2323Controls whether an existing xmlfile is read from *Filename*.
2424
2525- Default is false - an existing file is read.
2626
2727##### property RootName: DOMString (published)
2828
2929The name of the root element in the file. Must match the value in the file when an existing file is read.
3030
3131- Default is 'CONFIG'. *It is simplest to leave this alone unless you have a good reason to change it.*
3232
3333##### procedure Flush (public)
3434
3535Writes the xml file - as long as there is a file name set.
3636
3737##### procedure Clear (public)
3838
3939Recreates the xmldocument as an empty document.
4040
4141##### constructor Create(AOwner: TComponent) (public)
4242
4343##### destructor Destroy (public)
4444
4545## Working with keys and paths
4646
4747XMLConfig maintains a "stack" of paths (as an array of widestrings). The overall path to an element might be
4848
49-` <rootName>/key1/key2/key3/key4/value="some_value".  `
49+```text
50+ <rootName>/key1/key2/key3/key4/value="some_value".
51+```
5052
5153This would appear in the file
5254
53-` <CONFIG><key1><key2><key3><key4 value="some_value"/></key3></key2></key1></CONFIG`
55+```text
56+ <CONFIG><key1><key2><key3><key4 value="some_value"/></key3></key2></key1></CONFIG
57+```
5458
5559(neglecting any other elements). However, the path stack can contain paths, not just nodes, so it could be four elements deep as key1;key2; key3;key4, but just as well only two elements as key1/key2;key3/key4, or three elements as key1;key2/key3;key4.
5660
5761Further, when reading or setting a value, a complete path can then be specified, so the path "stack" can be completely ignored and the full path (past *RootName*) specified for each value. Each value has an effective path, and the path stack is just a convenient way of getting to a specific effective path.
5862
5963##### procedure OpenKey(const aPath: WideString) (public)
6064
6165"Pushes" aPath onto the stack. If the effective path was \<RootName\>/key1, and aPath = key2/key3, after the call to OpenKey, the effective path is \<RootName\>/key1/key2/key3.
6266
6367##### procedure CloseKey (public)
6468
6569"Pops" the top path off the stack. Note that this is the last entered path, NOT the top element. Thus after the OpenKey example above followed by a CloseKey call, the stack reverts to \<RootName\>/key1, not \<RootName\>/key1/key2
6670
6771##### procedure ResetKey (public)
6872
6973Completely clears the stack. The effetive path reverts to \<RootName\>
7074
7175## Setting, Getting and Deleting Values
7276
7377All values are actually read and written as strings, with other overloaded types providing defined 'AsString' translations.
7478
7579##### function GetValue(const APath: WideString; const ADefault: WideString): WideString (public)\
7680procedure SetValue(const APath: WideString; const AValue: WideString) (public)
7781
7882Sets or Gets a string value from *RootName*/*Effective_path_from_stack*/*APath*. The path is created if it does not exist on Setting, and ADefault is returned if the path does not exist on Getting.
7983
8084##### function GetValue(const APath: WideString; ADefault: Integer): Integer; (public)\
8185procedure SetValue(const APath: WideString; AValue: Integer); (public)
8286
8387The integer values are converted to/from strings using IntToStr and strToIntDef
8488
8589##### function GetValue(const APath: WideString; ADefault: Boolean): Boolean; (public)\
8690procedure SetValue(const APath: WideString; AValue: Boolean); (public)
8791
8892The boolean values are stored as "True" or "False".
8993
9094*Warning - some other FCL/LCL XML components (eg those descended from TCustomPropertyStorage, such as TXMLPropStorage) store booleans using integer values, despite using XMLConifg as the storage component. This is, of course, only a problem if you use the same files from both components, or switch from one to the other during development, as I did.*
9195
9296##### procedure SetDeleteValue(const APath: WideString; const AValue, DefValue: WideString); (public)\
9397procedure SetDeleteValue(const APath: WideString; AValue, DefValue: Integer); (public)\
9498procedure SetDeleteValue(const APath: WideString; AValue, DefValue: Boolean); (public)
9599
96100If AValue = DefValue, the element is deleted. Otherwise, it is set to AValue.
97101
98102*I have not used this, but presumably could be used to store eg values of properties with well defined defaults only when they were different from the defaults.*
99103
100104##### procedure DeletePath(const APath: WideString); (public)
101105
102106Deletes **everything** beyond path APath
103107
104108##### procedure DeleteValue(const APath: WideString); (public)
105109
106110Deletes a **value** specified by APath. If APath does not specify a value , it does nothing
107111
108112##### property Modified: Boolean read FModified; (public)
109113
110114Allows you to see if the xmldocument has been modified, and hence, needs to be flushed. *However, flush does nothing if the document is not modified, so it is easier just to call flush anyway.*
111115
112116## Example
113117
114118The following sequence of instructions:
115119
116-` XmlConfig1.Filename := FILE_NAME ;        // reads the file if it already exists, but...`\
117-` XmlConfig1.Clear ;                        // if the file already exists, clear the data, we want to start from scratch`\
118-` XmlConfig1.SetValue ('L1/L2/L3', '333') ; // add a few data`\
119-` XmlConfig1.SetValue ('L1/L2/L4', '44') ;`\
120-` XmlConfig1.SetValue ('L1/L2/L3', '33') ;  // this will overwrite the previous value`\
121-` XmlConfig1.OpenKey  ('L1/L2') ;           // from now on, all keys will be relative to L1/L2`\
122-` XmlConfig1.SetValue ('Lm', 'mm') ;        // these will be added in L1/L2`\
123-` XmlConfig1.SetValue ('Lm/Ln', 'nn') ;`\
124-` XmlConfig1.SetValue ('/Lx/Ly', 'yy') ;    // but because of the initial "/", this will be added to the root`\
125-` XmlConfig1.CloseKey ;`\
126-` XmlConfig1.SetValue ('L6/L7', '77') ;     // L6 will be deleted`\
127-` XmlConfig1.SetValue ('L9', '99') ;`\
128-` XmlConfig1.SetValue ('L9/L99', '9999') ;  // the previous L9 was an attibute, this one will be a node`\
129-` XmlConfig1.DeletePath ('L6') ;`\
130-` XmlConfig1.Flush ;`
120+``` pascal
121+ XmlConfig1.Filename := FILE_NAME ; // reads the file if it already exists, but...
122+ XmlConfig1.Clear ; // if the file already exists, clear the data, we want to start from scratch
123+ XmlConfig1.SetValue ('L1/L2/L3', '333') ; // add a few data
124+ XmlConfig1.SetValue ('L1/L2/L4', '44') ;
125+ XmlConfig1.SetValue ('L1/L2/L3', '33') ; // this will overwrite the previous value
126+ XmlConfig1.OpenKey ('L1/L2') ; // from now on, all keys will be relative to L1/L2
127+ XmlConfig1.SetValue ('Lm', 'mm') ; // these will be added in L1/L2
128+ XmlConfig1.SetValue ('Lm/Ln', 'nn') ;
129+ XmlConfig1.SetValue ('/Lx/Ly', 'yy') ; // but because of the initial "/", this will be added to the root
130+ XmlConfig1.CloseKey ;
131+ XmlConfig1.SetValue ('L6/L7', '77') ; // L6 will be deleted
132+ XmlConfig1.SetValue ('L9', '99') ;
133+ XmlConfig1.SetValue ('L9/L99', '9999') ; // the previous L9 was an attibute, this one will be a node
134+ XmlConfig1.DeletePath ('L6') ;
135+ XmlConfig1.Flush ;
136+```
131137
132138will give this XML:
133139
134-` <?xml version="1.0" encoding="utf-8"?>`\
135-` <CONFIG L9="99">`\
136-`   <L1>`\
137-`     <L2 L3="33" L4="44" Lm="mm">`\
138-`       <Lm Ln="nn"/>`\
139-`     </L2>`\
140-`   </L1>`\
141-`   <Lx Ly="yy"/>`\
142-`   <L9 L99="9999"/>`\
143-` </CONFIG>`
140+```text
141+ <?xml version="1.0" encoding="utf-8"?>
142+ <CONFIG L9="99">
143+ <L1>
144+ <L2 L3="33" L4="44" Lm="mm">
145+ <Lm Ln="nn"/>
146+ </L2>
147+ </L1>
148+ <Lx Ly="yy"/>
149+ <L9 L99="9999"/>
150+ </CONFIG>
151+```
144152
145153Note that the last item in the aPath parameter for SetValue is actually an attribute: XmlConfig1.SetValue ('L1/L2/L3', '333') actually sets attribute L3 for element L1/L2.
146154
147155------------------------------------------------------------------------
148156
149157## See also
150158
151159- XMLConf/TXMLConf is provided by the [[fcl-xml]] package.
152160
153161---
154162*From the Free Pascal wiki, page "xmlconf", as it stood on 2022-01-02 after a change by FTurtle, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history