I’ve worked on a couple of projects where XML files were generated via printfs or iostreams and this has always turned out to be a mistake. Maintaining such code can be tricky and you always spend an inordinate amount of time debugging the same type of problems over and over again. Usually a character with special meaning to XML (such as < or >) winds up not getting quoted correctly or you forget an end element tag.
The project I’m currently working on involves a search engine which returns its results in XML over an HTTP connection. I decided to use an XML writer rather than make the same mistake again. After looking around for an open source solution and not finding anything suitable for my needs, I decided to roll my own and place the project on Google Code.
To use xml-writer, simply drop xml_writer.h into your project directory and #include it as necessary. It is a very simple (less than 200 LOC) class. The accompanying unit tests also serve as documentation for its use.
Briefly, you instantiate an xml::writer object bound to an std::ostream. This allows you to send the resulting XML to a string (std::stringstream), a file (std::fostream) or any ostream compatible object. In my case, I created a stream object which writes directly to an HTTP connection.
You instantiate xml::element objects to actually create the XML element tags. An xml::element object has overloaded attr() methods to write element attributes and contents() to write element contents. When an xml::element object goes out of scope, it will write the necessary end element tag.
A simple example:
#include "xml_writer.h"
#include <sstream>
#include <iostream>
using namespace std;
int main()
{
stringstream ss;
xml::writer xw(ss);
{
xml::element record("record", xw);
record.attr("name", "fred").attr("age", 35);
record.contents("yabba dabba doo!");
}
cout << ss.str() << endl;
return 0;
}
will result in the following output:
<?xml version=”1.0″ encoding=”utf-8″?><record name=”fred” age=”35″>yabba dabba doo!</record>
NB: the extra scope created to encapsulate the record element was necessary so that the xml::element destructor is called before the resulting string is output. xml::element should always be enclosed in some kind of local scope for this to work properly.

