00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00014
00015 #ifndef __XMLWRITER_H_2CC1D410_9DE8_4452_B8F0_F987EF152E06
00016 #define __XMLWRITER_H_2CC1D410_9DE8_4452_B8F0_F987EF152E06
00017
00018
00019 #ifdef _MSC_VER
00020 #pragma warning( disable : 4786 )
00021 #pragma warning( disable : 4514 )
00022 #endif
00023
00024 #include <stack>
00025 #include <string>
00026 #include <sstream>
00027
00028 #include <fstream>
00029
00030 namespace BSUtilities {
00031 namespace xmlw {
00032
00033 class XmlStream {
00034 public:
00035
00036
00037 enum {versionMajor = 1, versionMinor = 0};
00038
00039
00040 struct Controller {
00041 typedef enum {whatProlog, whatTag, whatTagEnd, whatAttribute, whatCharData} what_type;
00042
00043 what_type what;
00044 std::string str;
00045
00046 inline Controller(const Controller& c) : what(c.what), str(c.str) {}
00047 inline Controller(const what_type _what) : what(_what){}
00048
00049
00050
00051 template<class t>
00052 inline Controller(const what_type _what, const t& _str) : what(_what), str(_str) {}
00053 };
00054
00055
00056 inline XmlStream(std::ostream& _s) : s(_s), state(stateNone), prologWritten(false) {}
00057
00058
00059 ~XmlStream() {
00060 if (stateTagName == state) {
00061 s << "/>";
00062 state = stateNone;
00063 }
00064 while (tags.size())
00065 endTag(tags.top());
00066 }
00067
00068
00069 template<class t>
00070 XmlStream& operator<<(const t& value) {
00071 if (stateTagName == state)
00072 tagName << value;
00073 s << value;
00074 return *this;
00075 }
00076
00077
00078
00079 XmlStream& operator<<(const Controller& controller) {
00080
00081 switch (controller.what) {
00082 case Controller::whatProlog:
00083 if (!prologWritten && stateNone == state) {
00084 s << "<?xml version=\"" << versionMajor << '.' << versionMinor << "\"?>\n";
00085 prologWritten = true;
00086 }
00087 break;
00088
00089 case Controller::whatTag:
00090 closeTagStart();
00091 s << '<';
00092 if (controller.str.empty()) {
00093 clearTagName();
00094 state = stateTagName;
00095 }
00096 else {
00097 s << controller.str;
00098 tags.push(controller.str);
00099 state = stateTag;
00100 }
00101 break;
00102
00103 case Controller::whatTagEnd:
00104 endTag(controller.str);
00105 break;
00106
00107 case Controller::whatAttribute:
00108 switch (state) {
00109 case stateTagName:
00110 tags.push(tagName.str());
00111 break;
00112
00113 case stateAttribute:
00114 s << '\"';
00115
00116 default:
00117 ;
00118 }
00119
00120 if (stateNone != state) {
00121 s << ' ' << controller.str << "=\"";
00122 state = stateAttribute;
00123 }
00124
00125
00126 break;
00127
00128 case Controller::whatCharData:
00129 closeTagStart();
00130 state = stateNone;
00131 break;
00132 }
00133
00134 return *this;
00135 }
00136
00137 private:
00138
00139 typedef enum {stateNone, stateTag, stateAttribute, stateTagName} state_type;
00140
00141
00142 typedef std::stack<std::string> tag_stack_type;
00143
00144 tag_stack_type tags;
00145
00146
00147 std::ostream& s;
00148 state_type state;
00149 bool prologWritten;
00150 std::ostringstream tagName;
00151
00152
00153 inline void clearTagName() {
00154 const std::string empty_str;
00155 tagName.rdbuf()->str(empty_str);
00156 }
00157
00158
00159 void closeTagStart(bool self_closed = false) {
00160 if (stateTagName == state)
00161 tags.push(tagName.str());
00162
00163
00164 switch (state) {
00165 case stateAttribute:
00166 s << '\"';
00167
00168 case stateTagName:
00169 case stateTag:
00170 if (self_closed)
00171 s << '/';
00172
00173 s << ">\n";
00174
00175 default:
00176 ;
00177 }
00178 }
00179
00180
00181 void endTag(const std::string& tag) {
00182 bool brk = false;
00183
00184 while (tags.size() > 0 && !brk) {
00185 if (stateNone == state)
00186
00187 s << "</" << tags.top() << ">\n";
00188 else {
00189 closeTagStart(true);
00190 state = stateNone;
00191 }
00192 brk = tag.empty() || tag == tags.top();
00193 tags.pop();
00194 }
00195 }
00196 };
00197
00198
00199
00200
00201 inline const XmlStream::Controller prolog() {
00202 return XmlStream::Controller(XmlStream::Controller::whatProlog);
00203 }
00204
00205 inline const XmlStream::Controller tag() {
00206 return XmlStream::Controller(XmlStream::Controller::whatTag);
00207 }
00208
00209 inline const XmlStream::Controller tag(const char* const tag_name) {
00210 return XmlStream::Controller(XmlStream::Controller::whatTag, tag_name);
00211 }
00212
00213
00214 inline const XmlStream::Controller tag(const std::string tag_name) {
00215 return XmlStream::Controller(XmlStream::Controller::whatTag,
00216 tag_name.c_str());
00217 }
00218
00219 inline const XmlStream::Controller endtag() {
00220 return XmlStream::Controller(XmlStream::Controller::whatTagEnd);
00221 }
00222
00223 inline const XmlStream::Controller endtag(const char* const tag_name) {
00224 return
00225 XmlStream::Controller(XmlStream::Controller::whatTagEnd, tag_name);
00226 }
00227
00228
00229 inline const XmlStream::Controller endtag(const std::string tag_name) {
00230 return XmlStream::Controller(XmlStream::Controller::whatTagEnd,
00231 tag_name.c_str());
00232 }
00233
00234 inline const XmlStream::Controller attr(const char* const attr_name) {
00235 return XmlStream::Controller(XmlStream::Controller::whatAttribute,
00236 attr_name);
00237 }
00238
00239
00240 inline const XmlStream::Controller attr(const std::string attr_name) {
00241 return XmlStream::Controller(XmlStream::Controller::whatAttribute,
00242 attr_name.c_str());
00243 }
00244
00245 inline const XmlStream::Controller chardata() {
00246 return XmlStream::Controller(XmlStream::Controller::whatCharData);
00247 }
00248
00250
00258 template<class X>
00259 void save (const std::string &filename, const X obj)
00260 {
00261 std::ofstream save_file (filename.c_str());
00262 if (save_file)
00263 {
00264 xmlw::XmlStream stream (save_file);
00265 stream << xmlw::prolog ();
00266
00267 obj.save (stream);
00268
00269 save_file.close ();
00270 }
00271 }
00272
00273 }
00274 }
00275
00276 #endif // __XMLWRITER_H_2CC1D410_9DE8_4452_B8F0_F987EF152E06