1*1cd03ba3SJeremy Kemp /* 2*1cd03ba3SJeremy Kemp * Courtesy: https://gist.github.com/sebclaeys/1227644 3*1cd03ba3SJeremy Kemp */ 4*1cd03ba3SJeremy Kemp 5*1cd03ba3SJeremy Kemp 6*1cd03ba3SJeremy Kemp #ifndef XML_WRITER_H 7*1cd03ba3SJeremy Kemp # define XML_WRITER_H 8*1cd03ba3SJeremy Kemp 9*1cd03ba3SJeremy Kemp # define HEADER "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" 10*1cd03ba3SJeremy Kemp # define INDENT " " 11*1cd03ba3SJeremy Kemp # define NEWLINE "\n" 12*1cd03ba3SJeremy Kemp 13*1cd03ba3SJeremy Kemp # include <string> 14*1cd03ba3SJeremy Kemp # include <stack> 15*1cd03ba3SJeremy Kemp # include <iostream> 16*1cd03ba3SJeremy Kemp 17*1cd03ba3SJeremy Kemp class xmlWriter 18*1cd03ba3SJeremy Kemp { 19*1cd03ba3SJeremy Kemp public: 20*1cd03ba3SJeremy Kemp xmlWriter(std::ostream & os)21*1cd03ba3SJeremy Kemp xmlWriter(std::ostream& os) : os(os), tag_open(false), new_line(true) {os << HEADER;} ~xmlWriter()22*1cd03ba3SJeremy Kemp ~xmlWriter() {} 23*1cd03ba3SJeremy Kemp openElt(const char * tag)24*1cd03ba3SJeremy Kemp xmlWriter& openElt(const char* tag) { 25*1cd03ba3SJeremy Kemp this->closeTag(); 26*1cd03ba3SJeremy Kemp if (elt_stack.size() > 0) 27*1cd03ba3SJeremy Kemp os << NEWLINE; 28*1cd03ba3SJeremy Kemp this->indent(); 29*1cd03ba3SJeremy Kemp this->os << "<" << tag; 30*1cd03ba3SJeremy Kemp elt_stack.push(tag); 31*1cd03ba3SJeremy Kemp tag_open = true; 32*1cd03ba3SJeremy Kemp new_line = false; 33*1cd03ba3SJeremy Kemp return *this; 34*1cd03ba3SJeremy Kemp } 35*1cd03ba3SJeremy Kemp closeElt()36*1cd03ba3SJeremy Kemp xmlWriter& closeElt() { 37*1cd03ba3SJeremy Kemp this->closeTag(); 38*1cd03ba3SJeremy Kemp std::string elt = elt_stack.top(); 39*1cd03ba3SJeremy Kemp this->elt_stack.pop(); 40*1cd03ba3SJeremy Kemp if (new_line) 41*1cd03ba3SJeremy Kemp { 42*1cd03ba3SJeremy Kemp os << NEWLINE; 43*1cd03ba3SJeremy Kemp this->indent(); 44*1cd03ba3SJeremy Kemp } 45*1cd03ba3SJeremy Kemp new_line = true; 46*1cd03ba3SJeremy Kemp this->os << "</" << elt << ">"; 47*1cd03ba3SJeremy Kemp return *this; 48*1cd03ba3SJeremy Kemp } 49*1cd03ba3SJeremy Kemp closeAll()50*1cd03ba3SJeremy Kemp xmlWriter& closeAll() { 51*1cd03ba3SJeremy Kemp while (elt_stack.size()) 52*1cd03ba3SJeremy Kemp this->closeElt(); 53*1cd03ba3SJeremy Kemp return *this; 54*1cd03ba3SJeremy Kemp } 55*1cd03ba3SJeremy Kemp attr(const char * key,const char * val)56*1cd03ba3SJeremy Kemp xmlWriter& attr(const char* key, const char* val) { 57*1cd03ba3SJeremy Kemp this->os << " " << key << "=\""; 58*1cd03ba3SJeremy Kemp this->write_escape(val); 59*1cd03ba3SJeremy Kemp this->os << "\""; 60*1cd03ba3SJeremy Kemp return *this; 61*1cd03ba3SJeremy Kemp } 62*1cd03ba3SJeremy Kemp attr(const char * key,std::string val)63*1cd03ba3SJeremy Kemp xmlWriter& attr(const char* key, std::string val) { 64*1cd03ba3SJeremy Kemp return attr(key, val.c_str()); 65*1cd03ba3SJeremy Kemp } 66*1cd03ba3SJeremy Kemp content(const char * val)67*1cd03ba3SJeremy Kemp xmlWriter& content(const char* val) { 68*1cd03ba3SJeremy Kemp this->closeTag(); 69*1cd03ba3SJeremy Kemp this->write_escape(val); 70*1cd03ba3SJeremy Kemp return *this; 71*1cd03ba3SJeremy Kemp } 72*1cd03ba3SJeremy Kemp 73*1cd03ba3SJeremy Kemp private: 74*1cd03ba3SJeremy Kemp std::ostream& os; 75*1cd03ba3SJeremy Kemp bool tag_open; 76*1cd03ba3SJeremy Kemp bool new_line; 77*1cd03ba3SJeremy Kemp std::stack<std::string> elt_stack; 78*1cd03ba3SJeremy Kemp closeTag()79*1cd03ba3SJeremy Kemp inline void closeTag() { 80*1cd03ba3SJeremy Kemp if (tag_open) 81*1cd03ba3SJeremy Kemp { 82*1cd03ba3SJeremy Kemp this->os << ">"; 83*1cd03ba3SJeremy Kemp tag_open = false; 84*1cd03ba3SJeremy Kemp } 85*1cd03ba3SJeremy Kemp } 86*1cd03ba3SJeremy Kemp indent()87*1cd03ba3SJeremy Kemp inline void indent() { 88*1cd03ba3SJeremy Kemp for (int i = 0; i < (int)elt_stack.size(); i++) 89*1cd03ba3SJeremy Kemp os << (INDENT); 90*1cd03ba3SJeremy Kemp } 91*1cd03ba3SJeremy Kemp write_escape(const char * str)92*1cd03ba3SJeremy Kemp inline void write_escape(const char* str) { 93*1cd03ba3SJeremy Kemp for (; *str; str++) 94*1cd03ba3SJeremy Kemp switch (*str) { 95*1cd03ba3SJeremy Kemp case '&': os << "&"; break; 96*1cd03ba3SJeremy Kemp case '<': os << "<"; break; 97*1cd03ba3SJeremy Kemp case '>': os << ">"; break; 98*1cd03ba3SJeremy Kemp case '\'': os << "'"; break; 99*1cd03ba3SJeremy Kemp case '"': os << """; break; 100*1cd03ba3SJeremy Kemp default: os.put(*str); break; 101*1cd03ba3SJeremy Kemp } 102*1cd03ba3SJeremy Kemp } 103*1cd03ba3SJeremy Kemp }; 104*1cd03ba3SJeremy Kemp 105*1cd03ba3SJeremy Kemp #endif /* !XML_WRITER_H */ 106