This is an XML Writer in C++. It doesn't do much but the basics, and I've tested it, so it should hold up well enough. I hope in the near future, I can bring you an XML Reader.I kinda built the function names after the Visual Basic names for their standard XML Writer (Microsoft's anyways), so if you see the similarities, that's where I got the names from. As for the actual function internals, I don't know if they are the same or not.XmlWriter.h:#ifndef XmlWriter_H#define XmlWriter_H#include <fstream>#include <iostream>#include <string>#include <vector>class XmlWriter {public:    bool open(const std::string);    void close();    bool exists(const std::string);    void writeOpenTag(const std::string);    void writeCloseTag();    void writeStartElementTag(const std::string);    void writeEndElementTag();    void writeAttribute(const std::string);    void writeString(const std::string);private:    std::ofstream outFile;    int indent;    int openTags;    int openElements;    std::vector<std::string> tempOpenTag;    std::vector<std::string> tempElementTag;};#endifXmlWriter.cpp:#include XmlWriter.h//=============================================================================//== Function Name  :   XmlWriter::exists//==//== Perameters//== Name       Type                Description//== ---------- -----------         --------------------//== fileName   const std::string   The name of the file that is in use//==//== Description//== --------------------------------------------------------------------------//== This function is used to check if the XML file exists//=============================================================================bool XmlWriter::exists(const std::string fileName){    std::fstream checkFile(fileName);    return checkFile.is_open();}//=============================================================================//== Function Name  :   XmlWriter::open//==//== Perameters//== Name       Type                Description//== ---------- -----------         --------------------//== strFile    const std::string   The name of the file that the user passes//==                                in the code//==//== Description//== --------------------------------------------------------------------------//== This function is used to open the XML file, first checking to see if it//== exists first//=============================================================================bool XmlWriter::open(const std::string strFile) {    if (exists(strFile)){        std::cout << Error: File alread exists.\n;        return false;    }    outFile.open(strFile);    if (outFile.is_open()) {        std::cout << File created successfully.\n;        outFile << <!--XML Document-->\n;        outFile << <?xml version='1.0' encoding='us-ascii'>\n;        indent = 0;        openTags = 0;        openElements = 0;        return true;    }    return false;}//=============================================================================//== Function Name  :   XmlWriter::close//==//== Perameters//== Name       Type                Description//== ---------- -----------         --------------------//== N/a        N/a                 N/a//==//== Description//== --------------------------------------------------------------------------//== This function is used to close the XML file//=============================================================================void XmlWriter::close() {    if (outFile.is_open()) {        outFile.close();    }    else {        std::cout << File already closed.\n;    }}//=============================================================================//== Function Name  :   XmlWriter::writeOpenTag//==//== Perameters//== Name       Type                Description//== ---------- -----------         --------------------//== openTag    const std::string   The name of the tag being created//==//== Description//== --------------------------------------------------------------------------//== This function creates a new tag, checking that the file is open, and saves//== the tag name in a vector to keep track of it//=============================================================================void XmlWriter::writeOpenTag(const std::string openTag) {    if (outFile.is_open()) {        for (int i = 0; i < indent; i++) {            outFile << \t;        }        tempOpenTag.resize(openTags + 1);        outFile << < << openTag << >\n;        tempOpenTag[openTags] = openTag;        indent += 1;        openTags += 1;    }    else {        std::cout << File is closed. Unable to write to file.\n;    }}//=============================================================================//== Function Name  :   XmlWriter::writeCloseTag//==//== Perameters//== Name       Type                Description//== ---------- -----------         --------------------//== N/a        N/a                 N/a//==//== Description//== --------------------------------------------------------------------------//== This function closes the currently open tag//=============================================================================void XmlWriter::writeCloseTag() {    if (outFile.is_open()) {        indent -= 1;        for (int i = 0; i < indent; i++) {            outFile << \t;        }        outFile << </ << tempOpenTag[openTags - 1] << >\n;        tempOpenTag.resize(openTags - 1);        openTags -= 1;    }    else {        std::cout << File is closed. Unable to write to file.\n;    }}//=============================================================================//== Function Name  :   XmlWriter::writeStartElementTag//==//== Perameters//== Name       Type                Description//== ---------- -----------         --------------------//== elementTag const std::string   The name of the element being created//==//== Description//== --------------------------------------------------------------------------//== This function creates a new element tag and saves the name to a vector//=============================================================================void XmlWriter::writeStartElementTag(const std::string elementTag) {    if (outFile.is_open()) {        for (int i = 0; i < indent; i++) {            outFile << \t;        }        tempElementTag.resize(openElements + 1);        tempElementTag[openElements] = elementTag;        openElements += 1;        outFile << < << elementTag;    }    else {        std::cout << File is closed. Unable to write to file.\n;    }}//=============================================================================//== Function Name  :   XmlWriter::writeEndElementTag//==//== Perameters//== Name       Type                Description//== ---------- -----------         --------------------//== N/a        N/a                 N/a//==//== Description//== --------------------------------------------------------------------------//== This function closed the currently opened element tag//=============================================================================void XmlWriter::writeEndElementTag() {    if (outFile.is_open()) {        outFile << </ << tempElementTag[openElements - 1] << >\n;        tempElementTag.resize(openElements - 1);        openElements -= 1;    }    else {        std::cout << File is closed. Unable to write to file.\n;    }}//=============================================================================//== Function Name  :   XmlWriter::writeAttribute//==//== Perameters//== Name           Type                Description//== ----------     -----------         --------------------//== outAttribute   const std::string   The attribute being written out//==//== Description//== --------------------------------------------------------------------------//== This function writes an attribute (if any) after the element tag is first//== opened and before the output for the element is written//=============================================================================void XmlWriter::writeAttribute(const std::string outAttribute) {    if (outFile.is_open()) {        outFile <<   << outAttribute;    }    else {        std::cout << File is closed. Unable to write to file.\n;    }}//=============================================================================//== Function Name  :   XmlWriter::writeString//==//== Perameters//== Name           Type                Description//== ----------     -----------         --------------------//== writeString    const std::string   The string to be written to the element//==//== Description//== --------------------------------------------------------------------------//=============================================================================void XmlWriter::writeString(const std::string outString) {    if (outFile.is_open()) {        outFile << > << outString;    }    else {        std::cout << File is closed. Unable to write to file.\n;    }}main.cpp:#include XmlWriter.hint main() {    XmlWriter xml;    if (xml.open(C:\\Users\\UserNameHere\\Desktop\\test.xml)) {        xml.writeOpenTag(testTag);        xml.writeStartElementTag(testEle1);        xml.writeString(This is my first tag string!);        xml.writeEndElementTag();        xml.writeOpenTag(testTag2);        xml.writeStartElementTag(testEle2);        xml.writeAttribute(testAtt=\TestAttribute\);        xml.writeString(I sometimes amaze myself.);        xml.writeEndElementTag();        xml.writeOpenTag(testTag3);        xml.writeStartElementTag(testEle3);        xml.writeAttribute(testAtt2=\TestAttrib2\);        xml.writeString(Though i'm sure someone can make something even better);        xml.writeEndElementTag();        xml.writeCloseTag();        xml.writeCloseTag();        xml.writeCloseTag();        xml.close();        std::cout << Success!\n;    } else {        std::cout << Error opening file.\n;    }    system(pause);    return 0;}
Basic XML Writer in C++
c++;xml
I'm going to second guess a bunch of decisions that you made.  I don't know that you made them all incorrectly, but I think that alternatives deserve consideration.std::ofstream outFile;Why not make this an ostream instead?  Then you could output to things other than just a file.  An ofstream is a limiting choice here.  My quick read is that the best choice would be to have both an XmlWriter and an XmlWriterFile which extends it.  int indent;I'd call this current_indent for readability.  Otherwise, one might guess that it reflects the overall indent rather than a value that changes over time.  int openTags;int openElements;If I had these variables, I'd call these something like openTagCount and openElementCount respectively.  When I see a plural variable, I expect it to contain multiple things.  That is, I expect plurals to indicate collections.  These don't hold the open tags and elements, just the counts.  But I actually wouldn't have these variables.  More in a moment.  std::vector<std::string> tempOpenTag;std::vector<std::string> tempElementTag;OK, these two vectors (along with the count variables) are used to implement stacks.  Here's the thing though, why not just make them std::stack?  You can even have the stack implementation use std::vector as the storage medium.  That way, you don't have to worry about managing the stack variables as you do here.  void XmlWriter::writeCloseTag() {    if (outFile.is_open()) {This seems unlikely enough to not be checked.  You already check that the file opens in the open method.  It shouldn't close itself arbitrarily often enough that you would need to check it in each write function.      indent -= 1;It's more common to just say indent--; rather than to specify a decrement of 1.      for (int i = 0; i < indent; i++) {        outFile << \t;    }Why not just outFile << std::string(indent, '\t');That saves you having to do indent calls to your stream.  You also may want to make the indent character (\t here) a constructor option.      outFile << </ << tempOpenTag[openTags - 1] << >\n;    tempOpenTag.resize(openTags - 1);    openTags -= 1;You shouldn't resize a std::vector by 1.  It's an expensive operation, so if you're going to do it, do it up large.  A typical expansion is more like 50% or 100%.  It's not evident that this program would need to make a vector smaller at all.  Either the stack is going to grow again or it will end and the entire data structure can be released.  You do three things to implement a pop operation on your stack.  If openTags was a stack variable, you could just say outFile << </ << openTags.top() << >\n;openTags.pop();The pop() will trigger any resizes that may be necessary.  You don't have to manage the number of open tags yourself.      }    else {        std::cout << File is closed. Unable to write to file.\n;    }}This isn't necessary if you don't do the excess is_open check.  What you should be doing is to check if writeCloseTag is called when the stack is empty.  If you use the stack variable, this looks something like if ( openTags.empty() ) {    // do something to handle this special case    // maybe write to STDERR    cerr << No tag to close. << endl;    return; // or exit or throw an exception}You can put that code at the beginning of the function.  You should also consider what should happen if writeCloseTag and writeEndElementTag are called in the wrong order.  I don't see how your code would even notice.  Perhaps open tags and elements should share the same stack rather than having two different stacks.  Rather than storing them as strings, you could store them as objects of classes which extend the same class.  That way you could know what is supposed to come next.  What would happen if writeString were called twice in a row?  Consider adding logic to auto-close the element only if one is open rather than every time writeString is called.  It should also check if it is currently in a context where a string can exist.  Check if an element tag is open before adding an attribute to it.  