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