Click here to Skip to main content
Click here to Skip to main content

Read and Write application parameters in XML

By , 30 Jun 2003
 

Sample Image - maximum width is 600 pixels

Introduction

This article provides an easy way to load and save the parameters of an application in XML format.

XML is a convenient format to deal with the parameters of applications for the following reasons:

  • It's text, so you can easily check the values and modify them with a classical editor (by the way, IE 5.0 shows XML in a very nice way).
  • It's based on a tree so you can have your parameters saved in a structured way.
  • It's platform and language independent.
My goal was not to parse an XML file, but to give an easy way to read and write the data. So the code is based on A simple STL based XML parser by David Hubbard. I would really like to thank him for his parser, it's a very good work! Moreover it saved me a lot of time, even if I made a few modifications in his original code to fulfill my goals.

The code is entirely based on STL. It compiles on linux, too. I guess it will compile on any other platform/compiler that supports STL.

Using the code

Now let's take an example to explain more precisely what you can do with ParamIO. Let's assume you have an application to show some text on the screen in a given color and in a given font (the demo project). The parameters of your application will be the text (1 string), the color (3 values RGB) and the font (1 string for the font name and 1 double for the font size). You want to be able to save those parameters on the disk and load them for a later use. A nice XML file containing those values can look like this:

<PARAMS>
  <TEXT>Hello world</TEXT>
  <COLOR>
	<RED>50</RED>
	<GREEN>128</GREEN>
	<BLUE>255</BLUE>
  </COLOR>
  <FONT>
	<NAME>Arial</NAME>
	<SIZE>12.0</SIZE>
  </FONT>
</PARAMS>
Let's say we have the following variables in the application :
std::string _text;                 // The text
int _red, _green, _blue;           // color
std::string _fontName;             // font name
double _fontSize;                  // font size
The code to write the previous file will be :
ParamIO outXml;

outXml.write("PARAMS:TEXT", _text);

outXml.write("PARAMS:COLOR:RED",   _red);
outXml.write("PARAMS:COLOR:GREEN", _green);
outXml.write("PARAMS:COLOR:BLUE",  _blue);

outXml.write("PARAMS:FONT:NAME", _fontName);
outXml.write("PARAMS:FONT:SIZE", _fontSize);

outXml.writeFile("filename.xml"); // Finally write the file to disk
As you can see, it's very easy. In the write method, the first parameter is a char* that defines the position in the XML tree. This is similar to XPath, but I didn't know XPath at the time I wrote this code, I would have used the '/' instead if I had known. The second parameter gives the value you want to write. write is a templated method so you can write almost any kind of variable, from int to std::string. Reading the file is also straightforward :
ParamIO inXml;

inXml.readFile("filename.xml"); // Read the file from disk

inXml.read("PARAMS:TEXT", _text, std::string("Hello world"));

inXml.read("PARAMS:COLOR:RED",   _red,   0);
inXml.read("PARAMS:COLOR:GREEN", _green, 0);
inXml.read("PARAMS:COLOR:BLUE",  _blue,  0);

inXml.read("PARAMS:FONT:NAME", _fontName, std::string("Arial"));
inXml.read("PARAMS:FONT:SIZE", _fontSize, 12.0);
You may be surprised by the third parameter of the read method. What does it mean? It's the default value of the parameter you try to read. Imagine you want to read a file like the previous one and the size of the font is not specified, then _fontSize will be automatically set to its default value 12.0. It's a very useful behaviour when you have several versions of a same application and some versions have parameters that didn't exist in older ones. It ensures that you still can read the old files, filling the missing values with default ones. It also lets you load a file that doesn't exist and set all the parameters with their default values.

ParamIO lets you read and write XML coming from streams also, it should be useful if you want some applications to exchange data through sockets for example.

The demo application includes a XML dialog box. With this dialog box (CXML_Dialog), you can visualise and modify any XML tree. I used it a lot, it's working really well. In case your parameter name contains FILENAME inside (e.g FONT_FILENAME), you'll see a button appear, and if you click on it, you'll obtain an open file dialog where you can find your file. I used this CXML_Dialog dialog box a lot and I'm very happy about it, it works really fine. CXML_Dialog uses a class from Easy Navigation Through an Editable List View by Lee Nowotny. I really thank him for the job, it works perfectly.

If you have any comments, suggestions or improvements let me know.

History

20 Nov 2002 : first version with GUI demo, with comparison capabilities

20 June 2003:

  • modified the website, added src download without the GUI demo
  • Added support for MFC CString has been added thanks to Paul Kissel : to enable CString read/write, just define _PARAMIO_CSTRING_SUPPORT_ in the compilation options.
  • Added a method to erase a node or an entire subtree as been added, thanks to Ogi's suggestion.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Arnaud Brejeon
Web Developer
China China
Member
I've been living & working in Tokyo since 2000 . I'm currently working in Gentech Corp. (www.gen.co.jp), developing computer vision applications, especially in the field of face detection.
 
I've been interested in C++ for quite a while and recently discovered Ruby.
 
My hobbies are trekking, japanese food, yoga & onsens.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Generallinker errors on new ProjectmemberLennin7 Jun '04 - 4:36 
I tried adding the files XmlMode,XmlParser,XmlStream,ParamIO,Xml_Notify,XmlUtil both headers, and cpp files to a new Win32 console project with MFC support. I've got this linker errors any ideas?
 
xmltest error LNK2005: "void __cdecl operator delete[](void *)" (??_V@YAXPAX@Z) already defined in LIBCMTD.lib(delete2.obj)
 
xmltest error LNK2005: "void * __cdecl operator new[](unsigned int)" (??_U@YAPAXI@Z) already defined in libcpmtd.lib(newaop.obj)
 
...
QuestionwriteFile() will truncate the existing file ???membersongge18 May '04 - 5:35 
Great codes! But in my usage, I have a problem,i.e. my program will call writeFile several times, so my data will be overwritten. For writeFile use the std::ofstream to write file, so existing file will be overwritten. I want to know: Is there any better way to avoid these?
 
Songge Info
Questionkey and value in the xml file ?memberDominque le Gros22 Apr '04 - 23:08 
HI,
 
how can i modified this source to make possible to write the key and the value from a database ? for reading,i should be load all keys and values in my database.
 
Thanks for your Reply.
 

 
best regards,
 
Dominique
GeneralThanksmemberTheBigW31 Mar '04 - 23:38 
Thanks for that Great Work!
 
David Hubbard wrote a great parser and you made it more usable. I need to write my own Config Writer, because I need some more functionality ( multiple entries of the same name, nesting of Setting into each other...), but the Functionality you added with the Handling for Nodes an Elements makes that quite easy.
Why did you add that CString support in such a nice "pure" STL Tool?
GeneralRe: ThanksmemberArnaud Brejeon3 Apr '04 - 0:55 
Thanks a lot for your support.
 
About CString, someone sent me an email with the changes to add the CString support because many people are interested in CString.
I want ParamIO to benefit as much as possible from other people, so I decided to add his code.
If you want to remove the CString support for your use, feel free to do it.
GeneralRe: ThanksmemberNelis Willers6 Jun '04 - 12:13 
TheBigW, how is work on your 'multiple entries' progressing?
If ready, won't you write make it available on CodeProject?
 
thanks
 
nelis
GeneralRe: ThanksmemberTheBigW6 Jun '04 - 21:52 
Yes it has been finished a while ago. It is already in heavy use in my recent project.
 
But to write an articel I still have to review the code, doing some coments and so on I hope to find the time to finish it it this month. If you need it earlier I could send you the source as it is.
GeneralRe: Thanksmembergraysong14 Jun '04 - 7:07 
Hi, BigW,
 
If you can send me one copy of your code, appreciate that.
 
thanks
 
hello world
GeneralRe: Thanksmemberboz27 Jul '04 - 15:13 
Hi, TheBigW, if I could get a copy of your code soon I'd really appreciate that, too
thanks,
boz
GeneralRe: ThanksmemberTheBigW28 Jul '04 - 3:17 
For all of you who needed to use many Keys of equal names at the same Level have a look at my (still brandnew) article at :
 
http://www.codeproject.com/useritems/XMLConfig.asp
 
I used the XML Attributes to solve the Problem. Maybe at is interesting for those who asked questions about that fact too.
QuestionUsing the ParamIO ???memberDominque le Gros17 Mar '04 - 5:55 
how can i write 2 differents objekts in the same file, like this example.
 
ParamIO outXml , Xmlout;
 
outXml.write("PARAMS:COLOR:GREEN", _green);
outXml.write("PARAMS:COLOR:BLUE", _blue);
 
Xmlout.write("PARAMS:FONT:NAME", _fontName);
Xmlout.write("PARAMS:FONT:SIZE", _fontSize);
 
outXml.writeFile("filename.xml"); // Finally write the file to disk
Xmlout.writeFile("filename.xml");
 

i want to have _green, _blue ,_fontName, _fontSize in the filename.xml.
 
any idee ?
 

 
best regards,
 
Dominique
GeneralUNICODE -- Very ImportantmemberExtraLean20 Feb '04 - 8:30 
Hi All,
 
ParamIO does not currently compile under UNICODE. Has anyone made any (local) changes that they would be willing to share to make ParamIO UNICODE compliant?
 
Arnaud, I see below that you were going to have a look at what it would take to implement UNICODE compatibility. Have you had a chance to look into it at all?
 
Thanks! Big Grin | :-D
 
--
Edward Livingston
(aka ExtraLean)
--
"I still maintain that seeing a nipple is far less disturbing than seeing someone get their brains blown out." -- Chris Maunder
GeneralRe: UNICODE -- Very ImportantmemberExtraLean20 Feb '04 - 9:03 
Thought I'd mention that it seems like there are only 2 comiler errors when building in UNICODE.
 
Both are in ParamIO.h:
-------------------------------------
Line 92:
text = std::string(value); // Convert from CString to std::string.
 
error:
error C2440: 'type cast' : cannot convert from 'CString' to 'std::basic_string<_Emem,_Traits,_Ax>'
-------------------------------------
Line 148:
return read(str, value, (LPCSTR)defaultVal);
 
error:
error C2440: 'type cast' : cannot convert from 'CString' to 'LPCSTR' No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
-------------------------------------
 
Hope this helps....
 
--
Edward Livingston
(aka ExtraLean)
--
"I still maintain that seeing a nipple is far less disturbing than seeing someone get their brains blown out." -- Chris Maunder
GeneralRe: UNICODE -- Very ImportantmemberArnaud Brejeon20 Feb '04 - 21:53 
Hi,
 
I never had time to make some changes for UNICODE.
I guess that what you should do is change string to wstring and LPCSTR to LPCTSTR .
 
I'd suggest you have a look at http://www.codeproject.com/vcpp/stl/upgradingstlappstounicode.asp
 
it may give good ideas to make the changes.
 
Good luck!
 
Arnaud
QuestionHow to change the attributes of xmlmemberBoggarapu Sateesh Kumar14 Feb '04 - 2:01 
Hi,
 
I am new to .NET and XML. I task is to read the xml, find a particular element, find the existance of particular attribute and if found then the attribute value should be updated with another value. I have to use vb.net using SAX parsers.
 
I could able to read the XML file using SAXXMLReader class but could not able to change the attribute value.
 
Can any help me sending the info regarding it.
 
I hope my problem is clear.
 
Thanks in advance.
 
Regards,
Sateesh.
GeneralIm having problemsmemberTauri29 Jan '04 - 6:37 
I'm using this:
std::string _text = "test";
ParamIO outXml;
outXml.write("PARAMS:TEXT", _text);
outXml.writeFile("Save.xml");
 
and getting this:
Compiling...
SquadServ.cpp
D:\Tauri\SquadServ\SquadServ.cpp(83) : warning C4003: not enough actual parameters for macro 'write'
D:\Tauri\SquadServ\SquadServ.cpp(83) : error C2039: 'send' : is not a member of 'ParamIO'
d:\tauri\squadserv\paramio.h(30) : see declaration of 'ParamIO'
D:\Tauri\SquadServ\SquadServ.cpp(83) : error C2059: syntax error : ','
Error executing cl.exe.
 
what should I do ?
GeneralRe: Im having problemsmemberNitron19 Feb '04 - 9:47 
instead of:
 
outXml.write("PARAMS:TEXT", _text);
 

do:
 
outXml.write("PARAMS:TEXT", _text.c_str());
 


 
~Nitron.
ññòòïðïðB A
start

GeneralPerfect!memberNitron7 Jan '04 - 7:13 
Just what I needed, thanks!
 
~Nitron.
ññòòïðïðB A
start

GeneralCannot compile in VC++6 - returns 252 errors!memberAndrew Fox24 Dec '03 - 2:50 
Hi,
I have read whole discussion about this library, but I cannot solve my problem. I wrote to all .cpp files the stdafx.h and set to static library. But during compilation, it returns 252 errors. The first & the most important(I think) is in ParamIO.cpp: ParamIO is not a class or a namespace name. All other errors are depending on this one. I don't know what to do...
GeneralRe: Cannot compile in VC++6 - returns 252 errors!memberArnaud Brejeon24 Dec '03 - 4:43 
Hi,
 
can you explain the problem by giving the output of the compiler?
I'm sure it's a small difference that makes all the errors.
First of all, can you compile properly the provided sample application?
I'll try to do my best to help you, but I don't have VC++ at the moment so I can't try many things.
 
Arnaud
GeneralRe: Cannot compile in VC++6 - returns 252 errors!memberAndrew Fox24 Dec '03 - 5:15 
Creating command line "link.exe @C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\RSP43D.tmp"
Output Window
Compiling...
ParamIO.cpp
D:\programming\C++projects\Polus\ParamIO.cpp(4) : error C2653: 'ParamIO' : is not a class or namespace name
D:\programming\C++projects\Polus\ParamIO.cpp(4) : error C2653: 'std' : is not a class or namespace name
D:\programming\C++projects\Polus\ParamIO.cpp(4) : error C2061: syntax error : identifier 'vector'
D:\programming\C++projects\Polus\ParamIO.cpp(6) : error C2065: 'access' : undeclared identifier
D:\programming\C++projects\Polus\ParamIO.cpp(6) : error C2228: left of '.clear' must have class/struct/union type
D:\programming\C++projects\Polus\ParamIO.cpp(13) : error C2653: 'std' : is not a class or namespace name
D:\programming\C++projects\Polus\ParamIO.cpp(13) : error C2065: 'istringstream' : undeclared identifier
D:\programming\C++projects\Polus\ParamIO.cpp(13) : error C2146: syntax error : missing ';' before identifier 'stream'
D:\programming\C++projects\Polus\ParamIO.cpp(13) : error C2065: 'stream' : undeclared identifier
D:\programming\C++projects\Polus\ParamIO.cpp(17) : error C2228: left of '.getline' must have class/struct/union type
D:\programming\C++projects\Polus\ParamIO.cpp(17) : fatal error C1903: unable to recover from previous error(s); stopping compilation
XML_Node.cpp
D:\programming\C++projects\Polus\XML_Node.cpp(5) : error C2653: 'XML_Node' : is not a class or namespace name
D:\programming\C++projects\Polus\XML_Node.cpp(7) : error C2550: 'XML_Node' : constructor initializer lists are only allowed on constructor definitions
 
.... & much more...
 
I'm sure that it is very small problem, but very hide for me \-:
 
Sample app is not problem for me to compile. It is work properly.
GeneralRe: Cannot compile in VC++6 - returns 252 errors!memberArnaud Brejeon27 Dec '03 - 22:17 
Hi,
 
try the following:
At the beginning of ParamIO.cpp, put
 
#include
std::vector testVec;
 

And check if those lines create an error. If they do, then you have a problem with your STL installation.
If not, do you have #include "ParamIO.h" at the beginning of ParamIO.cpp ?
 
Arnaud
GeneralRe: Cannot compile in VC++6 - returns 252 errors!memberAndrew Fox27 Dec '03 - 22:53 
Thanx, I have solved the problem - I hadn't got stdafx.h on first line!
GeneralThis won't compile with Visual Studio .NET 2003memberbenjamino19 Aug '03 - 4:40 
The primary reason being that there is an assumption in the code that vector::iterator and its chums are implemented as pointers to T. As far as I know this has previously been the case with VC++ but the C++ standard does not guarantee this.
 
Ben
GeneralRe: This won't compile with Visual Studio .NET 2003memberbobbymihalca19 Dec '03 - 5:43 
I replaced the code in XML_Node.cpp line 218
XML_Node::nodes_const_iterator res, end, begin;
begin = static_cast<XML_Node::nodes_const_iterator>(&_node);
end = static_cast<XML_Node::nodes_const_iterator>(&(_node) + 1);
with
XML_Node::nodes_const_iterator res;
XML_Node::nodes_const_iterator begin((std::vector<XML_Node>::_Tptr) &_node);
XML_Node::nodes_const_iterator end((std::vector<XML_Node>::_Tptr)(&(_node) + 1));
 
it seams to work but since I’m not a stl guru I don't know if is the correct way.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 1 Jul 2003
Article Copyright 2001 by Arnaud Brejeon
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid