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:

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 :

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.

Ajit Jadhav is perfectly right, in XML you can only have one root node.
Now if you really want to have several and don't need to follow exactly the XML norm, you can change the code to handle multiple root nodes, it's up to you.

I'm sorry but I don't have any knowledge about UNICODE.
I also think it should be a great improvement, if someone has some ideas how to do, please explain us. Meanwhile I'll try to read about UNICODE and see what's possible (or not).

This looks like it could be useful, but will require significant rework to be used in a professional (ie non-OpenSOurce) environment.

In particular, the XmlParser class has a huge number of public variables, and all of its code is inline. I use inline functions all the time, but only for short functions - some of these are 60 lines or more!

Overall it feels like a chunk of code written by a Java junkie, who doesn't like the concept of separate header and code files.

I will attempt to use this, but it will take several hours of rewriting and moving code around to bring this up to commercial standards.

now personally, i don't like header files... and frankly, i don't like prototyping either. it's a bitch; it's amazing anything works in c. but that's just me...

anyway... i don't think it's very "professional" to comment so harshly on a FREE and functional example. i'd be ashamed to make such a statement myself: especially if i was just turning right around to USE it in a commercial app. why don't you just write a top-down parser from scratch mr. "I will attempt to use this, but it will take several hours of rewriting and moving code around to bring this up to commercial standards." IMGOFMS

some part of the code is inline because VC++ wants template methods to be inline, or I couldn't figure out how to put them properly in a source file, if you have some hints, please help me.
I've been using this code in a professional environment for a while and it works pretty well and nobody complained about this yet.
If you want to rewrite it, you're welcome to do so and then we'll put your new code on the page, I think that's one of the ideas of OpenSource : other programmers (with better skills, or at least who think so) can improve the work.
I think it should take you a few minutes and not hours as you said (unless you're an amateur, too . I'm now busy with some other work so I won't have time to do that before some time, please proceed.

And in case you really hate my code (and David Hubbard's one), rewrite the same thing entirely and post it to the code project. Everybody will be so happy about your (probably) very professional work.

Arnaud Brejeon wrote:some part of the code is inline because VC++ wants template methods to be inline, or I couldn't figure out how to put them properly in a source file, if you have some hints, please help me.

That has nothing to do with VC. In fact, templates must be implemented in header files. The compiler has to know the exact implementation, otherwise how should it cope with the types of the template parameters?

Disclaimer:Because of heavy processing requirements, we are currently using some of your unused brain capacity for backup processing. Please ignore any hallucinations, voices or unusual dreams you may experience. Please avoid concentration-intensive tasks until further notice. Thank you.

I guess I must apologise to VC++ people, then.
But if they could try to write a "clever" compiler that will prevent me from writing code in the header, then I (and many other programmers, too) would be very happy .

1. You've got the code FOR FREE. What are you complaining for ?
2. Where is your beautyful code ? Even bad code is better than no code
3. You are very slow at copy & paste, don't you ?
4. After "several hours of rewriting", why didn't you post your "brought up to commercial standards" code here ?
5. If the code is so bad, why are you going to use it in a commercial product of yours ?

I use inline functions all the time, but only for short functions - some of these are 60 lines or more!

Can you give one reason other than personal taste why this is the case?

For a professional package we use whole libraries based on inline code to get around management problems with libraries. These problems mostly have to do with the different build modes such as Unicode, MBCS, ASCII, multi-threaded, single threaded, CRT in DLL form, CRT not in DLL form.

Overall it feels like a chunk of code written by a Java junkie, who doesn't like the concept of separate header and code files.

I will attempt to use this, but it will take several hours of rewriting and moving code around to bring this up to commercial standards.

I changed slightly the code to compile it under linux (I used some non-implemented yet stream_iterator before).
So know it compiles and runs properly on win200 and linux RedHat 7.1, the two OSes I have on my computer.
I'm quite confident that it will compile and run on any other compiler/platform that supports STL.

Of course you can do the same for reading, you can read from the memory using readStream method.

> and also how could I input attribute for each XML node with this class?

This is not a part of the class, but when the original XML file is parsed, attributes are parsed and stored in memory, too.
To add this feature, you'll have to go inside the code. I can give you a few hints.
In memory, the XML is stored like a tree and each node is an object of the XML_Node class.
The variable called "_attributes" in this class stores the attributes of each node in a string. If you want to use it properly, you may need to parse this string by yourself.
As I said, reading should be OK. In order to write, you just need to change the print method in XML_Node class so that the attributes are printed.
So I would say that everything is ready to handle attributes in the code, but it needs some work to do that properly.

Actually, we've been using this class in my company for a few months and nobody asked me to add attribute handling yet. I think it's not so important (but it depends on what you want to do). Recently I've seen some people use the attribute to store the type of the variable (integer, bool, ...) but I think you lose the power of STL that can read string and convert to any type you want (integer, double, ...).

If you have any other questions or if you made the attribute change successfully please tell me,