,

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.

Hi Loren,
If you want to see the XML file structured in a tree shape shouldn't be using an XML editor or even IE to view it. Adding extraneous Tab characters to the XML file seems like a realy bad idea to me, and certainly non-portable I would think.

As an aside I don't like static's used in this way unless there is a realy good reason. And where does l come from me wonders?

Thanks for your input. The way I see it is that tabs are like spaces in that they are just "whitespace". Correct me if I'm wrong, but the XML standard does not say that whitespace is not allowed (this is similar in nature to HTML). If an XML parser has problems parsing whitespace then I surely wouldn't want to use it!

Also, this is a class to create config files for applications. Assuming they were going to edit the file manually, I'm not sure who would want to use an XML editor just to hack a few lines in the config file (even still, the tabs should not prevent them from doing this). Notepad should be just fine, and the tabs help with visibility... especially when the config file gets a little on the larger side, and the nesting starts to get out of control.

Neville Franks wrote:...certainly non-portable I would think

On the non-portable issue, as long as the XML parser used by this class can support the tabs (which it does) then there should be no porting issues. But like I said before whitespace (tabs included) should not prevent any other XML parser from correctly reading an XML file either.

Neville Franks wrote:As an aside I don't like static's used in this way unless there is a realy good reason.

How would you have implemented the tabs without using static? I know of another way to do it, but using static made the code MUCH cleaner. However, I'm always willing to learn new things, and would like to hear how you would have implemented this!

Hi Loren,
Well maybe I'm being a bit too picky re. the tabs, but it just seems like you are polluting the file to me. You are right that whitespace is ignored and shouldn't cause any problems. That said if you did open it in an XML editor and then saved it, you may well loose the tabs. The other issue is for large XML files, you are just making them that bit larger again.

Re. the static. I don't know enough about the code, however it appears to build a DOM (Tree) and XML_Node includes _parent and getParent(). Where I do stuff like this I climb the tree untill I reach the root, and then you know the depth, which is what I assume nTabCount is about. If that doesn't work and no other generalized solution presents itself I would at least put the static in the XML_Node class, where it can be initialized properly.

Has someone got this code to work using VC++ 5? Maybe this is a stupid question, but
1. I can't compile the demo project and
2. I created another project where I have to use these functions, I included all the necessary cpp and h files in the project and included ParamIO.h in my main file. But I can't compile. The compiler always tells me that the class XML_Node has no constructor, and when I double click the exception, I'm sent to a file Vector.h

Any help? Could it be possible to pre-build a .lib file with the (compiled) functions in it, o I still could use this class in my program?

I didn't try the code you wrote down here, but I compiled STLPort, changed the paths in the options panel of my VC5 to the new libs and headers of STLPort (I putted them on top, above the paths to the libs and headers of VC5), but there were still headers he couldn't find. So I did a search on my HD for those headers, and I found them in the directorys of my Borland Free Commandlinetools (you know, the free Borland C++ compiler). I also added the paths to the libs and headres of BCC in the options of my VC, but I still couldn't compile it

I checked the alphabetical order and the latest version is not ordered (at least on my PC), you can check it with the demo app. If you still have problems, we'll check that more carefully.

About the XSL stylesheet, I don't think I'll add it because lots of people (e.g. me) don't need it. You always can use the ParamIO::writeStream method to modify the default output, for example this way:

They are alphabetical. If you create a file using your demo app and look at in the 'XML Dialog' window you will see that all the elements in a layer in the tree are ordered.
The order the WriteParamaters function puts them in and the order they appear in the file are different.
Please help! This class(es) are perfect for me apart from this minor setback!

Excellent work, but i think Jonny Newman is correct.
I saved my parameters and the bottom children elements (ie: the "leaf" nodes) are sorted in alphabetical order within their parent.
so
outXml.write("Param:Parent:Child", "zac");
outXml.write("Param:Parent:Child", "bob");
outXml.write("Param:Parent:Child", "alice");
outXml.write("Param:Parent:Child", "joe");
ends up with (using [ and ] instead)

I will fix this alphabetical order tonight if possible. Meanwhile I can explain why the order is alphabetical and not related to the order of the code.
I use a std::map to store the elements of the node, a map of strings is by default alphabetically ordered. I plan to change the design (from map to vector of strings) to fix this problem.
Something else, I ran into compilation problems with gcc 3.2 recently and I just made the changes on my PC to compile with it, I'll update this part of the code as well.
I also plan to handle XML tags and comments (they ruin the parsing right now). Luckily I'll finish tonight, I hope some of you guys can have a look at the changes and test if everything is still OK.

Thanks to everybody for the suggestions, it helps improving the code. I haver to apologize if sometimes I don't reply quickly, I'm quite busy right now.
For people who are hesitating using this class, I can tell them that we've been using it for several years in may company in a large number of projects and it's really cool!

I just updated the code, I don't know how long it will take to have the new version on the link. If you need it now, just ask me by mail.

The changes are :

. Fixed the alphabetical order (at least I hope so )
. Compiles with GCC 3.2 on linux (can someone check on .NET, ...?)
. Handles [?xml ...?] tag and [!-- comment tag --]. Are there other special tags? I didn't have time to check, tell me if you know.
. Using Loren Brewer's print method to display and save in files, files look much better now. Thanks Loren.