xmlstorage.h

Go to the documentation of this file.
00001 
00002  //
00003  // XML storage classes
00004  //
00005  // xmlstorage.h
00006  //
00007  // Copyright (c) 2004, 2005, 2006 Martin Fuchs <martin-fuchs@gmx.net>
00008  //
00009 
00010 
00011 /*
00012 
00013   All rights reserved.
00014 
00015   Redistribution and use in source and binary forms, with or without
00016   modification, are permitted provided that the following conditions are met:
00017 
00018   * Redistributions of source code must retain the above copyright
00019     notice, this list of conditions and the following disclaimer.
00020   * Redistributions in binary form must reproduce the above copyright
00021     notice, this list of conditions and the following disclaimer in
00022     the documentation and/or other materials provided with the
00023     distribution.
00024 
00025   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00026   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00028   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00029   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00030   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00031   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00032   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00033   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00034   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00035   POSSIBILITY OF SUCH DAMAGE.
00036 
00037 */
00038 
00039 #ifndef _XMLSTORAGE_H
00040 
00041 
00042 #if _MSC_VER>=1400
00043 #ifndef _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES
00044 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES         1
00045 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT   1
00046 #define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES           1
00047 #endif
00048 #endif
00049 
00050 
00051 #ifdef XS_USE_XERCES
00052 
00053 #ifndef UNICODE
00054 #ifndef XS_STRING_UTF8
00055 #define XS_STRING_UTF8
00056 #endif
00057 #endif
00058 
00059 #include <xercesc/parsers/SAXParser.hpp>
00060 #include <xercesc/sax/HandlerBase.hpp>
00061 
00062 using XERCES_CPP_NAMESPACE_QUALIFIER Locator;
00063 using XERCES_CPP_NAMESPACE_QUALIFIER SAXParser;
00064 using XERCES_CPP_NAMESPACE_QUALIFIER HandlerBase;
00065 using XERCES_CPP_NAMESPACE_QUALIFIER InputSource;
00066 using XERCES_CPP_NAMESPACE_QUALIFIER AttributeList;
00067 using XERCES_CPP_NAMESPACE_QUALIFIER SAXParseException;
00068 
00069 typedef XMLCh XML_Char;
00070 
00071 #elif defined(XS_USE_EXPAT)
00072 
00073 #include <expat/expat.h>
00074 
00075 #endif
00076 
00077 
00078 #ifdef _MSC_VER
00079 #pragma warning(disable: 4786)
00080 
00081 #ifndef XS_NO_COMMENT
00082 
00083 #ifdef XS_USE_XERCES
00084 #ifdef _DEBUG
00085 #pragma comment(lib, "xerces-c_2D")
00086 #else
00087 #pragma comment(lib, "xerces-c_2")
00088 #endif
00089 #elif defined(XS_USE_EXPAT)
00090 #ifdef XML_STATIC
00091 #ifndef _DEBUG
00092 #pragma comment(lib, "libexpatMT")
00093 #endif
00094 #else
00095 #pragma comment(lib, "libexpat")
00096 #endif
00097 #endif
00098 
00099 #ifndef _STRING_DEFINED // _STRING_DEFINED only allowed if using xmlstorage.cpp embedded in the project
00100 #if defined(_DEBUG) && defined(_DLL)    // DEBUG version only supported with MSVCRTD
00101 #if _MSC_VER==1400
00102 #pragma comment(lib, "xmlstorage-vc8d")
00103 #else
00104 #pragma comment(lib, "xmlstorage-vc6d")
00105 #endif
00106 #else
00107 #ifdef _DLL
00108 #if _MSC_VER==1400
00109 #pragma comment(lib, "xmlstorage-vc8")
00110 #else
00111 #pragma comment(lib, "xmlstorage-vc6")
00112 #endif
00113 #elif defined(_MT)
00114 #if _MSC_VER==1400
00115 #pragma comment(lib, "xmlstorage-vc8t")
00116 #else
00117 #pragma comment(lib, "xmlstorage-vc6t")
00118 #endif
00119 #else
00120  // -ML is no more supported by VS2005.
00121 #pragma comment(lib, "xmlstorage-vc6l")
00122 #endif
00123 #endif
00124 #endif // _STRING_DEFINED
00125 
00126 #endif // XS_NO_COMMENT
00127 
00128 #endif // _MSC_VER
00129 
00130 
00131 #ifdef UNICODE
00132 #ifndef _UNICODE
00133 #define _UNICODE
00134 #endif
00135 #else
00136 #ifdef _UNICODE
00137 #define UNICODE
00138 #endif
00139 #endif
00140 
00141 #include <windows.h>    // for LPCTSTR
00142 
00143 #include <tchar.h>
00144 #include <malloc.h>
00145 
00146 #include <fstream>
00147 #include <sstream>
00148 #include <string>
00149 #include <stack>
00150 #include <list>
00151 #include <map>
00152 
00153 
00154 #ifndef BUFFER_LEN
00155 #define BUFFER_LEN 2048
00156 #endif
00157 
00158 
00159 namespace XMLStorage {
00160 
00161 
00162 #ifndef XS_String
00163 
00164 #ifdef XS_STRING_UTF8
00165 #define XS_CHAR char
00166 #define XS_TEXT(x) x
00167 #define LPXSSTR LPSTR
00168 #define LPCXSSTR LPCSTR
00169 #define XS_cmp strcmp
00170 #define XS_icmp stricmp
00171 #define XS_ncmp strncmp
00172 #define XS_nicmp strnicmp
00173 #define XS_toi atoi
00174 #define XS_tod strtod
00175 #define XS_len strlen
00176 #define XS_snprintf _snprintf
00177 #define XS_vsnprintf _vsnprintf
00178 #define XS_strstr strstr
00179 #else
00180 #define XS_CHAR TCHAR
00181 #define XS_TEXT(x) TEXT(x)
00182 #define LPXSSTR LPTSTR
00183 #define LPCXSSTR LPCTSTR
00184 #define XS_cmp _tcscmp
00185 #define XS_icmp _tcsicmp
00186 #define XS_ncmp _tcsncmp
00187 #define XS_nicmp _tcsnicmp
00188 #define XS_toi _ttoi
00189 #define XS_tod _tcstod
00190 #define XS_len _tcslen
00191 #define XS_snprintf _sntprintf
00192 #define XS_vsnprintf _vsntprintf
00193 #define XS_strstr _tcsstr
00194 #endif
00195 
00196 #ifndef COUNTOF
00197 #if _MSC_VER>=1400
00198 #define COUNTOF _countof
00199 #else
00200 #define COUNTOF(b) (sizeof(b)/sizeof(b[0]))
00201 #endif
00202 #endif
00203 
00204 
00205 int inline isxmlsym(unsigned char c)
00206 {
00207     return isalnum(c) || c=='_' || c=='-';
00208 }
00209 
00210 
00211 #if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8)
00212 
00213 #define XS_String String
00214 
00215 #else // _STRING_DEFINED, !XS_STRING_UTF8
00216 
00217  /// string class for TCHAR strings
00218 
00219 struct XS_String
00220 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
00221  : public std::wstring
00222 #else
00223  : public std::string
00224 #endif
00225 {
00226 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
00227     typedef std::wstring super;
00228 #else
00229     typedef std::string super;
00230 #endif
00231 
00232     XS_String() {}
00233 
00234     XS_String(LPCXSSTR s) {if (s) super::assign(s);}
00235     XS_String(LPCXSSTR s, size_t l) : super(s, l) {}
00236 
00237     XS_String(const super& other) : super(other) {}
00238     XS_String(const XS_String& other) : super(other) {}
00239 
00240 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
00241     XS_String(LPCSTR s) {assign(s);}
00242     XS_String(LPCSTR s, size_t l) {assign(s, l);}
00243     XS_String(const std::string& other) {assign(other.c_str());}
00244     XS_String& operator=(LPCSTR s) {assign(s); return *this;}
00245     void assign(LPCSTR s) {if (s) {size_t bl=strlen(s); LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, bl, b, bl));} else erase();}
00246     void assign(LPCSTR s, size_t l) {if (s) {size_t bl=l; LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, l, b, bl));} else erase();}
00247 #else
00248     XS_String(LPCWSTR s) {assign(s);}
00249     XS_String(LPCWSTR s, size_t l) {assign(s, l);}
00250     XS_String(const std::wstring& other) {assign(other.c_str());}
00251     XS_String& operator=(LPCWSTR s) {assign(s); return *this;}
00252 #ifdef XS_STRING_UTF8
00253     void assign(const XS_String& s) {assign(s.c_str());}
00254     void assign(LPCWSTR s) {if (s) {size_t bl=wcslen(s); LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_UTF8, 0, s, (int)bl, b, (int)bl, 0, 0));} else erase();}
00255     void assign(LPCWSTR s, size_t l) {size_t bl=l; if (s) {LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_UTF8, 0, s, (int)l, b, (int)bl, 0, 0));} else erase();}
00256 #else // if !UNICODE && !XS_STRING_UTF8
00257     void assign(LPCWSTR s) {if (s) {size_t bl=wcslen(s); LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, (int)bl, b, (int)bl, 0, 0));} else erase();}
00258     void assign(LPCWSTR s, size_t l) {size_t bl=l; if (s) {LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, (int)l, b, (int)bl, 0, 0));} else erase();}
00259 #endif
00260 #endif
00261 
00262     XS_String& operator=(LPCXSSTR s) {if (s) super::assign(s); else erase(); return *this;}
00263     XS_String& operator=(const super& s) {super::assign(s); return *this;}
00264     void assign(LPCXSSTR s) {super::assign(s);}
00265     void assign(LPCXSSTR s, size_t l) {super::assign(s, l);}
00266 
00267     operator LPCXSSTR() const {return c_str();}
00268 
00269 #ifdef XS_STRING_UTF8
00270     operator std::wstring() const {size_t bl=length(); LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); return std::wstring(b, MultiByteToWideChar(CP_UTF8, 0, c_str(), bl, b, bl));}
00271 #elif defined(UNICODE)
00272     operator std::string() const {size_t bl=length(); LPSTR b=(LPSTR)alloca(bl); return std::string(b, WideCharToMultiByte(CP_ACP, 0, c_str(), bl, b, bl, 0, 0));}
00273 #else
00274     operator std::wstring() const {size_t bl=length(); LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); return std::wstring(b, MultiByteToWideChar(CP_ACP, 0, c_str(), (int)bl, b, (int)bl));}
00275 #endif
00276 
00277     XS_String& printf(LPCXSSTR fmt, ...)
00278     {
00279         va_list l;
00280         XS_CHAR b[BUFFER_LEN];
00281 
00282         va_start(l, fmt);
00283         super::assign(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));
00284         va_end(l);
00285 
00286         return *this;
00287     }
00288 
00289     XS_String& vprintf(LPCXSSTR fmt, va_list l)
00290     {
00291         XS_CHAR b[BUFFER_LEN];
00292 
00293         super::assign(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));
00294 
00295         return *this;
00296     }
00297 
00298     XS_String& appendf(LPCXSSTR fmt, ...)
00299     {
00300         va_list l;
00301         XS_CHAR b[BUFFER_LEN];
00302 
00303         va_start(l, fmt);
00304         super::append(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));
00305         va_end(l);
00306 
00307         return *this;
00308     }
00309 
00310     XS_String& vappendf(LPCXSSTR fmt, va_list l)
00311     {
00312         XS_CHAR b[BUFFER_LEN];
00313 
00314         super::append(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));
00315 
00316         return *this;
00317     }
00318 };
00319 
00320 #endif // _STRING_DEFINED, !XS_STRING_UTF8
00321 
00322 #endif // XS_String
00323 
00324 
00325 #define XS_EMPTY_STR XS_TEXT("")
00326 #define XS_TRUE_STR XS_TEXT("true")
00327 #define XS_FALSE_STR XS_TEXT("false")
00328 #define XS_INTFMT_STR XS_TEXT("%d")
00329 #define XS_FLOATFMT_STR XS_TEXT("%f")
00330 
00331  // work around GCC's wide string constant bug
00332 #ifdef __GNUC__
00333 extern const LPCXSSTR XS_EMPTY;
00334 extern const LPCXSSTR XS_TRUE;
00335 extern const LPCXSSTR XS_FALSE;
00336 extern const LPCXSSTR XS_INTFMT;
00337 extern const LPCXSSTR XS_FLOATFMT;
00338 #else
00339 #define XS_EMPTY XS_EMPTY_STR
00340 #define XS_TRUE XS_TRUE_STR
00341 #define XS_FALSE XS_FALSE_STR
00342 #define XS_INTFMT XS_INTFMT_STR
00343 #define XS_FLOATFMT XS_FLOATFMT_STR
00344 #endif
00345 
00346 
00347 #ifndef XS_STRING_UTF8
00348 
00349  // from UTF-8 to XS internal string encoding
00350 inline void assign_utf8(XS_String& s, const char* str, int lutf8)
00351 {
00352 #ifdef UNICODE
00353     LPTSTR buffer = (LPTSTR)alloca(sizeof(TCHAR)*lutf8);
00354     int l = MultiByteToWideChar(CP_UTF8, 0, str, lutf8, buffer, lutf8);
00355 #else
00356     LPWSTR wbuffer = (LPWSTR)alloca(sizeof(WCHAR)*lutf8);
00357     int l = MultiByteToWideChar(CP_UTF8, 0, str, lutf8, wbuffer, lutf8);
00358 
00359     int bl=2*l; LPSTR buffer = (LPSTR)alloca(bl);
00360     l = WideCharToMultiByte(CP_ACP, 0, wbuffer, l, buffer, bl, 0, 0);
00361 #endif
00362 
00363     s.assign(buffer, l);
00364 }
00365 
00366  // from UTF-8 to XS internal string encoding
00367 inline void assign_utf8(XS_String& s, const char* str)
00368 {
00369     assign_utf8(s, str, strlen(str));
00370 }
00371 
00372  // from XS internal string encoding to UTF-8
00373 inline std::string get_utf8(LPCTSTR s, size_t l)
00374 {
00375 #ifdef UNICODE
00376     size_t bl=2*l; LPSTR buffer = (LPSTR)alloca(bl);
00377     l = WideCharToMultiByte(CP_UTF8, 0, s, (int)l, buffer, (int)bl, 0, 0);
00378 #else
00379     LPWSTR wbuffer = (LPWSTR)alloca(sizeof(WCHAR)*l);
00380     l = MultiByteToWideChar(CP_ACP, 0, s, (int)l, wbuffer, (int)l);
00381 
00382     size_t bl=2*l; LPSTR buffer = (LPSTR)alloca(bl);
00383     l = WideCharToMultiByte(CP_UTF8, 0, wbuffer, (int)l, buffer, (int)bl, 0, 0);
00384 #endif
00385 
00386     return std::string(buffer, l);
00387 }
00388 
00389 #ifdef UNICODE
00390  // from XS internal string encoding to UTF-8
00391 inline std::string get_utf8(const char* s, size_t l)
00392 {
00393     LPWSTR wbuffer = (LPWSTR)alloca(sizeof(WCHAR)*l);
00394     l = MultiByteToWideChar(CP_ACP, 0, s, (int)l, wbuffer, (int)l);
00395 
00396     size_t bl=2*l; LPSTR buffer = (LPSTR)alloca(bl);
00397     l = WideCharToMultiByte(CP_UTF8, 0, wbuffer, (int)l, buffer, (int)bl, 0, 0);
00398 
00399     return std::string(buffer, l);
00400 }
00401 #endif
00402 
00403  // from XS internal string encoding to UTF-8
00404 inline std::string get_utf8(const XS_String& s)
00405 {
00406     return get_utf8(s.c_str(), s.length());
00407 }
00408 
00409 #endif // XS_STRING_UTF8
00410 
00411 extern std::string EncodeXMLString(const XS_String& str);
00412 extern XS_String DecodeXMLString(const XS_String& str);
00413 
00414 
00415 #ifdef __GNUC__
00416 #include <ext/stdio_filebuf.h>
00417 typedef __gnu_cxx::stdio_filebuf<char> STDIO_FILEBUF;
00418 #else
00419 typedef std::filebuf STDIO_FILEBUF;
00420 #endif
00421 
00422 struct FileHolder
00423 {
00424     FileHolder(LPCTSTR path, LPCTSTR mode)
00425     {
00426 #ifdef __STDC_WANT_SECURE_LIB__ // secure CRT functions using VS 2005
00427         if (_tfopen_s(&_pfile, path, mode) != 0)
00428             _pfile = NULL;
00429 #else
00430         _pfile = _tfopen(path, mode);
00431 #endif
00432     }
00433 
00434     ~FileHolder()
00435     {
00436         if (_pfile)
00437             fclose(_pfile);
00438     }
00439 
00440 protected:
00441     FILE*   _pfile;
00442 };
00443 
00444  /// input file stream with ANSI/UNICODE file names
00445 struct tifstream : public std::istream, FileHolder
00446 {
00447     typedef std::istream super;
00448 
00449     tifstream(LPCTSTR path)
00450      :  super(&_buf),
00451         FileHolder(path, TEXT("rb")),   // binary mode is important for XMLReader::read_buffer() with MinGW libraries
00452 #ifdef __GNUC__
00453         _buf(_pfile, std::ios::in)
00454 #else
00455         _buf(_pfile)
00456 #endif
00457     {
00458     }
00459 
00460 protected:
00461     STDIO_FILEBUF _buf;
00462 };
00463 
00464  /// output file stream with ANSI/UNICODE file names
00465 struct tofstream : public std::ostream, FileHolder
00466 {
00467     typedef std::ostream super;
00468 
00469     tofstream(LPCTSTR path)
00470      :  super(&_buf),
00471         FileHolder(path, TEXT("wb")),
00472 #ifdef __GNUC__
00473         _buf(_pfile, std::ios::out)
00474 #else
00475         _buf(_pfile)
00476 #endif
00477     {
00478     }
00479 
00480     ~tofstream()
00481     {
00482         flush();
00483     }
00484 
00485 protected:
00486     STDIO_FILEBUF _buf;
00487 };
00488 
00489 
00490  // write XML files with 2 spaces indenting
00491 #define XML_INDENT_SPACE "  "
00492 
00493 
00494 #if defined(XS_USE_XERCES) || defined(XS_USE_EXPAT)
00495 
00496 #if defined(XML_UNICODE)/*Expat*/ || defined(XS_USE_XERCES)/*Xerces*/   // Are Expat/Xerces XML strings UTF-16 encoded?
00497 typedef XS_String String_from_XML_Char;
00498 
00499 #elif defined(XS_STRING_UTF8)
00500 typedef XS_String String_from_XML_Char;
00501 
00502 #else
00503 
00504  /// converter from Expat/Xerces strings to XMLStorage internal strings
00505 struct String_from_XML_Char : public XS_String
00506 {
00507     String_from_XML_Char(const XML_Char* str)
00508     {
00509         assign_utf8(*this, str);
00510     }
00511 };
00512 
00513 #endif
00514 
00515 #endif // defined(XS_USE_XERCES) || defined(XS_USE_EXPAT)
00516 
00517 
00518 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
00519 
00520  // optimization for faster UNICODE/ASCII string comparison without temporary A/U conversion
00521 inline bool operator==(const XS_String& s1, const char* s2)
00522 {
00523     LPCWSTR p = s1;
00524     const unsigned char* q = (const unsigned char*)s2;
00525 
00526     while(*p && *q)
00527         if (*p++ != *q++)
00528             return false;
00529 
00530     return *p == *q;
00531 };
00532 
00533 #endif
00534 
00535 
00536  /// XML Error with message and location
00537 struct XMLError
00538 {
00539     XMLError()
00540      :  _line(0),
00541         _column(0),
00542         _error_code(0)
00543     {
00544     }
00545 
00546     std::string str() const;
00547     friend std::ostream& operator<<(std::ostream&, const XMLError& err);
00548 
00549     XS_String _message;
00550     XS_String _systemId;
00551     int _line;
00552     int _column;
00553     int _error_code;
00554 };
00555 
00556 struct XMLErrorList : public std::list<XMLError>
00557 {
00558     XS_String str() const;
00559 };
00560 
00561 
00562 #ifdef XMLNODE_LOCATION
00563  /// location of XML Node including XML file name
00564 struct XMLLocation
00565 {
00566     XMLLocation()
00567      :  _pdisplay_path(NULL),
00568         _line(0),
00569         _column(0)
00570     {
00571     }
00572 
00573     XMLLocation(const char* display_path, int line, int column)
00574      :  _pdisplay_path(display_path),
00575         _line(line),
00576         _column(column)
00577     {
00578     }
00579 
00580     std::string str() const;
00581 
00582 protected:
00583     const char* _pdisplay_path; // character pointer for fast reference
00584     int _line;
00585     int _column;
00586 };
00587 #endif
00588 
00589 
00590 enum PRETTY_FLAGS {
00591     PRETTY_PLAIN    = 0,
00592     PRETTY_LINEFEED = 1,
00593     PRETTY_INDENT   = 2
00594 };
00595 
00596 
00597 struct StyleSheet
00598 {
00599     std::string _href;      // CDATA #REQUIRED
00600     std::string _type;      // CDATA #REQUIRED
00601     std::string _title;     // CDATA #IMPLIED
00602     std::string _media;     // CDATA #IMPLIED
00603     std::string _charset;   // CDATA #IMPLIED
00604     bool        _alternate; // (yes|no) "no"
00605 
00606     StyleSheet() : _alternate(false) {}
00607 
00608     StyleSheet(const std::string& href, const std::string& type="text/xsl", bool alternate=false)
00609      :  _href(href),
00610         _type(type),
00611         _alternate(alternate)
00612     {
00613     }
00614 
00615     bool empty() const {return _href.empty();}
00616     void print(std::ostream& out) const;
00617 };
00618 
00619 struct StyleSheetList : public std::list<StyleSheet>
00620 {
00621     void    set(const StyleSheet& stylesheet)
00622     {
00623         clear();
00624         push_back(stylesheet);
00625     }
00626 };
00627 
00628 
00629 struct DocType
00630 {
00631     std::string _name;
00632 
00633      // External Document Types are noted, but not parsed.
00634     std::string _public;
00635     std::string _system;
00636 
00637      // Internal DTDs are not supported.
00638 
00639     void parse(const char* str);
00640     bool empty() const {return _name.empty();}
00641 };
00642 
00643  /// Management of XML file headers and formating
00644 struct XMLFormat
00645 {
00646     XMLFormat(PRETTY_FLAGS pretty=PRETTY_INDENT, const std::string& xml_version="1.0", const std::string& encoding="utf-8", const DocType& doctype=DocType())
00647      :  _pretty(pretty),
00648         _endl("\n"),
00649         _version(xml_version),
00650         _encoding(encoding),
00651         _doctype(doctype),
00652         _standalone(-1)
00653     {
00654     }
00655 
00656     void print_header(std::ostream& out, bool lf=true) const;
00657 
00658     PRETTY_FLAGS _pretty;
00659     const char* _endl;      // line ending string: "\n" or "\r\n"
00660 
00661     std::string _version;
00662     std::string _encoding;
00663 
00664     DocType     _doctype;
00665 
00666     StyleSheetList _stylesheets;
00667 
00668 //  std::string _additional;
00669 
00670     int     _standalone;
00671 };
00672 
00673 
00674 enum WRITE_MODE {
00675     FORMAT_PLAIN,       /// write XML without any white space
00676     FORMAT_SMART,       /// preserve original white space and comments if present; pretty print otherwise
00677     FORMAT_ORIGINAL,    /// write XML stream preserving original white space and comments
00678     FORMAT_PRETTY       /// pretty print node to stream without preserving original white space
00679 };
00680 
00681 
00682  /// in memory representation of an XML node
00683 struct XMLNode : public XS_String
00684 {
00685 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
00686      // optimized read access without temporary A/U conversion when using ASCII attribute names
00687     struct AttributeMap : public std::map<XS_String, XS_String>
00688     {
00689         typedef std::map<XS_String, XS_String> super;
00690 
00691         const_iterator find(const char* x) const
00692         {
00693             for(const_iterator it=begin(); it!=end(); ++it)
00694                 if (it->first == x)
00695                     return it;
00696 
00697             return end();
00698         }
00699 
00700         const_iterator find(const key_type& x) const
00701         {
00702             return super::find(x);
00703         }
00704 
00705         iterator find(const key_type& x)
00706         {
00707             return super::find(x);
00708         }
00709 
00710         XS_String get(const char* x, LPCXSSTR def=XS_EMPTY_STR) const
00711         {
00712             const_iterator found = find(x);
00713 
00714             if (found != end())
00715                 return found->second;
00716             else
00717                 return def;
00718         }
00719     };
00720 #else
00721     struct AttributeMap : public std::map<XS_String, XS_String>
00722     {
00723         XS_String get(const char* x, LPCXSSTR def=XS_EMPTY_STR) const
00724         {
00725             const_iterator found = find(x);
00726 
00727             if (found != end())
00728                 return found->second;
00729             else
00730                 return def;
00731         }
00732     };
00733 #endif
00734 
00735      /// internal children node list
00736     struct Children : public std::list<XMLNode*>
00737     {
00738         void assign(const Children& other)
00739         {
00740             clear();
00741 
00742             for(Children::const_iterator it=other.begin(); it!=other.end(); ++it)
00743                 push_back(new XMLNode(**it));
00744         }
00745 
00746         void clear()
00747         {
00748             while(!empty()) {
00749                 XMLNode* node = back();
00750                 pop_back();
00751 
00752                 node->clear();
00753                 delete node;
00754             }
00755         }
00756     };
00757 
00758      // access to protected class members for XMLPos and XMLReader
00759     friend struct XMLPos;
00760     friend struct const_XMLPos;
00761     friend struct XMLReaderBase;
00762 
00763     XMLNode(const XS_String& name)
00764      :  XS_String(name)
00765     {
00766     }
00767 
00768     XMLNode(const XS_String& name, const std::string& leading)
00769      :  XS_String(name),
00770         _leading(leading)
00771     {
00772     }
00773 
00774     XMLNode(const XMLNode& other)
00775      :  XS_String(other),
00776         _attributes(other._attributes),
00777         _leading(other._leading),
00778         _content(other._content),
00779         _end_leading(other._end_leading),
00780         _trailing(other._trailing)
00781 #ifdef XMLNODE_LOCATION
00782         , _location(other._location)
00783 #endif
00784     {
00785         for(Children::const_iterator it=other._children.begin(); it!=other._children.end(); ++it)
00786             _children.push_back(new XMLNode(**it));
00787     }
00788 
00789     virtual ~XMLNode()
00790     {
00791         while(!_children.empty()) {
00792             delete _children.back();
00793             _children.pop_back();
00794         }
00795     }
00796 
00797     void clear()
00798     {
00799         _leading.erase();
00800         _content.erase();
00801         _end_leading.erase();
00802         _trailing.erase();
00803 
00804         _attributes.clear();
00805         _children.clear();
00806 
00807         XS_String::erase();
00808     }
00809 
00810     XMLNode& operator=(const XMLNode& other)
00811     {
00812         _children.assign(other._children);
00813 
00814         _attributes = other._attributes;
00815 
00816         _leading = other._leading;
00817         _content = other._content;
00818         _end_leading = other._end_leading;
00819         _trailing = other._trailing;
00820 
00821         return *this;
00822     }
00823 
00824      /// add a new child node
00825     void add_child(XMLNode* child)
00826     {
00827         _children.push_back(child);
00828     }
00829 
00830      /// write access to an attribute
00831     void put(const XS_String& attr_name, const XS_String& value)
00832     {
00833         _attributes[attr_name] = value;
00834     }
00835 
00836      /// C++ write access to an attribute
00837     XS_String& operator[](const XS_String& attr_name)
00838     {
00839         return _attributes[attr_name];
00840     }
00841 
00842      /// read only access to an attribute
00843     template<typename T> XS_String get(const T& attr_name, LPCXSSTR def=XS_EMPTY_STR) const
00844     {
00845         AttributeMap::const_iterator found = _attributes.find(attr_name);
00846 
00847         if (found != _attributes.end())
00848             return found->second;
00849         else
00850             return def;
00851     }
00852 
00853      /// convenient value access in children node
00854     XS_String subvalue(const XS_String& name, const XS_String& attr_name, int n=0) const
00855     {
00856         const XMLNode* node = find(name, n);
00857 
00858         if (node)
00859             return node->get(attr_name);
00860         else
00861             return XS_String();
00862     }
00863 
00864      /// convenient storage of distinct values in children node
00865     XS_String& subvalue(const XS_String& name, const XS_String& attr_name, int n=0)
00866     {
00867         XMLNode* node = find(name, n);
00868 
00869         if (!node) {
00870             node = new XMLNode(name);
00871             add_child(node);
00872         }
00873 
00874         return (*node)[attr_name];
00875     }
00876 
00877 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
00878      /// convenient value access in children node
00879     XS_String subvalue(const char* name, const char* attr_name, int n=0) const
00880     {
00881         const XMLNode* node = find(name, n);
00882 
00883         if (node)
00884             return node->get(attr_name);
00885         else
00886             return XS_String();
00887     }
00888 
00889      /// convenient storage of distinct values in children node
00890     XS_String& subvalue(const char* name, const XS_String& attr_name, int n=0)
00891     {
00892         XMLNode* node = find(name, n);
00893 
00894         if (!node) {
00895             node = new XMLNode(name);
00896             add_child(node);
00897         }
00898 
00899         return (*node)[attr_name];
00900     }
00901 #endif
00902 
00903     const Children& get_children() const
00904     {
00905         return _children;
00906     }
00907 
00908     Children& get_children()
00909     {
00910         return _children;
00911     }
00912 
00913     const AttributeMap& get_attributes() const
00914     {
00915         return _attributes;
00916     }
00917 
00918     AttributeMap& get_attributes()
00919     {
00920         return _attributes;
00921     }
00922 
00923     XS_String get_content() const
00924     {
00925 #ifdef XS_STRING_UTF8
00926         const XS_String& ret = _content;
00927 #else
00928         XS_String ret;
00929         assign_utf8(ret, _content.c_str(), _content.length());
00930 #endif
00931 
00932         return DecodeXMLString(ret.c_str());
00933     }
00934 
00935     void set_content(const XS_String& s)
00936     {
00937         _content.assign(EncodeXMLString(s.c_str()));
00938     }
00939 
00940 #ifdef XMLNODE_LOCATION
00941     const XMLLocation& get_location() const {return _location;}
00942 #endif
00943 
00944      /// write node with children tree to output stream
00945     std::ostream& write(std::ostream& out, const XMLFormat& format, WRITE_MODE mode=FORMAT_SMART, int indent=0) const
00946     {
00947         switch(mode) {
00948           case FORMAT_PLAIN:
00949             plain_write_worker(out);
00950             break;
00951 
00952           case FORMAT_PRETTY:
00953             pretty_write_worker(out, format, indent);
00954             break;
00955 
00956           case FORMAT_ORIGINAL:
00957             write_worker(out, indent);
00958             break;
00959 
00960         default:     // FORMAT_SMART
00961             smart_write_worker(out, format, indent);
00962         }
00963 
00964         return out;
00965     }
00966 
00967 protected:
00968     Children _children;
00969     AttributeMap _attributes;
00970 
00971     std::string _leading;       // UTF-8 encoded
00972     std::string _content;       // UTF-8 and entity encoded, may contain CDATA sections; decode with DecodeXMLString()
00973     std::string _end_leading;   // UTF-8 encoded
00974     std::string _trailing;      // UTF-8 encoded
00975 
00976 #ifdef XMLNODE_LOCATION
00977     XMLLocation _location;
00978 #endif
00979 
00980     XMLNode* get_first_child() const
00981     {
00982         if (!_children.empty())
00983             return _children.front();
00984         else
00985             return NULL;
00986     }
00987 
00988     XMLNode* find(const XS_String& name, int n=0) const
00989     {
00990         for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
00991             if (**it == name)
00992                 if (!n--)
00993                     return *it;
00994 
00995         return NULL;
00996     }
00997 
00998     XMLNode* find(const XS_String& name, const XS_String& attr_name, const XS_String& attr_value, int n=0) const
00999     {
01000         for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it) {
01001             const XMLNode& node = **it;
01002 
01003             if (node==name && node.get(attr_name)==attr_value)
01004                 if (!n--)
01005                     return *it;
01006         }
01007 
01008         return NULL;
01009     }
01010 
01011 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
01012     XMLNode* find(const char* name, int n=0) const
01013     {
01014         for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
01015             if (**it == name)
01016                 if (!n--)
01017                     return *it;
01018 
01019         return NULL;
01020     }
01021 
01022     template<typename T, typename U>
01023     XMLNode* find(const char* name, const T& attr_name, const U& attr_value, int n=0) const
01024     {
01025         for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it) {
01026             const XMLNode& node = **it;
01027 
01028             if (node==name && node.get(attr_name)==attr_value)
01029                 if (!n--)
01030                     return *it;
01031         }
01032 
01033         return NULL;
01034     }
01035 #endif
01036 
01037      /// XPath find function (const)
01038     const XMLNode* find_relative(const char* path) const;
01039 
01040      /// XPath find function
01041     XMLNode* find_relative(const char* path)
01042         {return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->find_relative(path));}
01043 
01044      /// relative XPath create function
01045     XMLNode* create_relative(const char* path);
01046 
01047     void    write_worker(std::ostream& out, int indent) const;
01048     void    plain_write_worker(std::ostream& out) const;
01049     void    pretty_write_worker(std::ostream& out, const XMLFormat& format, int indent) const;
01050     void    smart_write_worker(std::ostream& out, const XMLFormat& format, int indent) const;
01051 };
01052 
01053 
01054  /// iterator access to children nodes with name filtering
01055 struct XMLChildrenFilter
01056 {
01057     XMLChildrenFilter(XMLNode::Children& children, const XS_String& name)
01058      :  _begin(children.begin(), children.end(), name),
01059         _end(children.end(), children.end(), name)
01060     {
01061     }
01062 
01063     XMLChildrenFilter(XMLNode* node, const XS_String& name)
01064      :  _begin(node->get_children().begin(), node->get_children().end(), name),
01065         _end(node->get_children().end(), node->get_children().end(), name)
01066     {
01067     }
01068 
01069      /// internal iterator class
01070     struct iterator
01071     {
01072         typedef XMLNode::Children::iterator BaseIterator;
01073 
01074         iterator(BaseIterator begin, BaseIterator end, const XS_String& filter_name)
01075          :  _cur(begin),
01076             _end(end),
01077             _filter_name(filter_name)
01078         {
01079             search_next();
01080         }
01081 
01082         operator BaseIterator()
01083         {
01084             return _cur;
01085         }
01086 
01087         const XMLNode* operator*() const
01088         {
01089             return *_cur;
01090         }
01091 
01092         XMLNode* operator*()
01093         {
01094             return *_cur;
01095         }
01096 
01097         iterator& operator++()
01098         {
01099             ++_cur;
01100             search_next();
01101 
01102             return *this;
01103         }
01104 
01105         iterator operator++(int)
01106         {
01107             iterator ret = *this;
01108 
01109             ++_cur;
01110             search_next();
01111 
01112             return ret;
01113         }
01114 
01115         bool operator==(const BaseIterator& other) const
01116         {
01117             return _cur == other;
01118         }
01119 
01120         bool operator!=(const BaseIterator& other) const
01121         {
01122             return _cur != other;
01123         }
01124 
01125     protected:
01126         BaseIterator    _cur;
01127         BaseIterator    _end;
01128         XS_String   _filter_name;
01129 
01130         void search_next()
01131         {
01132             while(_cur!=_end && **_cur!=_filter_name)
01133                 ++_cur;
01134         }
01135     };
01136 
01137     iterator begin()
01138     {
01139         return _begin;
01140     }
01141 
01142     iterator end()
01143     {
01144         return _end;
01145     }
01146 
01147 protected:
01148     iterator    _begin;
01149     iterator    _end;
01150 };
01151 
01152 
01153  /// read only iterator access to children nodes with name filtering
01154 struct const_XMLChildrenFilter
01155 {
01156     const_XMLChildrenFilter(const XMLNode::Children& children, const XS_String& name)
01157      :  _begin(children.begin(), children.end(), name),
01158         _end(children.end(), children.end(), name)
01159     {
01160     }
01161 
01162     const_XMLChildrenFilter(const XMLNode* node, const XS_String& name)
01163      :  _begin(node->get_children().begin(), node->get_children().end(), name),
01164         _end(node->get_children().end(), node->get_children().end(), name)
01165     {
01166     }
01167 
01168      /// internal iterator class
01169     struct const_iterator
01170     {
01171         typedef XMLNode::Children::const_iterator BaseIterator;
01172 
01173         const_iterator(BaseIterator begin, BaseIterator end, const XS_String& filter_name)
01174          :  _cur(begin),
01175             _end(end),
01176             _filter_name(filter_name)
01177         {
01178             search_next();
01179         }
01180 
01181         operator BaseIterator()
01182         {
01183             return _cur;
01184         }
01185 
01186         const XMLNode* operator*() const
01187         {
01188             return *_cur;
01189         }
01190 
01191         const_iterator& operator++()
01192         {
01193             ++_cur;
01194             search_next();
01195 
01196             return *this;
01197         }
01198 
01199         const_iterator operator++(int)
01200         {
01201             const_iterator ret = *this;
01202 
01203             ++_cur;
01204             search_next();
01205 
01206             return ret;
01207         }
01208 
01209         bool operator==(const BaseIterator& other) const
01210         {
01211             return _cur == other;
01212         }
01213 
01214         bool operator!=(const BaseIterator& other) const
01215         {
01216             return _cur != other;
01217         }
01218 
01219     protected:
01220         BaseIterator    _cur;
01221         BaseIterator    _end;
01222         XS_String   _filter_name;
01223 
01224         void search_next()
01225         {
01226             while(_cur!=_end && **_cur!=_filter_name)
01227                 ++_cur;
01228         }
01229     };
01230 
01231     const_iterator begin()
01232     {
01233         return _begin;
01234     }
01235 
01236     const_iterator end()
01237     {
01238         return _end;
01239     }
01240 
01241 protected:
01242     const_iterator  _begin;
01243     const_iterator  _end;
01244 };
01245 
01246 
01247  /// iterator for XML trees
01248 struct XMLPos
01249 {
01250     XMLPos(XMLNode* root)
01251      :  _root(root),
01252         _cur(root)
01253     {
01254     }
01255 
01256     XMLPos(const XMLPos& other)
01257      :  _root(other._root),
01258         _cur(other._cur)
01259     {   // don't copy _stack
01260     }
01261 
01262     XMLPos(XMLNode* node, const XS_String& name)
01263      :  _root(node),
01264         _cur(node)
01265     {
01266         smart_create(name);
01267     }
01268 
01269     XMLPos(XMLNode* node, const XS_String& name, const XS_String& attr_name, const XS_String& attr_value)
01270      :  _root(node),
01271         _cur(node)
01272     {
01273         smart_create(name, attr_name, attr_value);
01274     }
01275 
01276     XMLPos(const XMLPos& other, const XS_String& name)
01277      :  _root(other._root),
01278         _cur(other._cur)
01279     {
01280         smart_create(name);
01281     }
01282 
01283     XMLPos(const XMLPos& other, const XS_String& name, const XS_String& attr_name, const XS_String& attr_value)
01284      :  _root(other._root),
01285         _cur(other._cur)
01286     {
01287         smart_create(name, attr_name, attr_value);
01288     }
01289 
01290      /// access to current node
01291     XMLNode& cur()
01292     {
01293         return *_cur;
01294     }
01295 
01296     const XMLNode& cur() const
01297     {
01298         return *_cur;
01299     }
01300 
01301      /// C++ access to current node
01302     operator const XMLNode*() const {return _cur;}
01303     operator XMLNode*() {return _cur;}
01304 
01305     const XMLNode* operator->() const {return _cur;}
01306     XMLNode* operator->() {return _cur;}
01307 
01308     const XMLNode& operator*() const {return *_cur;}
01309     XMLNode& operator*() {return *_cur;}
01310 
01311      /// attribute access
01312     XS_String get(const XS_String& attr_name) const
01313     {
01314         return _cur->get(attr_name);
01315     }
01316 
01317      /// attribute setting
01318     void put(const XS_String& attr_name, const XS_String& value)
01319     {
01320         _cur->put(attr_name, value);
01321     }
01322 
01323      /// C++ attribute access
01324     template<typename T> XS_String get(const T& attr_name) const {return (*_cur)[attr_name];}
01325     XS_String& operator[](const XS_String& attr_name) {return (*_cur)[attr_name];}
01326 
01327      /// insert children when building tree
01328     void add_down(XMLNode* child)
01329     {
01330         _cur->add_child(child);
01331         go_to(child);
01332     }
01333 
01334      /// go back to previous position
01335     bool back()
01336     {
01337         if (!_stack.empty()) {
01338             _cur = _stack.top();
01339             _stack.pop();
01340             return true;
01341         } else
01342             return false;
01343     }
01344 
01345      /// go down to first child
01346     bool go_down()
01347     {
01348         XMLNode* node = _cur->get_first_child();
01349 
01350         if (node) {
01351             go_to(node);
01352             return true;
01353         } else
01354             return false;
01355     }
01356 
01357      /// search for child and go down
01358     bool go_down(const XS_String& name, int n=0)
01359     {
01360         XMLNode* node = _cur->find(name, n);
01361 
01362         if (node) {
01363             go_to(node);
01364             return true;
01365         } else
01366             return false;
01367     }
01368 
01369      /// move XPath like to position in XML tree
01370     bool go(const char* path);
01371 
01372      /// create child nodes using XPath notation and move to the deepest child
01373     bool create_relative(const char* path)
01374     {
01375         XMLNode* node = _cur->create_relative(path);
01376         if (!node)
01377             return false;   // invalid path specified
01378 
01379         go_to(node);
01380         return true;
01381     }
01382 
01383      /// create node and move to it
01384     void create(const XS_String& name)
01385     {
01386         add_down(new XMLNode(name));
01387     }
01388 
01389      /// create node if not already existing and move to it
01390     void smart_create(const XS_String& name)
01391     {
01392         XMLNode* node = _cur->find(name);
01393 
01394         if (node)
01395             go_to(node);
01396         else
01397             add_down(new XMLNode(name));
01398     }
01399 
01400      /// search matching child node identified by key name and an attribute value
01401     void smart_create(const XS_String& name, const XS_String& attr_name, const XS_String& attr_value)
01402     {
01403         XMLNode* node = _cur->find(name, attr_name, attr_value);
01404 
01405         if (node)
01406             go_to(node);
01407         else {
01408             node = new XMLNode(name);
01409             add_down(node);
01410             (*node)[attr_name] = attr_value;
01411         }
01412     }
01413 
01414 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
01415      /// search for child and go down
01416     bool go_down(const char* name, int n=0)
01417     {
01418         XMLNode* node = _cur->find(name, n);
01419 
01420         if (node) {
01421             go_to(node);
01422             return true;
01423         } else
01424             return false;
01425     }
01426 
01427      /// create node and move to it
01428     void create(const char* name)
01429     {
01430         add_down(new XMLNode(name));
01431     }
01432 
01433      /// create node if not already existing and move to it
01434     void smart_create(const char* name)
01435     {
01436         XMLNode* node = _cur->find(name);
01437 
01438         if (node)
01439             go_to(node);
01440         else
01441             add_down(new XMLNode(name));
01442     }
01443 
01444      /// search matching child node identified by key name and an attribute value
01445     template<typename T, typename U>
01446     void smart_create(const char* name, const T& attr_name, const U& attr_value)
01447     {
01448         XMLNode* node = _cur->find(name, attr_name, attr_value);
01449 
01450         if (node)
01451             go_to(node);
01452         else {
01453             XMLNode* node = new XMLNode(name);
01454             add_down(node);
01455             (*node)[attr_name] = attr_value;
01456         }
01457     }
01458 #endif
01459 
01460     XS_String& str() {return *_cur;}
01461     const XS_String& str() const {return *_cur;}
01462 
01463 protected:
01464     XMLNode* _root;
01465     XMLNode* _cur;
01466     std::stack<XMLNode*> _stack;
01467 
01468      /// go to specified node
01469     void go_to(XMLNode* child)
01470     {
01471         _stack.push(_cur);
01472         _cur = child;
01473     }
01474 };
01475 
01476 
01477  /// iterator for XML trees
01478 struct const_XMLPos
01479 {
01480     const_XMLPos(const XMLNode* root)
01481      :  _root(root),
01482         _cur(root)
01483     {
01484     }
01485 
01486     const_XMLPos(const const_XMLPos& other)
01487      :  _root(other._root),
01488         _cur(other._cur)
01489     {   // don't copy _stack
01490     }
01491 
01492      /// access to current node
01493     const XMLNode& cur() const
01494     {
01495         return *_cur;
01496     }
01497 
01498      /// C++ access to current node
01499     operator const XMLNode*() const {return _cur;}
01500 
01501     const XMLNode* operator->() const {return _cur;}
01502 
01503     const XMLNode& operator*() const {return *_cur;}
01504 
01505      /// attribute access
01506     XS_String get(const XS_String& attr_name) const
01507     {
01508         return _cur->get(attr_name);
01509     }
01510 
01511      /// C++ attribute access
01512     template<typename T> XS_String get(const T& attr_name) const {return _cur->get(attr_name);}
01513 
01514      /// go back to previous position
01515     bool back()
01516     {
01517         if (!_stack.empty()) {
01518             _cur = _stack.top();
01519             _stack.pop();
01520             return true;
01521         } else
01522             return false;
01523     }
01524 
01525      /// go down to first child
01526     bool go_down()
01527     {
01528         const XMLNode* node = _cur->get_first_child();
01529 
01530         if (node) {
01531             go_to(node);
01532             return true;
01533         } else
01534             return false;
01535     }
01536 
01537      /// search for child and go down
01538     bool go_down(const XS_String& name, int n=0)
01539     {
01540         XMLNode* node = _cur->find(name, n);
01541 
01542         if (node) {
01543             go_to(node);
01544             return true;
01545         } else
01546             return false;
01547     }
01548 
01549      /// move XPath like to position in XML tree
01550     bool go(const char* path);
01551 
01552 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
01553      /// search for child and go down
01554     bool go_down(const char* name, int n=0)
01555     {
01556         XMLNode* node = _cur->find(name, n);
01557 
01558         if (node) {
01559             go_to(node);
01560             return true;
01561         } else
01562             return false;
01563     }
01564 #endif
01565 
01566     const XS_String& str() const {return *_cur;}
01567 
01568 protected:
01569     const XMLNode* _root;
01570     const XMLNode* _cur;
01571     std::stack<const XMLNode*> _stack;
01572 
01573      /// go to specified node
01574     void go_to(const XMLNode* child)
01575     {
01576         _stack.push(_cur);
01577         _cur = child;
01578     }
01579 };
01580 
01581 
01582  /// type converter for boolean data
01583 struct XMLBool
01584 {
01585     XMLBool(bool value=false)
01586      :  _value(value)
01587     {
01588     }
01589 
01590     XMLBool(LPCXSSTR value, bool def=false)
01591     {
01592         if (value && *value)
01593             _value = !XS_icmp(value, XS_TRUE);
01594         else
01595             _value = def;
01596     }
01597 
01598     XMLBool(const XMLNode* node, const XS_String& attr_name, bool def=false)
01599     {
01600         const XS_String& value = node->get(attr_name);
01601 
01602         if (!value.empty())
01603             _value = !XS_icmp(value.c_str(), XS_TRUE);
01604         else
01605             _value = def;
01606     }
01607 
01608     operator bool() const
01609     {
01610         return _value;
01611     }
01612 
01613     bool operator!() const
01614     {
01615         return !_value;
01616     }
01617 
01618     operator LPCXSSTR() const
01619     {
01620         return _value? XS_TRUE: XS_FALSE;
01621     }
01622 
01623 protected:
01624     bool    _value;
01625 
01626 private:
01627     void operator=(const XMLBool&); // disallow assignment operations
01628 };
01629 
01630  /// type converter for boolean data with write access
01631 struct XMLBoolRef
01632 {
01633     XMLBoolRef(XMLNode* node, const XS_String& attr_name, bool def=false)
01634      :  _ref((*node)[attr_name])
01635     {
01636         if (_ref.empty())
01637             assign(def);
01638     }
01639 
01640     operator bool() const
01641     {
01642         return !XS_icmp(_ref.c_str(), XS_TRUE);
01643     }
01644 
01645     bool operator!() const
01646     {
01647         return XS_icmp(_ref.c_str(), XS_TRUE)? true: false;
01648     }
01649 
01650     XMLBoolRef& operator=(bool value)
01651     {
01652         assign(value);
01653 
01654         return *this;
01655     }
01656 
01657     void assign(bool value)
01658     {
01659         _ref.assign(value? XS_TRUE: XS_FALSE);
01660     }
01661 
01662     void toggle()
01663     {
01664         assign(!operator bool());
01665     }
01666 
01667 protected:
01668     XS_String& _ref;
01669 };
01670 
01671 
01672  /// type converter for integer data
01673 struct XMLInt
01674 {
01675     XMLInt(int value)
01676      :  _value(value)
01677     {
01678     }
01679 
01680     XMLInt(LPCXSSTR value, int def=0)
01681     {
01682         if (value && *value)
01683             _value = XS_toi(value);
01684         else
01685             _value = def;
01686     }
01687 
01688     XMLInt(const XMLNode* node, const XS_String& attr_name, int def=0)
01689     {
01690         const XS_String& value = node->get(attr_name);
01691 
01692         if (!value.empty())
01693             _value = XS_toi(value.c_str());
01694         else
01695             _value = def;
01696     }
01697 
01698     operator int() const
01699     {
01700         return _value;
01701     }
01702 
01703     operator XS_String() const
01704     {
01705         XS_CHAR buffer[32];
01706         XS_snprintf(buffer, COUNTOF(buffer), XS_INTFMT, _value);
01707         return buffer;
01708     }
01709 
01710 protected:
01711     int _value;
01712 
01713 private:
01714     void operator=(const XMLInt&); // disallow assignment operations
01715 };
01716 
01717  /// type converter for integer data with write access
01718 struct XMLIntRef
01719 {
01720     XMLIntRef(XMLNode* node, const XS_String& attr_name, int def=0)
01721      :  _ref((*node)[attr_name])
01722     {
01723         if (_ref.empty())
01724             assign(def);
01725     }
01726 
01727     XMLIntRef& operator=(int value)
01728     {
01729         assign(value);
01730 
01731         return *this;
01732     }
01733 
01734     operator int() const
01735     {
01736         return XS_toi(_ref.c_str());
01737     }
01738 
01739     void assign(int value)
01740     {
01741         XS_CHAR buffer[32];
01742         XS_snprintf(buffer, COUNTOF(buffer), XS_INTFMT, value);
01743         _ref.assign(buffer);
01744     }
01745 
01746 protected:
01747     XS_String& _ref;
01748 };
01749 
01750 
01751  /// type converter for numeric data
01752 struct XMLDouble
01753 {
01754     XMLDouble(double value)
01755      :  _value(value)
01756     {
01757     }
01758 
01759     XMLDouble(LPCXSSTR value, double def=0.)
01760     {
01761         LPTSTR end;
01762 
01763         if (value && *value)
01764             _value = XS_tod(value, &end);
01765         else
01766             _value = def;
01767     }
01768 
01769     XMLDouble(const XMLNode* node, const XS_String& attr_name, double def=0.)
01770     {
01771         LPTSTR end;
01772         const XS_String& value = node->get(attr_name);
01773 
01774         if (!value.empty())
01775             _value = XS_tod(value.c_str(), &end);
01776         else
01777             _value = def;
01778     }
01779 
01780     operator double() const
01781     {
01782         return _value;
01783     }
01784 
01785     operator XS_String() const
01786     {
01787         XS_CHAR buffer[32];
01788         XS_snprintf(buffer, COUNTOF(buffer), XS_FLOATFMT, _value);
01789         return buffer;
01790     }
01791 
01792 protected:
01793     double _value;
01794 
01795 private:
01796     void operator=(const XMLDouble&); // disallow assignment operations
01797 };
01798 
01799  /// type converter for numeric data with write access
01800 struct XMLDoubleRef
01801 {
01802     XMLDoubleRef(XMLNode* node, const XS_String& attr_name, double def=0.)
01803      :  _ref((*node)[attr_name])
01804     {
01805         if (_ref.empty())
01806             assign(def);
01807     }
01808 
01809     XMLDoubleRef& operator=(double value)
01810     {
01811         assign(value);
01812 
01813         return *this;
01814     }
01815 
01816     operator double() const
01817     {
01818         LPTSTR end;
01819         return XS_tod(_ref.c_str(), &end);
01820     }
01821 
01822     void assign(double value)
01823     {
01824         XS_CHAR buffer[32];
01825         XS_snprintf(buffer, COUNTOF(buffer), XS_FLOATFMT, value);
01826         _ref.assign(buffer);
01827     }
01828 
01829 protected:
01830     XS_String& _ref;
01831 };
01832 
01833 
01834  /// type converter for string data
01835 struct XMLString
01836 {
01837     XMLString(const XS_String& value)
01838      :  _value(value)
01839     {
01840     }
01841 
01842     XMLString(LPCXSSTR value, LPCXSSTR def=XS_EMPTY)
01843     {
01844         if (value && *value)
01845             _value = value;
01846         else
01847             _value = def;
01848     }
01849 
01850     XMLString(const XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_EMPTY)
01851     {
01852         const XS_String& value = node->get(attr_name);
01853 
01854         if (!value.empty())
01855             _value = value;
01856         else
01857             _value = def;
01858     }
01859 
01860     operator const XS_String&() const
01861     {
01862         return _value;
01863     }
01864 
01865     const XS_String& c_str() const
01866     {
01867         return _value;
01868     }
01869 
01870 protected:
01871     XS_String   _value;
01872 
01873 private:
01874     void operator=(const XMLString&); // disallow assignment operations
01875 };
01876 
01877  /// type converter for string data with write access
01878 struct XMStringRef
01879 {
01880     XMStringRef(XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_EMPTY)
01881      :  _ref((*node)[attr_name])
01882     {
01883         if (_ref.empty())
01884             assign(def);
01885     }
01886 
01887     XMStringRef(XMLNode* node, const XS_String& node_name, const XS_String& attr_name, LPCXSSTR def=XS_EMPTY)
01888      :  _ref(node->subvalue(node_name, attr_name))
01889     {
01890         if (_ref.empty())
01891             assign(def);
01892     }
01893 
01894     XMStringRef& operator=(const XS_String& value)
01895     {
01896         assign(value);
01897 
01898         return *this;
01899     }
01900 
01901     operator const XS_String&() const
01902     {
01903         return _ref;
01904     }
01905 
01906     void assign(const XS_String& value)
01907     {
01908         _ref.assign(value);
01909     }
01910 
01911 protected:
01912     XS_String& _ref;
01913 };
01914 
01915 
01916 template<typename T>
01917     inline void read_option(T& var, const_XMLPos& cfg, LPCXSSTR key)
01918     {
01919         const XS_String& val = cfg.get(key);
01920 
01921         if (!val.empty())
01922             var = val;
01923     }
01924 
01925 template<>
01926     inline void read_option(int& var, const_XMLPos& cfg, LPCXSSTR key)
01927     {
01928         const XS_String& val = cfg.get(key);
01929 
01930         if (!val.empty())
01931             var = XS_toi(val.c_str());
01932     }
01933 
01934 
01935 #ifdef _MSC_VER
01936 #pragma warning(disable: 4355)
01937 #endif
01938 
01939  /// XML reader base class
01940 struct XMLReaderBase
01941 #ifdef XS_USE_XERCES
01942  : public HandlerBase
01943 #endif
01944 {
01945 #ifdef XS_USE_XERCES
01946 
01947     XMLReaderBase(XMLNode* node, InputSource* source, bool adoptSource=false);
01948     virtual ~XMLReaderBase();
01949 
01950     void read();
01951 
01952 protected:
01953     SAXParser*  _parser;
01954     InputSource* _source;
01955     bool        _deleteSource;
01956 
01957     virtual void XMLDecl(const XMLCh* const versionStr, const XMLCh* const encodingStr,
01958                          const XMLCh* const standaloneStr, const XMLCh* const actualEncodingStr);
01959 
01960      // Handlers for the SAX DocumentHandler interface
01961     virtual void setDocumentLocator(const Locator* const locator);
01962     virtual void startElement(const XMLCh* const name, AttributeList& attributes);
01963     virtual void endElement(const XMLCh* const name);
01964     virtual void characters(const XMLCh* const chars, const unsigned int length);
01965     virtual void ignorableWhitespace(const XMLCh* const chars, const unsigned int length);
01966 
01967      // Handlers for the SAX ErrorHandler interface
01968     virtual void error(const SAXParseException& e);
01969     virtual void fatalError(const SAXParseException& e);
01970     virtual void warning(const SAXParseException& e);
01971     virtual void resetErrors();
01972 
01973 #elif defined(XS_USE_EXPAT) // !XS_USE_XERCES
01974 
01975     XMLReaderBase(XMLNode* node);
01976     virtual ~XMLReaderBase();
01977 
01978 protected:
01979     XML_Parser  _parser;
01980 
01981     static void XMLCALL XML_XmlDeclHandler(void* userData, const XML_Char* version, const XML_Char* encoding, int standalone=-1);
01982     static void XMLCALL XML_StartElementHandler(void* userData, const XML_Char* name, const XML_Char** atts);
01983     static void XMLCALL XML_EndElementHandler(void* userData, const XML_Char* name);
01984     static void XMLCALL XML_DefaultHandler(void* userData, const XML_Char* s, int len);
01985 
01986     static std::string get_expat_error_string(XML_Error error_code);
01987 
01988 #else // XS_USE_EXPAT
01989 
01990     XMLReaderBase(XMLNode* node)
01991      :  _pos(node),
01992         _endl_defined(false),
01993         _utf8(false)
01994     {
01995         _last_tag = TAG_NONE;
01996     }
01997 
01998     virtual ~XMLReaderBase();
01999 
02000     bool    parse();
02001 
02002 #endif
02003 
02004 public:
02005 #ifndef XS_USE_XERCES
02006     void read();
02007 
02008     std::string get_position() const;
02009 #endif
02010     const XMLFormat& get_format() const {return _format;}
02011     const char* get_endl() const {return _endl_defined? _format._endl: "\n";}
02012 
02013     const XMLErrorList& get_errors() const {return _errors;}
02014     const XMLErrorList& get_warnings() const {return _warnings;}
02015 
02016     void clear_errors() {_errors.clear(); _warnings.clear();}
02017 
02018 #ifdef XMLNODE_LOCATION
02019     const char* _display_path;  // character pointer for fast reference in XMLLocation
02020 
02021 #ifdef XS_USE_XERCES
02022     const Locator* _locator;
02023 #endif
02024 
02025     XMLLocation get_location() const;
02026 #endif
02027 
02028 protected:
02029     XMLPos      _pos;
02030 
02031     std::string _content;       // UTF-8 encoded
02032     enum {TAG_NONE, TAG_START, TAG_END} _last_tag;
02033 
02034     XMLErrorList _errors;
02035     XMLErrorList _warnings;
02036 
02037     XMLFormat   _format;
02038     bool    _endl_defined;
02039 
02040 #ifdef XS_USE_XERCES
02041     //@@
02042 #elif defined(XS_USE_EXPAT)
02043     virtual int read_buffer(char* buffer, int len) = 0;
02044 #else
02045     virtual int get() = 0;
02046     int     eat_endl();
02047 
02048     bool    _utf8;
02049 #endif
02050 
02051     void    finish_read();
02052 
02053     virtual void XmlDeclHandler(const char* version, const char* encoding, int standalone);
02054     virtual void StartElementHandler(const XS_String& name, const XMLNode::AttributeMap& attributes);
02055     virtual void EndElementHandler();
02056 #if defined(XS_USE_XERCES) || defined(XS_USE_EXPAT)
02057     virtual void DefaultHandler(const XML_Char* s, int len);
02058 #else
02059     virtual void DefaultHandler(const std::string& s);
02060 #endif
02061 };
02062 
02063 
02064  /// XML file reader
02065 
02066 #ifdef XS_USE_XERCES
02067 
02068 struct XercesXMLReader : public XMLReaderBase
02069 {
02070     XercesXMLReader(XMLNode* node, InputSource* source, bool adoptSource=false)
02071      :  XMLReaderBase(node, source, adoptSource)
02072     {
02073     }
02074 
02075     XercesXMLReader(XMLNode* node, LPCTSTR path);
02076     XercesXMLReader(XMLNode* node, const XMLByte* buffer, size_t bytes, const std::string& system_id=std::string());
02077 };
02078 
02079 #define XMLReader XercesXMLReader
02080 
02081 #elif defined(XS_USE_EXPAT)
02082 
02083 struct ExpatXMLReader : public XMLReaderBase
02084 {
02085     ExpatXMLReader(XMLNode* node, std::istream& in)
02086      :  XMLReaderBase(node),
02087         _in(in)
02088     {
02089     }
02090 
02091      /// read XML stream into XML tree below _pos
02092     int read_buffer(char* buffer, int len)
02093     {
02094         if (!_in.good())
02095             return -1;
02096 
02097         _in.read(buffer, len);
02098 
02099         return _in.gcount();
02100     }
02101 
02102 protected:
02103     std::istream&   _in;
02104 };
02105 
02106 #define XMLReader ExpatXMLReader
02107 
02108 #else // XS_USE_XERCES, XS_USE_EXPAT
02109 
02110 struct XMLReader : public XMLReaderBase
02111 {
02112     XMLReader(XMLNode* node, std::istream& in)
02113      :  XMLReaderBase(node),
02114         _in(in)
02115     {
02116     }
02117 
02118      /// read one character from XML stream
02119     int get()
02120     {
02121         return _in.get();
02122     }
02123 
02124 protected:
02125     std::istream&   _in;
02126 };
02127 
02128 #endif // XS_USE_XERCES
02129 
02130 
02131  /// XML document holder
02132 struct XMLDoc : public XMLNode
02133 {
02134     XMLDoc()
02135      :  XMLNode("")
02136     {
02137     }
02138 
02139     XMLDoc(LPCTSTR path)
02140      :  XMLNode("")
02141     {
02142         read(path);
02143     }
02144 
02145 #ifdef XS_USE_XERCES
02146     bool read(LPCTSTR path)
02147     {
02148         XMLReader reader(this, path);
02149 
02150 #if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8)
02151         return read(reader, std::string(ANS(path)));
02152 #else
02153         return read(reader, XS_String(path));
02154 #endif
02155     }
02156 
02157     bool read(const char* buffer, size_t len, const std::string& system_id=std::string())
02158     {
02159         XMLReader reader(this, (const XMLByte*)buffer, len, system_id);
02160 
02161         return read(reader, system_id);
02162     }
02163 
02164 #else // XS_USE_XERCES
02165 
02166     bool read(LPCTSTR path)
02167     {
02168         tifstream in(path);
02169         XMLReader reader(this, in);
02170 
02171 #if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8)
02172         return read(reader, std::string(ANS(path)));
02173 #else
02174         return read(reader, XS_String(path));
02175 #endif
02176     }
02177 
02178     bool read(const char* buffer, size_t len, const std::string& system_id=std::string())
02179     {
02180         std::istringstream in(std::string(buffer, len));
02181 
02182         return read(in, system_id);
02183     }
02184 
02185     bool read(std::istream& in, const std::string& system_id=std::string())
02186     {
02187         XMLReader reader(this, in);
02188 
02189         return read(reader, system_id);
02190     }
02191 #endif // XS_USE_XERCES
02192 
02193     bool read(XMLReaderBase& reader, const std::string& display_path)
02194     {
02195 #ifdef XMLNODE_LOCATION
02196          // make a string copy to handle temporary string objects
02197         _display_path = display_path;
02198         reader._display_path = _display_path.c_str();
02199 #endif
02200 
02201         reader.clear_errors();
02202         reader.read();
02203 
02204         _format = reader.get_format();
02205         _format._endl = reader.get_endl();
02206 
02207         if (!reader.get_errors().empty()) {
02208             _errors = reader.get_errors();
02209             return false;
02210         }
02211 
02212         return true;
02213     }
02214 
02215      /// write XML stream preserving previous white space and comments
02216     std::ostream& write(std::ostream& out, WRITE_MODE mode=FORMAT_SMART) const
02217     {
02218         _format.print_header(out, mode!=FORMAT_PLAIN);
02219 
02220         if (!_children.empty())
02221             _children.front()->write(out, _format, mode);
02222 
02223         return out;
02224     }
02225 
02226      /// write XML stream with formating
02227     std::ostream& write_formating(std::ostream& out) const
02228     {
02229         return write(out, FORMAT_PRETTY);
02230     }
02231 
02232     bool write(LPCTSTR path, WRITE_MODE mode=FORMAT_SMART) const
02233     {
02234         tofstream out(path);
02235 
02236         return write(out, mode).good();
02237     }
02238 
02239     bool write_formating(LPCTSTR path) const
02240     {
02241         tofstream out(path);
02242 
02243         return write_formating(out).good();
02244     }
02245 
02246     XMLFormat       _format;
02247     XMLErrorList    _errors;
02248 
02249 #ifdef XMLNODE_LOCATION
02250     std::string     _display_path;
02251 #endif
02252 };
02253 
02254 
02255  /// XML message wrapper
02256 struct XMLMessage : public XMLDoc
02257 {
02258     XMLMessage(const char* name)
02259      :  _pos(this)
02260     {
02261         _pos.create(name);
02262     }
02263 
02264     std::string toString() const
02265     {
02266         std::ostringstream out;
02267 
02268         write(out);
02269 
02270         return out.str();
02271     }
02272 
02273     XMLPos  _pos;
02274 
02275 protected:
02276     XMLMessage()
02277      :  _pos(this)
02278     {
02279     }
02280 };
02281 
02282 
02283 struct XMLMessageFromString : public XMLMessage
02284 {
02285     XMLMessageFromString(const std::string& xml_str, const std::string& system_id=std::string())
02286     {
02287         read(xml_str.c_str(), xml_str.length(), system_id);
02288     }
02289 };
02290 
02291 
02292  /// Reader for XML Messages
02293 struct XMLMessageReader : public XMLPos
02294 {
02295     XMLMessageReader(const std::string& xml_str, const std::string& system_id=std::string())
02296      :  XMLPos(&_msg)
02297     {
02298         _msg.read(xml_str.c_str(), xml_str.length(), system_id);
02299     }
02300 
02301     const XMLDoc& get_document()
02302     {
02303         return _msg;
02304     }
02305 
02306 protected:
02307     XMLDoc  _msg;
02308 };
02309 
02310 
02311 struct XMLWriter
02312 {
02313     XMLWriter(std::ostream& out, const XMLFormat& format=XMLFormat())
02314      :  _pofstream(NULL),
02315         _out(out),
02316         _format(format)
02317     {
02318         format.print_header(_out, false);   // _format._endl is printed in write_pre()
02319     }
02320 
02321     XMLWriter(LPCTSTR path, const XMLFormat& format=XMLFormat())
02322      :  _pofstream(new tofstream(path)),
02323         _out(*_pofstream),
02324         _format(format)
02325     {
02326         format.print_header(_out, false);   // _format._endl is printed in write_pre()
02327     }
02328 
02329     ~XMLWriter()
02330     {
02331         _out << _format._endl;
02332         delete _pofstream;
02333     }
02334 
02335      /// create node and move to it
02336     void create(const XS_String& name)
02337     {
02338         if (!_stack.empty()) {
02339             StackEntry& last = _stack.top();
02340 
02341             if (last._state < PRE_CLOSED) {
02342                 write_attributes(last);
02343                 close_pre(last);
02344             }
02345 
02346             ++last._children;
02347         }
02348 
02349         StackEntry entry;
02350         entry._node_name = name;
02351         _stack.push(entry);
02352 
02353         write_pre(entry);
02354     }
02355 
02356      /// go back to previous position
02357     bool back()
02358     {
02359         if (!_stack.empty()) {
02360             write_post(_stack.top());
02361 
02362             _stack.pop();
02363             return true;
02364         } else
02365             return false;
02366     }
02367 
02368      /// attribute setting
02369     void put(const XS_String& attr_name, const XS_String& value)
02370     {
02371         if (!_stack.empty())
02372             _stack.top()._attributes[attr_name] = value;
02373     }
02374 
02375      /// C++ write access to an attribute
02376     XS_String& operator[](const XS_String& attr_name)
02377     {
02378         if (_stack.empty())
02379             return s_empty_attr;
02380 
02381         return _stack.top()._attributes[attr_name];
02382     }
02383 
02384     void set_content(const XS_String& s)
02385     {
02386         if (!_stack.empty())
02387             _stack.top()._content = EncodeXMLString(s.c_str());
02388     }
02389 
02390      // public for access in StackEntry
02391     enum WRITESTATE {
02392         NOTHING, /*PRE,*/ ATTRIBUTES, PRE_CLOSED, /*CONTENT,*/ POST
02393     };
02394 
02395 protected:
02396     tofstream*      _pofstream;
02397     std::ostream&   _out;
02398     const XMLFormat&_format;
02399 
02400     typedef XMLNode::AttributeMap AttrMap;
02401 
02402     struct StackEntry {
02403         XS_String   _node_name;
02404         AttrMap     _attributes;
02405         std::string _content;
02406         WRITESTATE  _state;
02407         bool        _children;
02408 
02409         StackEntry() : _state(NOTHING), _children(false) {}
02410     };
02411 
02412     std::stack<StackEntry> _stack;
02413 
02414     static XS_String s_empty_attr;
02415 
02416     void close_pre(StackEntry& entry)
02417     {
02418         _out << '>';
02419 
02420         entry._state = PRE_CLOSED;
02421     }
02422 
02423     void write_pre(StackEntry& entry)
02424     {
02425         if (_format._pretty >= PRETTY_LINEFEED)
02426             _out << _format._endl;
02427 
02428         if (_format._pretty == PRETTY_INDENT)
02429             for(size_t i=_stack.size(); --i>0; )
02430                 _out << XML_INDENT_SPACE;
02431 
02432         _out << '<' << EncodeXMLString(entry._node_name);
02433         //entry._state = PRE;
02434     }
02435 
02436     void write_attributes(StackEntry& entry)
02437     {
02438         for(AttrMap::const_iterator it=entry._attributes.begin(); it!=entry._attributes.end(); ++it)
02439             _out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
02440 
02441         entry._state = ATTRIBUTES;
02442     }
02443 
02444     void write_post(StackEntry& entry)
02445     {
02446         if (entry._state < ATTRIBUTES)
02447             write_attributes(entry);
02448 
02449         if (entry._children || !entry._content.empty()) {
02450             if (entry._state < PRE_CLOSED)
02451                 close_pre(entry);
02452 
02453             _out << entry._content;
02454             //entry._state = CONTENT;
02455 
02456             if (_format._pretty>=PRETTY_LINEFEED && entry._content.empty())
02457                 _out << _format._endl;
02458 
02459             if (_format._pretty==PRETTY_INDENT && entry._content.empty())
02460                 for(size_t i=_stack.size(); --i>0; )
02461                     _out << XML_INDENT_SPACE;
02462 
02463             _out << "</" << EncodeXMLString(entry._node_name) << ">";
02464         } else {
02465             _out << "/>";
02466         }
02467 
02468         entry._state = POST;
02469     }
02470 };
02471 
02472 
02473 }   // namespace XMLStorage
02474 
02475 #define _XMLSTORAGE_H
02476 #endif // _XMLSTORAGE_H

IBrowser Source Code Documentation
generated on 18.09.2008 by doxygen

Homepage