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