00001 00002 // 00003 // XML storage C++ classes version 1.5 00004 // 00005 // Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Martin Fuchs <martin-fuchs@gmx.net> 00006 // 00007 00008 /// \file xmlstorage.h 00009 /// XMLStorage header file 00010 00011 00012 /* 00013 00014 All rights reserved. 00015 00016 Redistribution and use in source and binary forms, with or without 00017 modification, are permitted provided that the following conditions are met: 00018 00019 * Redistributions of source code must retain the above copyright 00020 notice, this list of conditions and the following disclaimer. 00021 * Redistributions in binary form must reproduce the above copyright 00022 notice, this list of conditions and the following disclaimer in 00023 the documentation and/or other materials provided with the 00024 distribution. 00025 00026 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00027 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00028 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00029 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00030 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00031 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00032 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00033 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00034 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00035 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00036 POSSIBILITY OF SUCH DAMAGE. 00037 00038 */ 00039 00040 #ifndef _XMLSTORAGE_H 00041 00042 #ifndef XS_STRICT_XML_1_0 00043 //#define XS_STRICT_XML_1_0 // suppress characters invalid for the XML 1.0 specification 00044 #endif 00045 00046 00047 #ifdef UNICODE 00048 #ifndef _UNICODE 00049 #define _UNICODE 00050 #endif 00051 #else 00052 #ifdef _UNICODE 00053 #define UNICODE 00054 #endif 00055 #endif 00056 00057 #ifndef _WIN32 00058 #ifdef UNICODE 00059 #error no UNICODE build in Unix version available 00060 #endif 00061 #ifndef XS_STRING_UTF8 00062 #define XS_STRING_UTF8 00063 #endif 00064 #endif 00065 00066 00067 #if _MSC_VER>=1400 // VS2005 or higher 00068 #ifndef _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 00069 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 00070 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 1 00071 #define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 1 00072 #endif 00073 #endif 00074 00075 00076 #ifdef XS_USE_XERCES 00077 00078 #ifndef UNICODE 00079 #ifndef XS_STRING_UTF8 00080 #define XS_STRING_UTF8 00081 #endif 00082 #endif 00083 00084 #include <xercesc/parsers/SAXParser.hpp> 00085 #include <xercesc/sax/HandlerBase.hpp> 00086 00087 using XERCES_CPP_NAMESPACE_QUALIFIER Locator; 00088 using XERCES_CPP_NAMESPACE_QUALIFIER SAXParser; 00089 using XERCES_CPP_NAMESPACE_QUALIFIER HandlerBase; 00090 using XERCES_CPP_NAMESPACE_QUALIFIER InputSource; 00091 using XERCES_CPP_NAMESPACE_QUALIFIER AttributeList; 00092 using XERCES_CPP_NAMESPACE_QUALIFIER SAXParseException; 00093 00094 typedef XMLCh XML_Char; 00095 00096 #elif defined(XS_USE_EXPAT) 00097 00098 #include <expat/expat.h> 00099 00100 #else 00101 #define XS_NATIVE 00102 #endif 00103 00104 00105 #ifdef _MSC_VER 00106 #pragma warning(disable: 4786) // identifier was truncated to 'number' characters in the debug information 00107 00108 #pragma warning(push) 00109 #pragma warning(disable: 4512) // assignment operator could not be generated 00110 00111 #ifndef XS_NO_COMMENT 00112 00113 #ifdef XS_USE_XERCES 00114 #ifdef _DEBUG 00115 #pragma comment(lib, "xerces-c_2D") 00116 #else 00117 #pragma comment(lib, "xerces-c_2") 00118 #endif 00119 #elif defined(XS_USE_EXPAT) 00120 #ifdef XML_STATIC 00121 #ifndef _DEBUG 00122 #pragma comment(lib, "libexpatMT") 00123 #endif 00124 #else 00125 #pragma comment(lib, "libexpat") 00126 #endif 00127 #endif 00128 00129 #ifndef _STRING_DEFINED // _STRING_DEFINED only allowed if using xmlstorage.cpp embedded in the project 00130 #if defined(_DEBUG) && defined(_DLL) // DEBUG version only supported with MSVCRTD 00131 #if _MSC_VER==1500 // VS2008 00132 #pragma comment(lib, "xmlstorage-vc9d") 00133 #elif _MSC_VER==1400 // VS2005 00134 #pragma comment(lib, "xmlstorage-vc8d") 00135 #else 00136 #pragma comment(lib, "xmlstorage-vc6d") 00137 #endif 00138 #else 00139 #ifdef _DLL 00140 #if _MSC_VER==1500 // VS2008 00141 #pragma comment(lib, "xmlstorage-vc9") 00142 #elif _MSC_VER==1400 // VS2005 00143 #pragma comment(lib, "xmlstorage-vc8") 00144 #else 00145 #pragma comment(lib, "xmlstorage-vc6") 00146 #endif 00147 #elif defined(_MT) 00148 #if _MSC_VER==1500 // VS2008 00149 #pragma comment(lib, "xmlstorage-vc9t") 00150 #elif _MSC_VER==1400 // VS2005 00151 #pragma comment(lib, "xmlstorage-vc8t") 00152 #else 00153 #pragma comment(lib, "xmlstorage-vc6t") 00154 #endif 00155 #else 00156 // -ML is no more supported since VS2005. 00157 #pragma comment(lib, "xmlstorage-vc6l") 00158 #endif 00159 #endif 00160 #endif // _STRING_DEFINED 00161 00162 #endif // XS_NO_COMMENT 00163 00164 #endif // _MSC_VER 00165 00166 00167 #ifdef _WIN32 00168 00169 #include <windows.h> // for LPCTSTR 00170 #include <tchar.h> 00171 #include <malloc.h> 00172 00173 #ifndef _MSC_VER 00174 #include <stdio.h> // vsnprintf(), snprintf() 00175 #endif 00176 00177 #else // _WIN32 00178 00179 #include <wchar.h> 00180 #include <stdlib.h> 00181 #include <string.h> // strcasecmp() 00182 #include <stdarg.h> 00183 00184 typedef char CHAR; 00185 #ifdef _WCHAR_T_DEFINED 00186 #define __wchar_t wchar_t 00187 #endif 00188 00189 typedef __wchar_t WCHAR; 00190 typedef unsigned char UCHAR; 00191 typedef char* LPSTR; 00192 typedef const char* LPCSTR; 00193 typedef WCHAR* LPWSTR; 00194 typedef const WCHAR* LPCWSTR; 00195 00196 #ifndef UNICODE 00197 #define TEXT(x) x 00198 typedef char TCHAR; 00199 typedef unsigned char _TUCHAR; 00200 typedef CHAR* PTSTR; 00201 typedef CHAR* LPTSTR; 00202 typedef const CHAR* LPCTSTR; 00203 00204 #define _ttoi atoi 00205 #define _tfopen fopen 00206 #define _tcstod strtod 00207 #define _tcslen strlen 00208 #define _tcsstr strstr 00209 #define _snprintf snprintf 00210 #define _sntprintf snprintf 00211 #define _vsnprintf vsnprintf 00212 #define _vsntprintf vsnprintf 00213 #define _stricmp strcasecmp 00214 #define _tcsicmp strcasecmp 00215 #define strnicmp strncasecmp 00216 #define _tcsnicmp strncasecmp 00217 #endif // UNICODE 00218 00219 #endif // _WIN32 00220 00221 #include <assert.h> 00222 00223 #ifdef __BORLANDC__ 00224 #define _stricmp stricmp 00225 #endif 00226 00227 00228 #include <fstream> 00229 #include <sstream> 00230 #include <string> 00231 #include <stack> 00232 #include <list> 00233 #include <map> 00234 00235 00236 #ifndef BUFFER_LEN 00237 #define BUFFER_LEN 2048 00238 #endif 00239 00240 #define BUFFER_HUGE 0x7F80 00241 00242 #ifndef ALLOCA_MAX 00243 #define ALLOCA_MAX 0x10000 00244 #endif 00245 00246 00247 namespace XMLStorage { 00248 00249 00250 #ifndef XS_String 00251 00252 #ifdef XS_STRING_UTF8 00253 #define XS_CHAR char 00254 #define XS_TEXT(x) x 00255 #define LPXSSTR LPSTR 00256 #define LPCXSSTR LPCSTR 00257 #define XS_cmp strcmp 00258 #define XS_icmp _stricmp 00259 #define XS_ncmp strncmp 00260 #define XS_nicmp strnicmp 00261 #define XS_toi atoi 00262 #define XS_toi64 _atoi64 00263 #define XS_tod strtod 00264 #define XS_len strlen 00265 #define XS_snprintf _snprintf 00266 #define XS_vsnprintf _vsnprintf 00267 #define XS_vsnprintf_s _vsnprintf_s 00268 #define XS_strstr strstr 00269 #else 00270 #define XS_CHAR TCHAR 00271 #define XS_TEXT(x) TEXT(x) 00272 #define LPXSSTR LPTSTR 00273 #define LPCXSSTR LPCTSTR 00274 #define XS_cmp _tcscmp 00275 #define XS_icmp _tcsicmp 00276 #define XS_ncmp _tcsncmp 00277 #define XS_nicmp _tcsnicmp 00278 #define XS_toi _ttoi 00279 #define XS_toi64 _ttoi64 00280 #define XS_tod _tcstod 00281 #define XS_len _tcslen 00282 #define XS_snprintf _sntprintf 00283 #define XS_vsnprintf _vsntprintf 00284 #define XS_vsnprintf_s _vsntprintf_s 00285 #define XS_strstr _tcsstr 00286 #endif 00287 00288 #ifndef COUNTOF 00289 #if _MSC_VER>=1400 // VS2005 or higher 00290 #define COUNTOF _countof 00291 #else 00292 #define COUNTOF(b) (sizeof(b)/sizeof(b[0])) 00293 #endif 00294 #endif 00295 00296 00297 // manage a locally allocated heap pointer 00298 struct TmpHeap 00299 { 00300 TmpHeap() 00301 { 00302 _pHeap = NULL; 00303 } 00304 00305 ~TmpHeap() 00306 { 00307 if (_pHeap) 00308 free(_pHeap); 00309 } 00310 00311 void operator=(void* p) 00312 { 00313 _pHeap = p; 00314 } 00315 00316 private: 00317 void* _pHeap; 00318 }; 00319 00320 // temporary memory allocation using alloca() or malloc() for bigger buffer sizes 00321 #define TMP_ALLOC(T, b, h, l) \ 00322 TmpHeap h; T* b; \ 00323 if (l <= ALLOCA_MAX) b = (T*)alloca(sizeof(T)*l); \ 00324 else h = b = (T*)malloc(sizeof(T)*l) 00325 00326 00327 extern const char* get_xmlsym_end_utf8(const char* p); 00328 00329 00330 #if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8) 00331 00332 #define XS_String String 00333 00334 #else // _STRING_DEFINED, !XS_STRING_UTF8 00335 00336 /// string class for TCHAR strings 00337 00338 struct XS_String 00339 #if defined(UNICODE) && !defined(XS_STRING_UTF8) 00340 : public std::wstring 00341 #else 00342 : public std::string 00343 #endif 00344 { 00345 #if defined(UNICODE) && !defined(XS_STRING_UTF8) 00346 typedef std::wstring super; 00347 #else 00348 typedef std::string super; 00349 #endif 00350 00351 XS_String() {} 00352 00353 XS_String(LPCXSSTR s) {if (s) super::assign(s);} 00354 XS_String(LPCXSSTR s, size_t l) : super(s, l) {} 00355 00356 XS_String(const super& other) : super(other) {} 00357 XS_String(const XS_String& other) : super(other) {} 00358 00359 #ifdef _WIN32 00360 #if defined(UNICODE) && !defined(XS_STRING_UTF8) 00361 XS_String(LPCSTR s) {assign(s);} 00362 XS_String(LPCSTR s, size_t l) {assign(s, l);} 00363 XS_String(const std::string& s) {assign(s.c_str());} 00364 XS_String& operator=(LPCSTR s) {assign(s); return *this;} 00365 void assign(LPCSTR s) {if (s) {size_t bl=strlen(s); TMP_ALLOC(WCHAR, b, h, bl); super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, (int)bl, b, (int)bl));} else erase();} 00366 void assign(LPCSTR s, size_t l) {if (s) {size_t bl=l; TMP_ALLOC(WCHAR, b, h, bl); super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, (int)l, b, (int)bl));} else erase();} 00367 #else 00368 XS_String(LPCWSTR s) {assign(s);} 00369 XS_String(LPCWSTR s, size_t l) {assign(s, l);} 00370 XS_String(const std::wstring& ws) {assign(ws.c_str());} 00371 XS_String& operator=(LPCWSTR s) {assign(s); return *this;} 00372 #ifdef XS_STRING_UTF8 00373 void assign(LPCWSTR s) {if (s) {size_t bl=4*wcslen(s); TMP_ALLOC(char, b, h, bl); super::assign(b, WideCharToMultiByte(CP_UTF8, 0, s, (int)bl, b, (int)bl, 0, 0));} else erase();} 00374 void assign(LPCWSTR s, size_t l) {if (s) {size_t bl=4*l; TMP_ALLOC(char, b, h, bl); super::assign(b, WideCharToMultiByte(CP_UTF8, 0, s, (int)l, b, (int)bl, 0, 0));} else erase();} 00375 #else // if !UNICODE && !XS_STRING_UTF8 00376 void assign(LPCWSTR s) {if (s) {size_t bl=wcslen(s); TMP_ALLOC(char, b, h, bl); super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, (int)bl, b, (int)bl, 0, 0));} else erase();} 00377 void assign(LPCWSTR s, size_t l) {if (s) {size_t bl=l; TMP_ALLOC(char, b, h, bl); super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, (int)l, b, (int)bl, 0, 0));} else erase();} 00378 #endif 00379 #endif 00380 #endif // _WIN32 00381 00382 #ifdef __ISSD_H 00383 // XS_String(const _ISSD RString& s) {assign(s.c_str());} 00384 // void assign(const _ISSD RString& s) {assign(s.c_str());} 00385 XS_String& operator=(const _ISSD RString& s) {assign(s); return *this;} 00386 #endif 00387 00388 #ifdef XS_STRING_UTF8 00389 void assign(const XS_String& s) {assign(s.c_str());} 00390 #endif 00391 00392 XS_String& operator=(LPCXSSTR s) {if (s) super::assign(s); else erase(); return *this;} 00393 XS_String& operator=(const super& s) {super::assign(s); return *this;} 00394 void assign(LPCXSSTR s) {super::assign(s);} 00395 void assign(LPCXSSTR s, size_t l) {super::assign(s, l);} 00396 00397 operator LPCXSSTR() const {return c_str();} 00398 00399 #ifdef _WIN32 00400 #ifdef XS_STRING_UTF8 00401 operator std::wstring() const {size_t bl=length(); TMP_ALLOC(WCHAR, b, h, bl); return std::wstring(b, MultiByteToWideChar(CP_UTF8, 0, c_str(), bl, b, bl));} 00402 #elif defined(UNICODE) 00403 operator std::string() const {size_t bl=length(); TMP_ALLOC(char, b, h, bl); return std::string(b, WideCharToMultiByte(CP_ACP, 0, c_str(), (int)bl, b, (int)bl, 0, 0));} 00404 #else 00405 operator std::wstring() const {size_t bl=length(); TMP_ALLOC(WCHAR, b, h, bl); return std::wstring(b, MultiByteToWideChar(CP_ACP, 0, c_str(), (int)bl, b, (int)bl));} 00406 #endif 00407 #endif 00408 00409 XS_String& printf(LPCXSSTR fmt, ...) 00410 { 00411 va_list vl; 00412 00413 va_start(vl, fmt); 00414 vprintf(fmt, vl); 00415 va_end(vl); 00416 00417 return *this; 00418 } 00419 00420 XS_String& vprintf(LPCXSSTR fmt, va_list vl) 00421 { 00422 XS_CHAR b[BUFFER_LEN]; 00423 00424 int l = XS_vsnprintf(b, COUNTOF(b), fmt, vl); 00425 00426 if (l >= 0) 00427 super::assign(b, l); 00428 else { 00429 LPTSTR p = (LPTSTR)malloc(sizeof(TCHAR)*BUFFER_HUGE); 00430 00431 #ifdef __STDC_WANT_SECURE_LIB__ 00432 l = XS_vsnprintf_s(p, BUFFER_HUGE, _TRUNCATE, fmt, vl); 00433 #else 00434 l = XS_vsnprintf(p, BUFFER_HUGE, fmt, vl); 00435 #endif 00436 if (l >= 0) 00437 super::assign(p, l); 00438 else 00439 super::assign(fmt); // snprintf failed 00440 00441 free(p); 00442 } 00443 00444 return *this; 00445 } 00446 00447 XS_String& appendf(LPCXSSTR fmt, ...) 00448 { 00449 va_list vl; 00450 00451 va_start(vl, fmt); 00452 vappendf(fmt, vl); 00453 va_end(vl); 00454 00455 return *this; 00456 } 00457 00458 XS_String& vappendf(LPCXSSTR fmt, va_list vl) 00459 { 00460 XS_CHAR b[BUFFER_LEN]; 00461 00462 int l = XS_vsnprintf(b, COUNTOF(b), fmt, vl); 00463 00464 if (l >= 0) 00465 super::append(b, l); 00466 else { 00467 LPTSTR p = (LPTSTR)malloc(sizeof(TCHAR)*BUFFER_HUGE); 00468 00469 #ifdef __STDC_WANT_SECURE_LIB__ 00470 l = XS_vsnprintf_s(p, BUFFER_HUGE, _TRUNCATE, fmt, vl); 00471 #else 00472 l = XS_vsnprintf(p, BUFFER_HUGE, fmt, vl); 00473 #endif 00474 if (l >= 0) 00475 super::append(p, l); 00476 else 00477 super::append(fmt); // snprintf failed 00478 00479 free(p); 00480 } 00481 00482 return *this; 00483 } 00484 }; 00485 00486 #endif // _STRING_DEFINED, !XS_STRING_UTF8 00487 00488 #endif // XS_String 00489 00490 00491 #define XS_EMPTY_STR XS_TEXT("") 00492 #define XS_TRUE_STR XS_TEXT("true") 00493 #define XS_FALSE_STR XS_TEXT("false") 00494 #define XS_INTFMT_STR XS_TEXT("%d") 00495 #define XS_INT64FMT_STR XS_TEXT("%I64d") 00496 #define XS_FLOATFMT_STR XS_TEXT("%f") 00497 00498 #define XS_KEY_STR XS_TEXT("key") 00499 #define XS_VALUE_STR XS_TEXT("value") 00500 #define XS_PROPERTY_STR XS_TEXT("property") 00501 00502 // work around GCC's wide string constant bug 00503 #ifdef __GNUC__ 00504 extern const LPCXSSTR XS_EMPTY; 00505 extern const LPCXSSTR XS_TRUE; 00506 extern const LPCXSSTR XS_FALSE; 00507 extern const LPCXSSTR XS_INTFMT; 00508 extern const LPCXSSTR XS_INT64FMT; 00509 extern const LPCXSSTR XS_FLOATFMT; 00510 #else 00511 #define XS_EMPTY XS_EMPTY_STR 00512 #define XS_TRUE XS_TRUE_STR 00513 #define XS_FALSE XS_FALSE_STR 00514 #define XS_INTFMT XS_INTFMT_STR 00515 #define XS_INT64FMT XS_INT64FMT_STR 00516 #define XS_FLOATFMT XS_FLOATFMT_STR 00517 #endif 00518 00519 extern const XS_String XS_KEY; 00520 extern const XS_String XS_VALUE; 00521 extern const XS_String XS_PROPERTY; 00522 00523 #define CDATA_START "<![CDATA[" 00524 #define CDATA_END "]]>" 00525 00526 00527 inline LPCXSSTR safe_skip_space(LPCXSSTR s) 00528 { 00529 if (s) { 00530 // strip leading white space 00531 while(_istspace(*s)) 00532 ++s; 00533 00534 return s; 00535 } else 00536 return XS_EMPTY_STR; 00537 } 00538 00539 00540 #ifdef XS_STRING_UTF8 00541 00542 template<typename T> inline XS_String from_utf8(const T& s) 00543 { 00544 return s; 00545 } 00546 00547 inline XS_String from_utf8(const char* s, size_t l) 00548 { 00549 return XS_String(s, l); 00550 } 00551 00552 #else 00553 00554 // from UTF-8 to XS internal string encoding 00555 inline void assign_utf8(XS_String& s, const char* str, size_t lutf8) 00556 { 00557 // Benutzung von malloc() für Strings größer als BUFFER_LEN 00558 #ifdef UNICODE 00559 TMP_ALLOC(TCHAR, buffer, h, lutf8); 00560 int l = MultiByteToWideChar(CP_UTF8, 0, str, (int)lutf8, buffer, (int)lutf8); 00561 #else 00562 TMP_ALLOC(WCHAR, wbuffer, hw, lutf8); 00563 int l = MultiByteToWideChar(CP_UTF8, 0, str, (int)lutf8, wbuffer, (int)lutf8); 00564 00565 int bl = 2*l; 00566 TMP_ALLOC(char, buffer, h, bl); 00567 l = WideCharToMultiByte(CP_ACP, 0, wbuffer, l, buffer, bl, 0, 0); 00568 #endif 00569 00570 s.assign(buffer, l); 00571 } 00572 00573 // from UTF-8 to XS internal string encoding 00574 inline void assign_utf8(XS_String& s, const char* str) 00575 { 00576 assign_utf8(s, str, strlen(str)); 00577 } 00578 00579 // from XS internal string encoding to UTF-8 00580 inline std::string get_utf8(LPCTSTR s, size_t l) 00581 { 00582 #ifdef UNICODE 00583 size_t bl = 4*l; 00584 TMP_ALLOC(char, buffer, h, bl); 00585 l = WideCharToMultiByte(CP_UTF8, 0, s, (int)l, buffer, (int)bl, 0, 0); 00586 #else 00587 TMP_ALLOC(WCHAR, wbuffer, hw, l); 00588 l = MultiByteToWideChar(CP_ACP, 0, s, (int)l, wbuffer, (int)l); 00589 00590 size_t bl = 4*l; 00591 TMP_ALLOC(char, buffer, h, bl); 00592 l = WideCharToMultiByte(CP_UTF8, 0, wbuffer, (int)l, buffer, (int)bl, 0, 0); 00593 #endif 00594 00595 return std::string(buffer, l); 00596 } 00597 00598 #ifdef UNICODE 00599 // from XS internal string encoding to UTF-8 00600 inline std::string get_utf8(const char* s, size_t l) 00601 { 00602 TMP_ALLOC(WCHAR, wbuffer, wh, l); 00603 l = MultiByteToWideChar(CP_ACP, 0, s, (int)l, wbuffer, (int)l); 00604 00605 size_t bl = 4*l; 00606 TMP_ALLOC(char, buffer, h, bl); 00607 l = WideCharToMultiByte(CP_UTF8, 0, wbuffer, (int)l, buffer, (int)bl, 0, 0); 00608 00609 return std::string(buffer, l); 00610 } 00611 #endif 00612 00613 // from XS internal string encoding to UTF-8 00614 inline std::string get_utf8(const XS_String& s) 00615 { 00616 return get_utf8(s.c_str(), s.length()); 00617 } 00618 00619 inline XS_String from_utf8(const char* s) 00620 { 00621 XS_String ret; 00622 assign_utf8(ret, s, strlen(s)); 00623 return ret; 00624 } 00625 00626 inline XS_String from_utf8(const std::string& s) 00627 { 00628 XS_String ret; 00629 assign_utf8(ret, s.c_str(), s.length()); 00630 return ret; 00631 } 00632 00633 inline XS_String from_utf8(const char* s, size_t l) 00634 { 00635 XS_String ret; 00636 assign_utf8(ret, s, l); 00637 return ret; 00638 } 00639 00640 #endif // XS_STRING_UTF8 00641 00642 extern std::string EncodeXMLString(const XS_String& str, bool cdata=false); 00643 extern XS_String DecodeXMLString(const std::string& str_utf8); 00644 00645 00646 #ifdef __GNUC__ 00647 #include <ext/stdio_filebuf.h> 00648 #define FILE_FILEBUF __gnu_cxx::stdio_filebuf<char> 00649 #elif defined(_MSC_VER) 00650 #define FILE_FILEBUF std::filebuf 00651 #endif 00652 00653 #ifdef FILE_FILEBUF 00654 00655 /// base class for XMLStorage::tifstream and XMLStorage::tofstream 00656 struct FileHolder 00657 { 00658 FileHolder(LPCTSTR path, LPCTSTR mode) 00659 : _own_file(true) 00660 { 00661 #ifdef __STDC_WANT_SECURE_LIB__ // secure CRT functions using VS 2005 00662 if (_tfopen_s(&_pfile, path, mode) != 0) 00663 _pfile = NULL; 00664 #else 00665 _pfile = _tfopen(path, mode); 00666 #endif 00667 } 00668 00669 FileHolder(FILE* pfile) 00670 : _pfile(pfile), 00671 _own_file(false) 00672 { 00673 } 00674 00675 ~FileHolder() 00676 { 00677 if (_own_file && _pfile) 00678 fclose(_pfile); 00679 } 00680 00681 operator FILE*() {return _pfile;} 00682 00683 protected: 00684 FILE* _pfile; 00685 bool _own_file; 00686 }; 00687 00688 /// input file stream with ANSI/UNICODE file names 00689 struct tifstream : public std::istream, FileHolder 00690 { 00691 typedef std::istream super; 00692 00693 tifstream(LPCTSTR path) 00694 : super(&_buf), 00695 FileHolder(path, TEXT("rb")), // binary mode is important for XMLReader::read_buffer() with MinGW libraries 00696 #ifdef __GNUC__ 00697 _buf(_pfile, std::ios::in) 00698 #else 00699 _buf(_pfile) 00700 #endif 00701 { 00702 if (!_pfile) 00703 setstate(badbit); 00704 } 00705 00706 protected: 00707 FILE_FILEBUF _buf; 00708 }; 00709 00710 /// output file stream with ANSI/UNICODE file names 00711 struct tofstream : public std::ostream, FileHolder 00712 { 00713 typedef std::ostream super; 00714 00715 tofstream(LPCTSTR path, LPCTSTR mode=TEXT("wb")) 00716 : super(&_buf), 00717 FileHolder(path, mode), 00718 #ifdef __GNUC__ 00719 _buf(_pfile, std::ios::out) 00720 #else 00721 _buf(_pfile) 00722 #endif 00723 { 00724 if (!_pfile) 00725 setstate(badbit); 00726 } 00727 00728 tofstream(FILE* pFile) 00729 : super(&_buf), 00730 FileHolder(pFile), 00731 #ifdef __GNUC__ 00732 _buf(_pfile, std::ios::out) 00733 #else 00734 _buf(_pfile) 00735 #endif 00736 { 00737 if (!_pfile) 00738 setstate(badbit); 00739 } 00740 00741 ~tofstream() 00742 { 00743 flush(); 00744 } 00745 00746 protected: 00747 FILE_FILEBUF _buf; 00748 }; 00749 00750 #else // FILE_FILEBUF 00751 00752 #ifdef UNICODE 00753 #error UNICODE not supported for this platform 00754 #endif 00755 00756 struct tifstream : public std::ifstream 00757 { 00758 typedef std::ifstream super; 00759 00760 tifstream(const char* path) 00761 : super(path, std::ios::in|std::ios::binary) 00762 { 00763 } 00764 }; 00765 00766 struct tofstream : public std::ofstream 00767 { 00768 typedef std::ofstream super; 00769 00770 tofstream(const char* path) 00771 : super(path, std::ios::out|std::ios::binary) 00772 { 00773 } 00774 }; 00775 00776 #endif 00777 00778 00779 // write XML files with 2 spaces indenting 00780 #define XML_INDENT_SPACE " " 00781 00782 00783 #if defined(XS_USE_XERCES) || defined(XS_USE_EXPAT) 00784 00785 #if defined(XML_UNICODE)/*Expat*/ || defined(XS_USE_XERCES)/*Xerces*/ // Are Expat/Xerces XML strings UTF-16 encoded? 00786 typedef XS_String String_from_XML_Char; 00787 00788 #elif defined(XS_STRING_UTF8) 00789 typedef XS_String String_from_XML_Char; 00790 00791 #else 00792 00793 /// converter from Expat/Xerces strings to XMLStorage internal strings 00794 struct String_from_XML_Char : public XS_String 00795 { 00796 String_from_XML_Char(const XML_Char* str) 00797 { 00798 assign_utf8(*this, str); 00799 } 00800 }; 00801 00802 #endif 00803 00804 #endif // defined(XS_USE_XERCES) || defined(XS_USE_EXPAT) 00805 00806 00807 #if defined(UNICODE) && !defined(XS_STRING_UTF8) 00808 00809 // optimization for faster UNICODE/ASCII string comparison without temporary A/U conversion 00810 inline bool operator==(const XS_String& s1, const char* s2) 00811 { 00812 LPCWSTR p = s1; 00813 const unsigned char* q = (const unsigned char*)s2; 00814 00815 while(*p && *q) 00816 if (*p++ != *q++) 00817 return false; 00818 00819 return *p == *q; 00820 }; 00821 00822 #endif 00823 00824 00825 #if defined(XS_NATIVE) || defined(XMLNODE_LOCATION) 00826 /// location of XML Node including XML file name 00827 struct XMLLocation 00828 { 00829 XMLLocation() 00830 : _pdisplay_path(NULL), 00831 _line(0), 00832 _column(0) 00833 { 00834 } 00835 00836 XMLLocation(const char* display_path, int line, int column) 00837 : _pdisplay_path(display_path), 00838 _line(line), 00839 _column(column) 00840 { 00841 } 00842 00843 std::string str() const; 00844 00845 const char* get_path() const {return _pdisplay_path? _pdisplay_path: "";} 00846 int get_line() const {return _line;} 00847 int get_column() const {return _column;} 00848 00849 void set_path(const char* path) 00850 { 00851 _pdisplay_path = path; 00852 _line = 1; 00853 _column = 1; 00854 } 00855 00856 protected: 00857 const char* _pdisplay_path; // character pointer for fast reference 00858 int _line; 00859 int _column; 00860 00861 friend struct XMLReader; 00862 }; 00863 #endif 00864 00865 00866 /// XML Error with message and location 00867 struct XMLError 00868 { 00869 XMLError() 00870 : _line(0), 00871 _column(0), 00872 _error_code(0) 00873 { 00874 } 00875 00876 XMLError(const char* msg) 00877 : _line(0), 00878 _column(0), 00879 _error_code(0), 00880 _message(msg) 00881 { 00882 } 00883 00884 XMLError(const XMLLocation& location, const char* msg) 00885 : _systemId(location.get_path()), 00886 _line(location.get_line()), 00887 _column(location.get_column()), 00888 _error_code(0), 00889 _message(msg) 00890 { 00891 } 00892 00893 std::string str() const; 00894 00895 friend std::ostream& operator<<(std::ostream&, const XMLError& err); 00896 00897 std::string _message; 00898 std::string _systemId; 00899 int _line; 00900 int _column; 00901 int _error_code; 00902 }; 00903 00904 /// list of XMLError entries 00905 struct XMLErrorList : public std::list<XMLError> 00906 { 00907 XS_String str(const char* del="\n") const; 00908 }; 00909 00910 00911 enum PRETTY_FLAGS { 00912 PRETTY_PLAIN = 0, 00913 PRETTY_LINEFEED = 1, 00914 PRETTY_INDENT = 2 00915 }; 00916 00917 00918 /// XML Stylesheet entry 00919 struct StyleSheet 00920 { 00921 std::string _href; // CDATA #REQUIRED 00922 std::string _type; // CDATA #REQUIRED 00923 std::string _title; // CDATA #IMPLIED 00924 std::string _media; // CDATA #IMPLIED 00925 std::string _charset; // CDATA #IMPLIED 00926 bool _alternate; // (yes|no) "no" 00927 00928 StyleSheet() : _alternate(false) {} 00929 00930 StyleSheet(const std::string& href, const std::string& type="text/xsl", bool alternate=false) 00931 : _href(href), 00932 _type(type), 00933 _alternate(alternate) 00934 { 00935 } 00936 00937 bool empty() const {return _href.empty();} 00938 void print(std::ostream& out) const; 00939 }; 00940 00941 /// list of StyleSheet entries 00942 struct StyleSheetList : public std::list<StyleSheet> 00943 { 00944 void set(const StyleSheet& stylesheet) 00945 { 00946 clear(); 00947 push_back(stylesheet); 00948 } 00949 }; 00950 00951 00952 /// XML document type description 00953 struct DocType 00954 { 00955 std::string _name; 00956 00957 // External Document Types are noted, but not parsed. 00958 std::string _public; 00959 std::string _system; 00960 00961 // Internal DTDs are not supported. 00962 00963 void parse(const char* str); 00964 bool empty() const {return _name.empty();} 00965 }; 00966 00967 /// Management of XML file headers and formating 00968 struct XMLFormat 00969 { 00970 XMLFormat(PRETTY_FLAGS pretty=PRETTY_INDENT, const std::string& encoding="utf-8", const DocType& doctype=DocType() 00971 #ifndef XS_STRICT_XML_1_0 00972 , const std::string& xml_version="1.0" 00973 #endif 00974 ) 00975 : _pretty(pretty), 00976 _endl("\n"), 00977 _encoding(encoding), 00978 _utf8_bom(false), 00979 _inhibit_header(false), 00980 _doctype(doctype), 00981 _standalone(-1) 00982 { 00983 #ifdef XS_STRICT_XML_1_0 00984 _version = "1.0"; 00985 #else 00986 _version = xml_version; 00987 #endif 00988 } 00989 00990 XMLFormat(PRETTY_FLAGS pretty, bool utf8_bom, const DocType& doctype=DocType()) 00991 : _pretty(pretty), 00992 _endl("\n"), 00993 _version("1.0"), 00994 _encoding("utf-8"), 00995 _utf8_bom(utf8_bom), 00996 _inhibit_header(false), 00997 _doctype(doctype), 00998 _standalone(-1) 00999 { 01000 } 01001 01002 void print_header(std::ostream& out, bool lf=true) const; 01003 01004 PRETTY_FLAGS _pretty; 01005 const char* _endl; // line ending string: "\n" or "\r\n" 01006 01007 std::string _version; 01008 std::string _encoding; 01009 bool _utf8_bom; 01010 bool _inhibit_header; 01011 01012 DocType _doctype; 01013 01014 StyleSheetList _stylesheets; 01015 01016 // std::string _additional; 01017 01018 int _standalone; 01019 }; 01020 01021 struct HeaderlessXMLFormat : public XMLFormat 01022 { 01023 HeaderlessXMLFormat(PRETTY_FLAGS pretty=PRETTY_INDENT) 01024 : XMLFormat(pretty) 01025 { 01026 _inhibit_header = true; 01027 } 01028 }; 01029 01030 01031 enum WRITE_MODE { 01032 FORMAT_PLAIN, /// write XML without any white space 01033 FORMAT_SMART, /// preserve original white space and comments if present; pretty print otherwise 01034 FORMAT_ORIGINAL, /// write XML stream preserving original white space and comments 01035 FORMAT_PRETTY /// pretty print node to stream without preserving original white space 01036 }; 01037 01038 01039 #if 1 01040 01041 // XS_StringMap node 01042 struct XS_SMNode 01043 { 01044 XS_SMNode(const XS_String& key) 01045 : first(key) 01046 { 01047 } 01048 01049 XS_SMNode(const XS_SMNode& other) 01050 : first(other.first), 01051 second(other.second) 01052 { 01053 if (other._pNext) 01054 _pNext = new XS_SMNode(*other._pNext); 01055 else 01056 _pNext = NULL; 01057 } 01058 01059 XS_String first; 01060 XS_String second; 01061 01062 XS_SMNode* _pNext; 01063 01064 private: 01065 // disallow overwritung 01066 void operator=(const XS_SMNode&) 01067 { 01068 } 01069 }; 01070 01071 // optimized string map for small numbers of values implemented as sorted linked list 01072 struct XS_StringMap 01073 { 01074 typedef XS_String key_type; 01075 typedef XS_String value_type; 01076 01077 struct iterator 01078 { 01079 iterator(XS_SMNode* ptr) 01080 : _ptr(ptr) 01081 { 01082 } 01083 01084 operator bool() const 01085 { 01086 return _ptr != NULL; 01087 } 01088 01089 XS_SMNode* operator->() 01090 { 01091 return _ptr; 01092 } 01093 01094 const XS_SMNode* operator->() const 01095 { 01096 return _ptr; 01097 } 01098 01099 void operator++() 01100 { 01101 _ptr = _ptr->_pNext; 01102 } 01103 01104 XS_SMNode* ptr() 01105 { 01106 return _ptr; 01107 } 01108 01109 const XS_SMNode* ptr() const 01110 { 01111 return _ptr; 01112 } 01113 01114 private: 01115 XS_SMNode* _ptr; 01116 }; 01117 01118 struct const_iterator 01119 { 01120 const_iterator(const XS_SMNode* ptr) 01121 : _ptr(ptr) 01122 { 01123 } 01124 01125 const_iterator(const iterator& it) 01126 : _ptr(it.ptr()) 01127 { 01128 } 01129 01130 operator bool() const 01131 { 01132 return _ptr != NULL; 01133 } 01134 01135 const XS_SMNode* operator->() const 01136 { 01137 return _ptr; 01138 } 01139 01140 void operator++() 01141 { 01142 _ptr = _ptr->_pNext; 01143 } 01144 01145 const XS_SMNode* ptr() const 01146 { 01147 return _ptr; 01148 } 01149 01150 private: 01151 const XS_SMNode* _ptr; 01152 }; 01153 01154 XS_StringMap() 01155 : _firstNode(NULL) 01156 { 01157 } 01158 01159 XS_StringMap(const XS_StringMap& other) 01160 : _firstNode(NULL) 01161 { 01162 assign(other); 01163 } 01164 01165 void operator=(const XS_StringMap& other) 01166 { 01167 clear(); 01168 assign(other); 01169 } 01170 01171 ~XS_StringMap() 01172 { 01173 clear(); 01174 } 01175 01176 void clear() 01177 { 01178 XS_SMNode* node = _firstNode; 01179 _firstNode = NULL; 01180 01181 while(node) { 01182 XS_SMNode* pNext = node->_pNext; 01183 delete node; 01184 node = pNext; 01185 } 01186 } 01187 01188 iterator begin() 01189 { 01190 return _firstNode; 01191 } 01192 01193 const_iterator begin() const 01194 { 01195 return _firstNode; 01196 } 01197 01198 iterator end() 01199 { 01200 return NULL; 01201 } 01202 01203 const_iterator end() const 01204 { 01205 return NULL; 01206 } 01207 01208 iterator find(const key_type& key) 01209 { 01210 for(iterator node=_firstNode; node; node=node->_pNext) { 01211 int c = node->first.compare(key); 01212 01213 if (c == 0) 01214 return node; 01215 else if (c > 0) 01216 break; 01217 } 01218 01219 return NULL; 01220 } 01221 01222 const_iterator find(const key_type& key) const 01223 { 01224 for(const_iterator node=_firstNode; node; node=node->_pNext) { 01225 int c = node->first.compare(key); 01226 01227 if (c == 0) 01228 return node; 01229 else if (c > 0) 01230 break; 01231 } 01232 01233 return NULL; 01234 } 01235 01236 value_type& operator[](const key_type& key) 01237 { 01238 iterator last = NULL; 01239 iterator node = _firstNode; 01240 01241 for(; node; node=(last=node)->_pNext) { 01242 int c = node->first.compare(key); 01243 01244 if (c == 0) 01245 break; // key matched 01246 else if (c > 0) { 01247 node = NULL; 01248 break; 01249 } 01250 } 01251 01252 if (!node) { 01253 // insert a new node into the linked list 01254 node = new XS_SMNode(key); 01255 01256 if (last) { 01257 node->_pNext = last->_pNext; 01258 last->_pNext = node.ptr(); 01259 } else { 01260 node->_pNext = _firstNode; 01261 _firstNode = node.ptr(); 01262 } 01263 } 01264 01265 return node->second; 01266 } 01267 01268 bool erase(const key_type& key) 01269 { 01270 iterator last = NULL; 01271 iterator node = _firstNode; 01272 01273 for(; node; node=(last=node)->_pNext) { 01274 int c = node->first.compare(key); 01275 01276 if (c == 0) { 01277 // remove the node from linked list 01278 if (last) 01279 last->_pNext = node->_pNext; 01280 else 01281 _firstNode = NULL; 01282 01283 delete node.ptr(); 01284 01285 return true; 01286 } else if (c > 0) 01287 break; 01288 } 01289 01290 return false; // key not found 01291 } 01292 01293 bool operator==(const XS_StringMap& other) const 01294 { 01295 const_iterator it1 = _firstNode; 01296 const_iterator it2 = other._firstNode; 01297 01298 while(it1 || it2) { 01299 if (!it1 || !it2) 01300 return false; 01301 01302 if (it1->first != it2->first) 01303 return false; 01304 01305 if (it1->second != it2->second) 01306 return false; 01307 } 01308 01309 return !it1 && !it2; 01310 } 01311 01312 bool operator!=(const XS_StringMap& other) const 01313 { 01314 return !operator==(other); 01315 } 01316 01317 private: 01318 XS_SMNode* _firstNode; 01319 01320 void assign(const XS_StringMap& other) 01321 { 01322 if (other._firstNode) 01323 _firstNode = new XS_SMNode(*other._firstNode); 01324 } 01325 }; 01326 01327 #else 01328 01329 typedef std::map<XS_String, XS_String> XS_StringMap; 01330 01331 #endif 01332 01333 01334 struct XMLNode; 01335 01336 struct XPathElement 01337 { 01338 XPathElement() : _child_idx(-1) {} 01339 01340 XPathElement(const XS_String& child_name, int child_idx=-1) 01341 : _child_name(child_name), _child_idx(child_idx) 01342 { 01343 } 01344 01345 XPathElement(const XS_String& child_name, int child_idx, const XS_String& attr_name, const XS_String& attr_value) 01346 : _child_name(child_name), _child_idx(child_idx) 01347 { 01348 _mAttrAndAttr[attr_name] = attr_value; 01349 } 01350 01351 XS_String _child_name; 01352 int _child_idx; 01353 01354 typedef XS_StringMap MAPATTR; // maps attribute names to its value 01355 MAPATTR _mAttrAndAttr; // map to handle AND conditions 01356 01357 LPCXSSTR parse(LPCXSSTR path); 01358 01359 XMLNode* find(XMLNode* node) const; 01360 const XMLNode* const_find(const XMLNode* node) const; 01361 01362 bool matches(const XMLNode& node, int& n) const; 01363 }; 01364 01365 struct XPath : std::list<XPathElement> 01366 { 01367 XPath() : _absolute(false) {} 01368 XPath(LPCXSSTR path) {init(path);} 01369 XPath(const XS_String& path) {init(path.c_str());} 01370 01371 void init(LPCXSSTR path); 01372 01373 bool _absolute; 01374 }; 01375 01376 01377 /// in memory representation of an XML node 01378 struct XMLNode : public XS_String 01379 { 01380 #if defined(UNICODE) && !defined(XS_STRING_UTF8) 01381 /// map of XML node attributes 01382 // optimized read access without temporary A/U conversion when using ASCII attribute names 01383 struct AttributeMap : public XS_StringMap 01384 { 01385 typedef XS_StringMap super; 01386 01387 const_iterator find(const char* x) const 01388 { 01389 for(const_iterator it=begin(); it!=end(); ++it) 01390 if (it->first == x) 01391 return it; 01392 01393 return end(); 01394 } 01395 01396 const_iterator find(const key_type& x) const 01397 { 01398 return super::find(x); 01399 } 01400 01401 iterator find(const key_type& x) 01402 { 01403 return super::find(x); 01404 } 01405 01406 XS_String get(const char* x, LPCXSSTR def=XS_EMPTY_STR) const 01407 { 01408 const_iterator found = find(x); 01409 01410 if (found != end()) 01411 return found->second; 01412 else 01413 return def; 01414 } 01415 }; 01416 #else 01417 /// map of XML node attributes 01418 struct AttributeMap : public XS_StringMap 01419 { 01420 XS_String get(const char* x, LPCXSSTR def=XS_EMPTY_STR) const 01421 { 01422 const_iterator found = find(x); 01423 01424 if (found != end()) 01425 return found->second; 01426 else 01427 return def; 01428 } 01429 }; 01430 #endif 01431 01432 /// internal children node list 01433 struct Children : public std::list<XMLNode*> 01434 { 01435 typedef std::list<XMLNode*> super; 01436 01437 Children() 01438 { 01439 } 01440 01441 Children(Children& other) 01442 { 01443 for(Children::const_iterator it=other.begin(); it!=other.end(); ++it) 01444 push_back(*it); 01445 } 01446 01447 void assign(Children& other) 01448 { 01449 clear(); 01450 move(other); 01451 } 01452 01453 void move(Children& other) 01454 { 01455 for(Children::const_iterator it=other.begin(); it!=other.end(); ++it) 01456 push_back(*it); 01457 01458 other.reset(); 01459 } 01460 01461 Children& operator=(Children& other) 01462 { 01463 assign(other); 01464 return *this; 01465 } 01466 01467 void copy(const Children& other) 01468 { 01469 for(Children::const_iterator it=other.begin(); it!=other.end(); ++it) 01470 push_back(new XMLNode(**it)); 01471 } 01472 01473 void clear() 01474 { 01475 while(!empty()) { 01476 XMLNode* node = back(); 01477 pop_back(); 01478 01479 node->clear(); 01480 delete node; 01481 } 01482 } 01483 01484 bool remove(XMLNode* node) 01485 { 01486 for(iterator it=begin(); it!=end(); ++it) 01487 if (*it == node) { 01488 erase(it); 01489 return true; 01490 } 01491 01492 return false; 01493 } 01494 01495 private: 01496 void reset() 01497 { 01498 super::clear(); 01499 } 01500 }; 01501 01502 // access to protected class members for XMLPos and XMLReader 01503 friend struct XMLPos; 01504 friend struct const_XMLPos; 01505 friend struct XMLReaderBase; 01506 friend struct XPathElement; 01507 01508 XMLNode(const XS_String& name) 01509 : XS_String(name), 01510 _cdata_content(false) 01511 { 01512 } 01513 01514 XMLNode(const XS_String& name, const std::string& leading) 01515 : XS_String(name), 01516 _leading(leading), 01517 _cdata_content(false) 01518 { 01519 } 01520 01521 XMLNode(const XMLNode& other) 01522 : XS_String(other), 01523 _attributes(other._attributes), 01524 _leading(other._leading), 01525 _content(other._content), 01526 _end_leading(other._end_leading), 01527 _trailing(other._trailing), 01528 #ifdef XMLNODE_LOCATION 01529 _location(other._location), 01530 #endif 01531 _cdata_content(false) 01532 { 01533 for(Children::const_iterator it=other._children.begin(); it!=other._children.end(); ++it) 01534 _children.push_back(new XMLNode(**it)); 01535 } 01536 01537 enum COPY_FLAGS {COPY_NOCHILDREN}; 01538 01539 #ifdef _MSC_VER 01540 #pragma warning(disable: 4100) // unreferenced formal parameter 01541 #endif 01542 XMLNode(const XMLNode& other, COPY_FLAGS copy_no_children) 01543 : XS_String(other), 01544 _attributes(other._attributes), 01545 _leading(other._leading), 01546 _content(other._content), 01547 _end_leading(other._end_leading), 01548 _trailing(other._trailing), 01549 #ifdef XMLNODE_LOCATION 01550 _location(other._location), 01551 #endif 01552 _cdata_content(false) 01553 { 01554 assert(copy_no_children==COPY_NOCHILDREN); 01555 } 01556 01557 virtual ~XMLNode() 01558 { 01559 while(!_children.empty()) { 01560 delete _children.back(); 01561 _children.pop_back(); 01562 } 01563 } 01564 01565 void clear() 01566 { 01567 _leading.erase(); 01568 _content.erase(); 01569 _end_leading.erase(); 01570 _trailing.erase(); 01571 01572 _attributes.clear(); 01573 _children.clear(); 01574 01575 XS_String::erase(); 01576 } 01577 01578 XMLNode& operator=(const XMLNode& other) 01579 { 01580 _children.clear(); 01581 _children.copy(other._children); 01582 01583 _attributes = other._attributes; 01584 01585 _leading = other._leading; 01586 _content = other._content; 01587 _end_leading = other._end_leading; 01588 _trailing = other._trailing; 01589 01590 return *this; 01591 } 01592 01593 /// add a new child node 01594 void add_child(XMLNode* child) 01595 { 01596 _children.push_back(child); 01597 } 01598 01599 /// remove all children named 'name' 01600 void remove_children(const XS_String& name) 01601 { 01602 Children::iterator it, next=_children.begin(); 01603 01604 while((it=next) != _children.end()) { 01605 ++next; 01606 01607 if (**it == name) 01608 _children.erase(it); 01609 } 01610 } 01611 01612 /// write access to an attribute 01613 void put(const XS_String& attr_name, const XS_String& value) 01614 { 01615 _attributes[attr_name] = value; 01616 } 01617 01618 /// index operator write access to an attribute 01619 XS_String& operator[](const XS_String& attr_name) 01620 { 01621 return _attributes[attr_name]; 01622 } 01623 01624 /// index operator read access to an attribute 01625 XS_String operator[](const XS_String& attr_name) const 01626 { 01627 #if defined(UNICODE) && !defined(XS_STRING_UTF8) 01628 return _attributes.get(((std::string)attr_name).c_str()); 01629 #else 01630 return _attributes.get(attr_name.c_str()); 01631 #endif 01632 } 01633 01634 /// read only access to an attribute 01635 template<typename T> XS_String get(const T& attr_name, LPCXSSTR def=XS_EMPTY_STR) const 01636 { 01637 AttributeMap::const_iterator found = _attributes.find(attr_name); 01638 01639 if (found != _attributes.end()) 01640 return found->second; 01641 else 01642 return def; 01643 } 01644 01645 /// remove the attribute 'attr_name' 01646 void erase(const XS_String& attr_name) 01647 { 01648 _attributes.erase(attr_name); 01649 } 01650 01651 /// convenient value access in children node 01652 XS_String subvalue(const XS_String& child_name, const XS_String& attr_name, int n=0) const 01653 { 01654 const XMLNode* node = XPathElement(child_name, n).const_find(this); 01655 01656 if (node) 01657 return node->get(attr_name); 01658 else 01659 return XS_String(); 01660 } 01661 01662 /// convenient storage of distinct values in children node 01663 XS_String& subvalue(const XS_String& child_name, const XS_String& attr_name, int n=0) 01664 { 01665 XMLNode* node = XPathElement(child_name, n).find(this); 01666 01667 if (!node) { 01668 node = new XMLNode(child_name); 01669 add_child(node); 01670 } 01671 01672 return (*node)[attr_name]; 01673 } 01674 01675 #if defined(UNICODE) && !defined(XS_STRING_UTF8) 01676 /// convenient value access in children node 01677 XS_String subvalue(const char* child_name, const char* attr_name, int n=0) const 01678 { 01679 const XMLNode* node = XPathElement(child_name, n).const_find(this); 01680 01681 if (node) 01682 return node->get(attr_name); 01683 else 01684 return XS_String(); 01685 } 01686 01687 /// convenient storage of distinct values in children node 01688 XS_String& subvalue(const char* child_name, const XS_String& attr_name, int n=0) 01689 { 01690 XMLNode* node = XPathElement(child_name, n).find(this); 01691 01692 if (!node) { 01693 node = new XMLNode(child_name); 01694 add_child(node); 01695 } 01696 01697 return (*node)[attr_name]; 01698 } 01699 #endif 01700 01701 const Children& get_children() const 01702 { 01703 return _children; 01704 } 01705 01706 Children& get_children() 01707 { 01708 return _children; 01709 } 01710 01711 const AttributeMap& get_attributes() const 01712 { 01713 return _attributes; 01714 } 01715 01716 AttributeMap& get_attributes() 01717 { 01718 return _attributes; 01719 } 01720 01721 /// read element node content 01722 XS_String get_content() const 01723 { 01724 return DecodeXMLString(_content); 01725 } 01726 01727 /// read element node content as encoded string 01728 std::string get_encoded_content() const 01729 { 01730 return _content; 01731 } 01732 01733 /// read content of a subnode specified by an XPath expression 01734 XS_String get_sub_content(const XPath& xpath) const 01735 { 01736 const XMLNode* node = find_relative(xpath); 01737 01738 if (node) 01739 return node->get_content(); 01740 else 01741 return XS_EMPTY_STR; 01742 } 01743 01744 /// set element node content 01745 void set_content(const XS_String& s, bool cdata=false) 01746 { 01747 _content.assign(EncodeXMLString(s.c_str(), cdata)); 01748 } 01749 01750 /// set element node content from encoded string 01751 void set_encoded_content(const std::string& s) 01752 { 01753 _content.assign(s); 01754 } 01755 01756 /// set content of a subnode specified by an XPath expression 01757 bool set_sub_content(const XPath& xpath, const XS_String& s, bool cdata=false) 01758 { 01759 XMLNode* node = create_relative(xpath); 01760 01761 if (node) { 01762 node->set_content(s, cdata); 01763 return true; 01764 } else 01765 return false; 01766 } 01767 01768 #ifdef XMLNODE_LOCATION 01769 const XMLLocation& get_location() const {return _location;} 01770 #endif 01771 01772 /// write node with children tree to output stream 01773 bool write(std::ostream& out, const XMLFormat& format, WRITE_MODE mode=FORMAT_SMART, int indent=0) const 01774 { 01775 switch(mode) { 01776 case FORMAT_PLAIN: 01777 plain_write_worker(out); 01778 break; 01779 01780 case FORMAT_PRETTY: 01781 pretty_write_worker(out, format, indent); 01782 break; 01783 01784 case FORMAT_ORIGINAL: 01785 original_write_worker(out); 01786 break; 01787 01788 default: // FORMAT_SMART 01789 smart_write_worker(out, format, indent); 01790 } 01791 01792 return out.good(); 01793 } 01794 01795 /// count the nodes matching the given relative XPath expression 01796 int count(const XPath& xpath) const 01797 { 01798 return count(xpath.begin(), xpath.end()); 01799 } 01800 01801 /// count the nodes matching the given relative XPath expression 01802 int count(XPath::const_iterator from, const XPath::const_iterator& to) const; 01803 01804 /// copy matching tree nodes using the given XPath filter expression 01805 bool filter(const XPath& xpath, XMLNode& target) const; 01806 01807 /// XPath find function (const) 01808 const XMLNode* find_relative(const XPath& xpath) const; 01809 01810 /// XPath find function 01811 XMLNode* find_relative(const XPath& xpath); 01812 01813 XMLNode* get_first_child() const 01814 { 01815 if (!_children.empty()) 01816 return _children.front(); 01817 else 01818 return NULL; 01819 } 01820 01821 protected: 01822 Children _children; 01823 AttributeMap _attributes; 01824 01825 std::string _leading; // UTF-8 encoded 01826 std::string _content; // UTF-8 and entity encoded, may contain CDATA sections; decode with DecodeXMLString() 01827 std::string _end_leading; // UTF-8 encoded 01828 std::string _trailing; // UTF-8 encoded 01829 01830 #ifdef XMLNODE_LOCATION 01831 XMLLocation _location; 01832 #endif 01833 01834 bool _cdata_content; 01835 01836 /// relative XPath create function 01837 XMLNode* create_relative(const XPath& xpath); 01838 01839 /// create a new node tree using the given XPath filter expression 01840 XMLNode* filter(XPath::const_iterator from, const XPath::const_iterator& to) const; 01841 01842 void original_write_worker(std::ostream& out) const; 01843 void plain_write_worker(std::ostream& out) const; 01844 void pretty_write_worker(std::ostream& out, const XMLFormat& format, int indent) const; 01845 void smart_write_worker(std::ostream& out, const XMLFormat& format, int indent) const; 01846 }; 01847 01848 01849 /// iterator access to children nodes with name filtering 01850 struct XMLChildrenFilter 01851 { 01852 XMLChildrenFilter(XMLNode::Children& children, const XS_String& name) 01853 : _begin(children.begin(), children.end(), name), 01854 _end(children.end(), children.end(), name) 01855 { 01856 } 01857 01858 XMLChildrenFilter(XMLNode* node, const XS_String& name) 01859 : _begin(node->get_children().begin(), node->get_children().end(), name), 01860 _end(node->get_children().end(), node->get_children().end(), name) 01861 { 01862 } 01863 01864 /// internal iterator class 01865 struct iterator 01866 { 01867 typedef XMLNode::Children::iterator BaseIterator; 01868 typedef iterator myType; 01869 01870 iterator(BaseIterator begin, BaseIterator end, const XS_String& filter_name) 01871 : _cur(begin), 01872 _end(end), 01873 _filter_name(filter_name) 01874 { 01875 search_next(); 01876 } 01877 01878 operator BaseIterator() 01879 { 01880 return _cur; 01881 } 01882 01883 const XMLNode* operator*() const 01884 { 01885 return *_cur; 01886 } 01887 01888 XMLNode* operator*() 01889 { 01890 return *_cur; 01891 } 01892 01893 myType& operator++() 01894 { 01895 ++_cur; 01896 search_next(); 01897 01898 return *this; 01899 } 01900 01901 myType operator++(int) 01902 { 01903 myType ret = *this; 01904 01905 ++_cur; 01906 search_next(); 01907 01908 return ret; 01909 } 01910 01911 bool operator==(const myType& other) const 01912 { 01913 return _cur == other._cur; 01914 } 01915 01916 bool operator!=(const myType& other) const 01917 { 01918 return _cur != other._cur; 01919 } 01920 01921 protected: 01922 BaseIterator _cur; 01923 BaseIterator _end; 01924 XS_String _filter_name; 01925 01926 void search_next() 01927 { 01928 while(_cur!=_end && **_cur!=_filter_name) 01929 ++_cur; 01930 } 01931 }; 01932 01933 iterator begin() 01934 { 01935 return _begin; 01936 } 01937 01938 iterator end() 01939 { 01940 return _end; 01941 } 01942 01943 protected: 01944 iterator _begin; 01945 iterator _end; 01946 }; 01947 01948 01949 /// read only iterator access to children nodes with name filtering 01950 struct const_XMLChildrenFilter 01951 { 01952 const_XMLChildrenFilter(const XMLNode::Children& children, const XS_String& name) 01953 : _begin(children.begin(), children.end(), name), 01954 _end(children.end(), children.end(), name) 01955 { 01956 } 01957 01958 const_XMLChildrenFilter(const XMLNode* node, const XS_String& name) 01959 : _begin(node->get_children().begin(), node->get_children().end(), name), 01960 _end(node->get_children().end(), node->get_children().end(), name) 01961 { 01962 } 01963 01964 /// internal iterator class 01965 struct const_iterator 01966 { 01967 typedef XMLNode::Children::const_iterator BaseIterator; 01968 typedef const_iterator myType; 01969 01970 const_iterator(BaseIterator begin, BaseIterator end, const XS_String& filter_name) 01971 : _cur(begin), 01972 _end(end), 01973 _filter_name(filter_name) 01974 { 01975 search_next(); 01976 } 01977 01978 operator BaseIterator() 01979 { 01980 return _cur; 01981 } 01982 01983 const XMLNode* operator*() const 01984 { 01985 return *_cur; 01986 } 01987 01988 const XMLNode* operator->() const 01989 { 01990 return *_cur; 01991 } 01992 01993 myType& operator++() 01994 { 01995 ++_cur; 01996 search_next(); 01997 01998 return *this; 01999 } 02000 02001 myType operator++(int) 02002 { 02003 myType ret = *this; 02004 02005 ++_cur; 02006 search_next(); 02007 02008 return ret; 02009 } 02010 02011 bool operator==(const myType& other) const 02012 { 02013 return _cur == other._cur; 02014 } 02015 02016 bool operator!=(const myType& other) const 02017 { 02018 return _cur != other._cur; 02019 } 02020 02021 protected: 02022 BaseIterator _cur; 02023 BaseIterator _end; 02024 XS_String _filter_name; 02025 02026 void search_next() 02027 { 02028 while(_cur!=_end && **_cur!=_filter_name) 02029 ++_cur; 02030 } 02031 }; 02032 02033 const_iterator begin() 02034 { 02035 return _begin; 02036 } 02037 02038 const_iterator end() 02039 { 02040 return _end; 02041 } 02042 02043 protected: 02044 const_iterator _begin; 02045 const_iterator _end; 02046 }; 02047 02048 02049 /// iterator for XML trees 02050 struct XMLPos 02051 { 02052 XMLPos(XMLNode* root) 02053 : _root(root), 02054 _cur(root) 02055 { 02056 } 02057 02058 XMLPos(const XMLPos& other) 02059 : _root(other._root), 02060 _cur(other._cur) 02061 { // don't copy _stack 02062 } 02063 02064 XMLPos(XMLNode* node, const XS_String& name) 02065 : _root(node), 02066 _cur(node) 02067 { 02068 smart_create(name); 02069 } 02070 02071 XMLPos(XMLNode* node, const XS_String& name, const XS_String& attr_name, const XS_String& attr_value) 02072 : _root(node), 02073 _cur(node) 02074 { 02075 smart_create(name, attr_name, attr_value); 02076 } 02077 02078 XMLPos(const XMLPos& other, const XS_String& name) 02079 : _root(other._root), 02080 _cur(other._cur) 02081 { 02082 smart_create(name); 02083 } 02084 02085 XMLPos(const XMLPos& other, const XS_String& name, const XS_String& attr_name, const XS_String& attr_value) 02086 : _root(other._root), 02087 _cur(other._cur) 02088 { 02089 smart_create(name, attr_name, attr_value); 02090 } 02091 02092 /// access to current node 02093 XMLNode& cur() 02094 { 02095 return *_cur; 02096 } 02097 02098 const XMLNode& cur() const 02099 { 02100 return *_cur; 02101 } 02102 02103 /// automatic access to current node 02104 operator const XMLNode*() const {return _cur;} 02105 operator XMLNode*() {return _cur;} 02106 02107 const XMLNode* operator->() const {return _cur;} 02108 XMLNode* operator->() {return _cur;} 02109 02110 const XMLNode& operator*() const {return *_cur;} 02111 XMLNode& operator*() {return *_cur;} 02112 02113 /// attribute access 02114 XS_String get(const XS_String& attr_name, LPCXSSTR def=XS_EMPTY_STR) const 02115 { 02116 return _cur->get(attr_name, def); 02117 } 02118 02119 /// attribute setting 02120 void put(const XS_String& attr_name, const XS_String& value) 02121 { 02122 _cur->put(attr_name, value); 02123 } 02124 02125 /// index operator attribute access 02126 template<typename T> XS_String get(const T& attr_name) const {return (*_cur)[attr_name];} 02127 XS_String& operator[](const XS_String& attr_name) {return (*_cur)[attr_name];} 02128 const XS_String& operator[](const XS_String& attr_name) const {return (*_cur)[attr_name];} 02129 02130 /// insert children when building tree 02131 void add_down(XMLNode* child) 02132 { 02133 _cur->add_child(child); 02134 go_to(child); 02135 } 02136 02137 /// go back to previous position 02138 bool back() 02139 { 02140 if (!_stack.empty()) { 02141 _cur = _stack.top(); 02142 _stack.pop(); 02143 return true; 02144 } else { 02145 assert(!_stack.empty()); 02146 return false; 02147 } 02148 } 02149 02150 /// go down to first child 02151 bool go_down() 02152 { 02153 XMLNode* node = _cur->get_first_child(); 02154 02155 if (node) { 02156 go_to(node); 02157 return true; 02158 } else 02159 return false; 02160 } 02161 02162 /// search for child and go down 02163 bool go_down(const XS_String& child_name, int n=0) 02164 { 02165 XMLNode* node = XPathElement(child_name, n).find(_cur); 02166 02167 if (node) { 02168 go_to(node); 02169 return true; 02170 } else 02171 return false; 02172 } 02173 02174 /// iterate to the next matching child 02175 bool iterate(const XS_String& child_name, int& cnt) 02176 { 02177 XMLNode* node = XPathElement(child_name, cnt).find(_cur); 02178 02179 if (node) { 02180 go_to(node); 02181 ++cnt; 02182 return true; 02183 } else 02184 return false; 02185 } 02186 02187 /// move to the position defined by xpath in XML tree 02188 bool go(const XPath& xpath); 02189 02190 /// create child nodes using XPath notation and move to the deepest child 02191 bool create_relative(const XPath& xpath) 02192 { 02193 XMLNode* node = _cur->create_relative(xpath); 02194 if (!node) 02195 return false; // invalid path specified 02196 02197 go_to(node); 02198 return true; 02199 } 02200 02201 /// create node and move to it 02202 void create(const XS_String& name) 02203 { 02204 add_down(new XMLNode(name)); 02205 } 02206 02207 /// create node with string content 02208 void create_node_content(const XS_String& node_name, const XS_String& content) 02209 { 02210 XMLNode* pNode = new XMLNode(node_name); 02211 pNode->set_content(content); 02212 _cur->add_child(pNode); 02213 } 02214 02215 /// create node if not already existing and move to it 02216 void smart_create(const XS_String& child_name) 02217 { 02218 XMLNode* node = XPathElement(child_name).find(_cur); 02219 02220 if (node) 02221 go_to(node); 02222 else 02223 add_down(new XMLNode(child_name)); 02224 } 02225 02226 /// search matching child node identified by key name and an attribute value 02227 void smart_create(const XS_String& child_name, const XS_String& attr_name, const XS_String& attr_value) 02228 { 02229 XMLNode* node = XPathElement(child_name, 0, attr_name, attr_value).find(_cur); 02230 02231 if (node) 02232 go_to(node); 02233 else { 02234 node = new XMLNode(child_name); 02235 add_down(node); 02236 (*node)[attr_name] = attr_value; 02237 } 02238 } 02239 02240 /// count the nodes matching the given relative XPath expression 02241 int count(const XPath& xpath) const 02242 { 02243 return _cur->count(xpath); 02244 } 02245 02246 /// create a new node tree using the given XPath filter expression 02247 int filter(const XPath& xpath, XMLNode& target) const 02248 { 02249 return _cur->filter(xpath, target); 02250 } 02251 02252 #if defined(UNICODE) && !defined(XS_STRING_UTF8) 02253 /// search for child and go down 02254 bool go_down(const char* child_name, int n=0) 02255 { 02256 XMLNode* node = XPathElement(child_name, n).find(_cur); 02257 02258 if (node) { 02259 go_to(node); 02260 return true; 02261 } else 02262 return false; 02263 } 02264 02265 /// create node and move to it 02266 void create(const char* child_name) 02267 { 02268 add_down(new XMLNode(child_name)); 02269 } 02270 02271 /// create node if not already existing and move to it 02272 void smart_create(const char* child_name) 02273 { 02274 XMLNode* node = XPathElement(child_name).find(_cur); 02275 02276 if (node) 02277 go_to(node); 02278 else 02279 add_down(new XMLNode(child_name)); 02280 } 02281 02282 /// search matching child node identified by key name and an attribute value 02283 template<typename T, typename U> 02284 void smart_create(const char* child_name, const T& attr_name, const U& attr_value) 02285 { 02286 XMLNode* node = XPathElement(child_name, 0, attr_name, attr_value).find(_cur); 02287 02288 if (node) 02289 go_to(node); 02290 else { 02291 node = new XMLNode(child_name); 02292 add_down(node); 02293 (*node)[attr_name] = attr_value; 02294 } 02295 } 02296 #endif 02297 02298 /// delete current node and go back to previous position 02299 bool delete_this() 02300 { 02301 if (!_stack.empty()) { 02302 XMLNode* pLast = _stack.top(); 02303 02304 if (pLast->_children.remove(_cur)) { 02305 _cur = _stack.top(); 02306 return true; 02307 } 02308 } 02309 02310 return false; 02311 } 02312 02313 /// remove all children named 'name' 02314 void remove_children(const XS_String& name) 02315 { 02316 _cur->remove_children(name); 02317 } 02318 02319 /// remove the attribute 'attr_name' from the current node 02320 void erase(const XS_String& attr_name) 02321 { 02322 _cur->erase(attr_name); 02323 } 02324 02325 XS_String& str() {return *_cur;} 02326 const XS_String& str() const {return *_cur;} 02327 02328 // property (key/value pair) setter functions 02329 void set_property(const XS_String& key, int value, const XS_String& name=XS_PROPERTY); 02330 void set_property(const XS_String& key, double value, const XS_String& name=XS_PROPERTY); 02331 void set_property(const XS_String& key, const XS_String& value, const XS_String& name=XS_PROPERTY); 02332 void set_property(const XS_String& key, const struct XMLBool& value, const XS_String& name=XS_PROPERTY); 02333 02334 void set_property(const XS_String& key, const char* value, const XS_String& name=XS_PROPERTY) 02335 {set_property(key, XS_String(value), name);} 02336 02337 protected: 02338 friend struct const_XMLPos; // access to _root 02339 02340 XMLNode* _root; 02341 XMLNode* _cur; 02342 std::stack<XMLNode*> _stack; 02343 02344 /// go to specified node 02345 void go_to(XMLNode* child) 02346 { 02347 _stack.push(_cur); 02348 _cur = child; 02349 } 02350 }; 02351 02352 02353 /// iterator for XML trees 02354 struct const_XMLPos 02355 { 02356 const_XMLPos(const XMLNode* root) 02357 : _root(root), 02358 _cur(root) 02359 { 02360 } 02361 02362 const_XMLPos(const const_XMLPos& other) 02363 : _root(other._root), 02364 _cur(other._cur) 02365 { // don't copy _stack 02366 } 02367 02368 const_XMLPos(const XMLPos& other) 02369 : _root(other._root), 02370 _cur(other._cur) 02371 { // don't copy _stack 02372 } 02373 02374 /// access to current node 02375 const XMLNode& cur() const 02376 { 02377 return *_cur; 02378 } 02379 02380 /// automatic access to current node 02381 operator const XMLNode*() const {return _cur;} 02382 02383 const XMLNode* operator->() const {return _cur;} 02384 02385 const XMLNode& operator*() const {return *_cur;} 02386 02387 /// attribute access 02388 XS_String get(const XS_String& attr_name) const 02389 { 02390 return _cur->get(attr_name); 02391 } 02392 02393 /// index operator attribute access 02394 template<typename T> XS_String get(const T& attr_name) const {return _cur->get(attr_name);} 02395 XS_String operator[](const XS_String& attr_name) const {return _cur->get(attr_name);} 02396 02397 /// go back to previous position 02398 bool back() 02399 { 02400 if (!_stack.empty()) { 02401 _cur = _stack.top(); 02402 _stack.pop(); 02403 return true; 02404 } else { 02405 assert(!_stack.empty()); 02406 return false; 02407 } 02408 } 02409 02410 /// go down to first child 02411 bool go_down() 02412 { 02413 const XMLNode* node = _cur->get_first_child(); 02414 02415 if (node) { 02416 go_to(node); 02417 return true; 02418 } else 02419 return false; 02420 } 02421 02422 /// search for child and go down 02423 bool go_down(const XS_String& child_name, int n=0) 02424 { 02425 const XMLNode* node = XPathElement(child_name, n).const_find(_cur); 02426 02427 if (node) { 02428 go_to(node); 02429 return true; 02430 } else 02431 return false; 02432 } 02433 02434 /// iterate to the next matching child 02435 bool iterate(const XS_String& child_name, int& cnt) 02436 { 02437 const XMLNode* node = XPathElement(child_name, cnt).const_find(_cur); 02438 02439 if (node) { 02440 go_to(node); 02441 ++cnt; 02442 return true; 02443 } else 02444 return false; 02445 } 02446 02447 /// move to the position defined by xpath in XML tree 02448 bool go(const XPath& xpath); 02449 02450 #if defined(UNICODE) && !defined(XS_STRING_UTF8) 02451 /// search for child and go down 02452 bool go_down(const char* child_name, int n=0) 02453 { 02454 const XMLNode* node = XPathElement(child_name, n).const_find(_cur); 02455 02456 if (node) { 02457 go_to(node); 02458 return true; 02459 } else 02460 return false; 02461 } 02462 #endif 02463 02464 const XS_String& str() const {return *_cur;} 02465 02466 protected: 02467 const XMLNode* _root; 02468 const XMLNode* _cur; 02469 std::stack<const XMLNode*> _stack; 02470 02471 /// go to specified node 02472 void go_to(const XMLNode* child) 02473 { 02474 _stack.push(_cur); 02475 _cur = child; 02476 } 02477 }; 02478 02479 02480 #ifdef _MSC_VER 02481 #pragma warning(disable: 4355) // 'this' : used in base member initializer list 02482 #endif 02483 02484 /// XML reader base class 02485 struct XMLReaderBase 02486 #ifdef XS_USE_XERCES 02487 : public HandlerBase 02488 #endif 02489 { 02490 #ifdef XS_USE_XERCES 02491 02492 XMLReaderBase(XMLNode* node, InputSource* source, bool adoptSource=false); 02493 virtual ~XMLReaderBase(); 02494 02495 void read(); 02496 02497 protected: 02498 SAXParser* _parser; 02499 InputSource* _source; 02500 bool _deleteSource; 02501 02502 virtual void XMLDecl(const XMLCh* const versionStr, const XMLCh* const encodingStr, 02503 const XMLCh* const standaloneStr, const XMLCh* const actualEncodingStr); 02504 02505 // Handlers for the SAX DocumentHandler interface 02506 virtual void setDocumentLocator(const Locator* const locator); 02507 virtual void startElement(const XMLCh* const name, AttributeList& attributes); 02508 virtual void endElement(const XMLCh* const name); 02509 virtual void characters(const XMLCh* const chars, const unsigned int length); 02510 virtual void ignorableWhitespace(const XMLCh* const chars, const unsigned int length); 02511 02512 // Handlers for the SAX ErrorHandler interface 02513 virtual void error(const SAXParseException& e); 02514 virtual void fatalError(const SAXParseException& e); 02515 virtual void warning(const SAXParseException& e); 02516 virtual void resetErrors(); 02517 02518 #elif defined(XS_USE_EXPAT) // !XS_USE_XERCES 02519 02520 XMLReaderBase(XMLNode* node); 02521 virtual ~XMLReaderBase(); 02522 02523 protected: 02524 XML_Parser _parser; 02525 02526 static void XMLCALL XML_XmlDeclHandler(void* userData, const XML_Char* version, const XML_Char* encoding, int standalone=-1); 02527 static void XMLCALL XML_StartElementHandler(void* userData, const XML_Char* name, const XML_Char** atts); 02528 static void XMLCALL XML_EndElementHandler(void* userData, const XML_Char* name); 02529 static void XMLCALL XML_DefaultHandler(void* userData, const XML_Char* s, int len); 02530 02531 static std::string get_expat_error_string(XML_Error error_code); 02532 02533 #else // XS_USE_EXPAT 02534 02535 XMLReaderBase(XMLNode* node) 02536 : _pos(node), 02537 _endl_defined(false) 02538 { 02539 _last_tag = TAG_NONE; 02540 } 02541 02542 virtual ~XMLReaderBase(); 02543 02544 bool parse(); 02545 02546 #endif 02547 02548 public: 02549 #ifndef XS_USE_XERCES 02550 void read(); 02551 02552 std::string get_position() const {return _location.str();} 02553 #endif 02554 const XMLFormat& get_format() const {return _format;} 02555 const char* get_endl() const {return _endl_defined? _format._endl: "\n";} 02556 02557 const XMLErrorList& get_errors() const {return _errors;} 02558 const XMLErrorList& get_warnings() const {return _warnings;} 02559 02560 void clear_errors() {_errors.clear(); _warnings.clear();} 02561 02562 #ifdef XS_NATIVE 02563 XMLLocation get_location() const {return _location;} 02564 void setSystemId(const char* systemId) {_location.set_path(systemId);} 02565 #elif defined(XMLNODE_LOCATION) 02566 const char* _display_path; // character pointer for fast reference in XMLLocation 02567 02568 #ifdef XS_USE_XERCES 02569 const Locator* _locator; 02570 #endif 02571 02572 XMLLocation get_location() const; 02573 void setSystemId(const char* systemId) {_display_path = systemId;} 02574 #endif 02575 02576 std::string get_encoded_content() const {return _content;} 02577 02578 protected: 02579 XMLPos _pos; 02580 02581 std::string _content; // UTF-8 encoded 02582 enum {TAG_NONE, TAG_START, TAG_END} _last_tag; 02583 02584 XMLErrorList _errors; 02585 XMLErrorList _warnings; 02586 02587 XMLFormat _format; 02588 bool _endl_defined; 02589 02590 #ifdef XS_NATIVE 02591 XMLLocation _location; 02592 02593 virtual int get() = 0; 02594 int eat_endl(); 02595 #elif defined(XS_USE_XERCES) 02596 //TODO 02597 #elif defined(XS_USE_EXPAT) 02598 virtual int read_buffer(char* buffer, int len) = 0; 02599 #endif 02600 02601 void finish_read(); 02602 02603 virtual void XmlDeclHandler(const char* version, const char* encoding, int standalone); 02604 virtual void StartElementHandler(const XS_String& name, const XMLNode::AttributeMap& attributes); 02605 virtual void EndElementHandler(); 02606 #if defined(XS_USE_XERCES) || defined(XS_USE_EXPAT) 02607 virtual void DefaultHandler(const XML_Char* s, int len); 02608 #else 02609 virtual void DefaultHandler(const std::string& s); 02610 #endif 02611 02612 #if !defined(XS_USE_XERCES) && !defined(XS_USE_EXPAT) 02613 friend struct ParseContext; 02614 #endif 02615 }; 02616 02617 02618 /// XML file reader 02619 02620 #ifdef XS_USE_XERCES 02621 02622 struct XercesXMLReader : public XMLReaderBase 02623 { 02624 XercesXMLReader(XMLNode* node, InputSource* source, bool adoptSource=false) 02625 : XMLReaderBase(node, source, adoptSource) 02626 { 02627 } 02628 02629 XercesXMLReader(XMLNode* node, LPCTSTR path); 02630 XercesXMLReader(XMLNode* node, const XMLByte* buffer, size_t bytes, const std::string& system_id=std::string()); 02631 }; 02632 02633 #define XMLReader XercesXMLReader 02634 02635 #elif defined(XS_USE_EXPAT) 02636 02637 struct ExpatXMLReader : public XMLReaderBase 02638 { 02639 ExpatXMLReader(XMLNode* node, std::istream& in) 02640 : XMLReaderBase(node), 02641 _in(in) 02642 { 02643 } 02644 02645 /// read XML stream into XML tree below _pos 02646 int read_buffer(char* buffer, int len) 02647 { 02648 if (!_in.good()) 02649 return -1; 02650 02651 _in.read(buffer, len); 02652 02653 return _in.gcount(); 02654 } 02655 02656 protected: 02657 std::istream& _in; 02658 }; 02659 02660 #define XMLReader ExpatXMLReader 02661 02662 #else // XS_USE_XERCES, XS_USE_EXPAT 02663 02664 struct XMLReader : public XMLReaderBase 02665 { 02666 XMLReader(XMLNode* node, std::istream& in) 02667 : XMLReaderBase(node), 02668 _in(in), 02669 _last_crlf(0) 02670 { 02671 } 02672 02673 /// read one character from XML stream 02674 int get() 02675 { 02676 int c = _in.get(); 02677 02678 // // increment line counter on LF 02679 // if (c == '\n') { 02680 // _location._column = 1; 02681 // ++_location._line; 02682 // increment line counter on LF, CR, CR/LF or LF/CR line endings 02683 if (c=='\n' || c=='\r') { 02684 if (!_last_crlf || c==_last_crlf) { 02685 _location._column = 1; 02686 ++_location._line; 02687 _last_crlf = c; 02688 } else 02689 _last_crlf = 0; 02690 } else { 02691 ++_location._column; 02692 _last_crlf = 0; 02693 } 02694 02695 return c; 02696 } 02697 02698 protected: 02699 std::istream& _in; 02700 int _last_crlf; 02701 }; 02702 02703 struct ReadBuffer 02704 { 02705 ReadBuffer(XMLErrorList& errors, XMLLocation& location); 02706 ~ReadBuffer(); 02707 02708 void reset(); 02709 bool empty() const {return _wptr==_buffer;} 02710 void append(int c); 02711 const std::string& str(bool utf8); 02712 size_t len() const; 02713 bool has_CDEnd() const; 02714 XS_String get_tag() const; 02715 void get_attributes(XMLNode::AttributeMap& attributes) const; 02716 XMLLocation& get_location() const {return _location;} 02717 02718 protected: 02719 XMLErrorList& _errors; 02720 XMLLocation& _location; 02721 char* _buffer; 02722 char* _wptr; 02723 size_t _len; 02724 std::string _buffer_str; // UTF-8 encoded 02725 }; 02726 02727 struct ParseContext 02728 { 02729 ParseContext(XMLReaderBase& reader); 02730 02731 void read_bom(); 02732 bool proceed(); 02733 int process_next(int c); 02734 02735 XMLReaderBase& _reader; 02736 ReadBuffer _buffer; 02737 int _next; 02738 bool _in_comment; 02739 bool _utf8; 02740 }; 02741 02742 #endif // XS_USE_XERCES 02743 02744 02745 #if defined(_MSC_VER) && _MSC_VER<1400 02746 02747 struct fast_ostringbuffer : public std::streambuf 02748 { 02749 typedef char _E; 02750 typedef std::char_traits<_E> _Tr; 02751 02752 explicit fast_ostringbuffer() 02753 {_Init(0, 0, std::_Noread);} // optimized for ios::out mode 02754 02755 virtual ~fast_ostringbuffer() 02756 {_Tidy();} 02757 02758 std::string str() const 02759 {if (pptr() != 0) 02760 {std::string _Str(pbase(), 02761 (_Seekhigh<pptr()? pptr(): _Seekhigh) - pbase()); 02762 return _Str;} 02763 else 02764 return std::string();} 02765 02766 protected: 02767 virtual int_type overflow(int_type _C = _Tr::eof()) 02768 {if (_Tr::eq_int_type(_Tr::eof(), _C)) 02769 return _Tr::not_eof(_C); 02770 else if (pptr() != 0 && pptr() < epptr()) 02771 {*_Pninc() = _Tr::to_char_type(_C); 02772 return _C;} 02773 else 02774 {size_t _Os = gptr() == 0 ? 0 : epptr() - eback(); 02775 size_t _Ns = _Os + _Alsize; 02776 _E *_P = _Al.allocate(_Ns, (void *)0); 02777 if (0 < _Os) 02778 _Tr::copy(_P, eback(), _Os); 02779 else if (_ALSIZE < _Alsize) 02780 _Alsize = _ALSIZE; 02781 02782 if (_Strmode & std::_Allocated) 02783 _Al.deallocate(eback(), _Os); 02784 02785 _Strmode |= std::_Allocated; 02786 02787 if (_Os == 0) 02788 {_Seekhigh = _P; 02789 setp(_P, _P + _Ns); 02790 setg(_P, _P, _P); } 02791 else 02792 {_Seekhigh = _Seekhigh - eback() + _P; 02793 setp(pbase() - eback() + _P, pptr() - eback() + _P, _P + _Ns); 02794 setg(_P, _P, _P);} 02795 *_Pninc() = _Tr::to_char_type(_C); 02796 02797 return _C;}} 02798 02799 void _Init(const _E *_S, size_t _N, std::_Strstate _M) 02800 {_Pendsave = 0, _Seekhigh = 0; 02801 _Alsize = _MINSIZE, _Strmode = _M; 02802 setg(0, 0, 0); 02803 setp(0, 0);} 02804 02805 void _Tidy() 02806 {if (_Strmode & std::_Allocated) 02807 _Al.deallocate(eback(), (pptr() != 0 ? epptr() : egptr()) - eback()); 02808 _Seekhigh = 0; 02809 _Strmode &= ~std::_Allocated;} 02810 02811 private: 02812 enum {_ALSIZE = 65536/*512*/, _MINSIZE = 32768/*32*/}; // bigger buffer sizes 02813 02814 _E *_Pendsave, *_Seekhigh; 02815 int _Alsize; 02816 std::_Strstate _Strmode; 02817 std::allocator<_E> _Al; 02818 }; 02819 02820 struct fast_ostringstream : public std::iostream 02821 { 02822 typedef std::iostream super; 02823 02824 explicit fast_ostringstream() 02825 : super(&_Sb) {} 02826 02827 std::string str() const 02828 {return _Sb.str();} 02829 02830 private: 02831 fast_ostringbuffer _Sb; 02832 }; 02833 02834 #else 02835 02836 typedef std::ostringstream fast_ostringstream; 02837 02838 #endif 02839 02840 02841 /// XML document holder 02842 struct XMLDoc : public XMLNode 02843 { 02844 XMLDoc() 02845 : XMLNode("") 02846 { 02847 } 02848 02849 XMLDoc(LPCTSTR path) 02850 : XMLNode("") 02851 { 02852 read_file(path); 02853 } 02854 02855 #ifdef XS_USE_XERCES 02856 bool read_file(LPCTSTR path) 02857 { 02858 XMLReader reader(this, path); 02859 02860 #if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8) 02861 return read(reader, std::string(ANS(path))); 02862 #else 02863 return read(reader, XS_String(path)); 02864 #endif 02865 } 02866 02867 bool read_buffer(const char* buffer, size_t len, const std::string& system_id=std::string()) 02868 { 02869 XMLReader reader(this, (const XMLByte*)buffer, len, system_id); 02870 02871 return read(reader, system_id); 02872 } 02873 02874 bool read_buffer(const std::string& in, const std::string& system_id=std::string()) 02875 { 02876 return read_buffer(in.c_str(), in.length(), system_id); 02877 } 02878 02879 #else // XS_USE_XERCES 02880 02881 bool read_file(LPCTSTR path) 02882 { 02883 tifstream in(path); 02884 if (!in.good()) 02885 return false; 02886 02887 XMLReader reader(this, in); 02888 02889 #if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8) 02890 return read(reader, std::string(ANS(path))); 02891 #else 02892 return read(reader, XS_String(path)); 02893 #endif 02894 } 02895 02896 bool read_buffer(const char* buffer, size_t len, const std::string& system_id=std::string()) 02897 { 02898 return read_buffer(std::string(buffer, len), system_id); 02899 } 02900 02901 bool read_buffer(const std::string& buffer, const std::string& system_id=std::string()) 02902 { 02903 std::istringstream istr(buffer); 02904 02905 return read_stream(istr, system_id); 02906 } 02907 02908 bool read_stream(std::istream& in, const std::string& system_id=std::string()) 02909 { 02910 XMLReader reader(this, in); 02911 02912 return read(reader, system_id); 02913 } 02914 #endif // XS_USE_XERCES 02915 02916 bool read(XMLReaderBase& reader, const std::string& display_path) 02917 { 02918 #ifdef XS_NATIVE 02919 reader.setSystemId(display_path.c_str()); 02920 #elif defiend(XMLNODE_LOCATION) 02921 // make a string copy to handle temporary string objects 02922 _display_path = display_path; 02923 reader._display_path = _display_path.c_str(); 02924 #endif 02925 02926 reader.clear_errors(); 02927 reader.read(); 02928 02929 _format = reader.get_format(); 02930 _format._endl = reader.get_endl(); 02931 02932 if (!reader.get_errors().empty()) { 02933 _errors = reader.get_errors(); 02934 return false; 02935 } 02936 02937 return true; 02938 } 02939 02940 /// write XML stream 02941 // FORMAT_SMART: preserving previous white space and comments 02942 bool write(std::ostream& out, WRITE_MODE mode=FORMAT_SMART) const 02943 { 02944 _format.print_header(out, mode!=FORMAT_PLAIN); 02945 02946 if (_children.size() == 1) 02947 _children.front()->write(out, _format, mode); 02948 else if (!_children.empty()) { 02949 //throw Exception("more than one XML root!"); 02950 return false; 02951 } 02952 02953 return out.good(); 02954 } 02955 02956 /// write XML stream with formating 02957 bool write_formating(std::ostream& out) const 02958 { 02959 return write(out, FORMAT_PRETTY); 02960 } 02961 02962 bool write_file(LPCTSTR path, WRITE_MODE mode=FORMAT_SMART) const 02963 { 02964 tofstream out(path); 02965 02966 return write(out, mode); 02967 } 02968 02969 bool write_formating(LPCTSTR path) const 02970 { 02971 tofstream out(path); 02972 02973 return write_formating(out); 02974 } 02975 02976 XMLFormat _format; 02977 XMLErrorList _errors; 02978 02979 #ifdef XMLNODE_LOCATION 02980 std::string _display_path; 02981 #endif 02982 }; 02983 02984 02985 struct XMLStateReader : public XMLReader 02986 { 02987 enum XML_STATE { 02988 XSS_NONE, 02989 XSS_START_ELEMENT, 02990 XSS_END_ELEMENT, 02991 XSS_ELEMENT, 02992 XSS_CHARACTERS, 02993 // XSS_COMMENT, 02994 // XSS_SPACE, 02995 // XSS_CDATA, 02996 // XSS_PROCESSING_INSTRUCTION 02997 }; 02998 02999 XMLStateReader(XMLNode* node, std::istream& in) 03000 : XMLReader(node, in), 03001 _parse_ctx(*this), 03002 _state(XSS_NONE) 03003 { 03004 } 03005 03006 bool has_next(); 03007 void next(); 03008 03009 // virtual void XmlDeclHandler(const char* version, const char* encoding, int standalone); 03010 virtual void StartElementHandler(const XS_String& name, const XMLNode::AttributeMap& attr); 03011 virtual void EndElementHandler(); 03012 virtual void DefaultHandler(const std::string& s); 03013 03014 ParseContext _parse_ctx; 03015 03016 enum XML_STATE _state; 03017 XS_String _node_name; 03018 XMLNode::AttributeMap _attrs; 03019 }; 03020 03021 03022 struct XMLStreamReader 03023 { 03024 typedef XMLReader super; 03025 03026 XMLStreamReader(std::istream& in) 03027 : _pInFile(NULL), 03028 _state_rdr(NULL, in), 03029 _level(0), 03030 _node(XS_EMPTY_STR) 03031 { 03032 } 03033 03034 XMLStreamReader(LPCTSTR path) 03035 : _pInFile(new tifstream(path)), 03036 _state_rdr(NULL, *_pInFile), 03037 _level(0), 03038 _node(XS_EMPTY_STR) 03039 { 03040 #ifdef UNICODE 03041 _state_rdr._parse_ctx._reader.setSystemId(std::string(XS_String(path)).c_str()); 03042 #else 03043 _state_rdr._parse_ctx._reader.setSystemId(path); 03044 #endif 03045 } 03046 03047 ~XMLStreamReader() 03048 { 03049 delete _pInFile; 03050 } 03051 03052 /*TODO 03053 XS_String getInstructions() const 03054 { 03055 return _instructions; 03056 } 03057 */ 03058 const XMLNode* operator->() const 03059 { 03060 return &_node; 03061 } 03062 03063 operator const XMLNode*() const 03064 { 03065 return &_node; 03066 } 03067 03068 XS_String str() const 03069 { 03070 return _node; 03071 } 03072 03073 /** 03074 * Return the value of an attribute in the current node. 03075 * @param attr_name 03076 * @return 03077 */ 03078 XS_String operator[](const XS_String& attr_name) const 03079 { 03080 return _node[attr_name]; 03081 } 03082 03083 /** 03084 * Go down to first child. 03085 * @return true if successfull 03086 */ 03087 bool go_down() 03088 { 03089 return first_child(); 03090 } 03091 03092 /** 03093 * Search for child and go down. 03094 * @param child_name 03095 * @return 03096 */ 03097 bool go_down(const XS_String& child_name) 03098 { 03099 return first_child(child_name); 03100 } 03101 03102 /// move X-Path like to position in XML tree 03103 bool go(const XPath& xpath) 03104 { 03105 // Absolute paths are not supported. 03106 if (xpath._absolute) 03107 return false; 03108 03109 return find_relative(xpath); 03110 } 03111 03112 /** 03113 * Move back to the next higher nesting level. 03114 * Remark: This implementation does _not_ jump more than one level up like XMLPos.node() 03115 * when using go() to move down more than one level at a time. 03116 * @return true if successfull 03117 */ 03118 bool back() 03119 { 03120 if (find_node(NULL, -1, _level+1, false)) 03121 // if (find_node(NULL, _level-1, _level-1, false)) 03122 return true; 03123 else { 03124 assert(_level>=0); // tried to move out of the tree hierarchy 03125 return false; 03126 } 03127 } 03128 03129 /** 03130 * Move to the first child node with the specified name. 03131 * @return true on success 03132 */ 03133 bool first_child(LPCXSSTR node_name=NULL) 03134 { 03135 return find_node(node_name, _level+1, _level, false); 03136 } 03137 03138 /** 03139 * Move to the next sibling node independent from its name. 03140 * @return true on success 03141 */ 03142 bool next() 03143 { 03144 return find_node(NULL, _level, _level-1, false); 03145 } 03146 03147 /** 03148 * Move to the next sibling node with the specified name. 03149 * @return true on success 03150 */ 03151 bool next_skip_others(const XS_String& node_name) 03152 { 03153 return find_node(node_name, _level, _level-1, false); 03154 } 03155 03156 /** 03157 * Move to the next sibling node with the specified name. 03158 * @return true on success 03159 */ 03160 bool next_stop_on_others(LPCXSSTR node_name=NULL) 03161 { 03162 return find_node(node_name, _level, _level-1, true); 03163 } 03164 03165 // Search matching child node identified by key name and an attribute value. 03166 bool find(const XPathElement& xelem) 03167 { 03168 int n = 0; 03169 03170 if (first_child(xelem._child_name)) { 03171 if (xelem.matches(_node, n)) 03172 return true; 03173 03174 while(next_skip_others(xelem._child_name)) 03175 if (xelem.matches(_node, n)) 03176 return true; 03177 } 03178 03179 return false; 03180 } 03181 03182 bool find_relative(const XPath& xpath); 03183 03184 const XMLErrorList& get_errors() const {return _state_rdr.get_errors();} 03185 03186 int _level; 03187 03188 private: 03189 tifstream* _pInFile; 03190 XMLStateReader _state_rdr; 03191 std::string _content; 03192 03193 protected: 03194 bool find_node(LPCXSSTR target_tag, int target_level, int min_level, bool stop_on_others); 03195 03196 XMLNode _node; 03197 03198 //protected: XS_String _instructions; 03199 03200 virtual void StartElementHandler(const XS_String& name, const XMLNode::AttributeMap& attr); 03201 virtual void EndElementHandler(); 03202 virtual void DefaultHandler(const std::string& s); 03203 }; 03204 03205 03206 /// read only iterator access to XMLStreamReader nodes 03207 struct XMLStreamChildrenIterator 03208 { 03209 XMLStreamChildrenIterator(XMLStreamReader& reader) 03210 : _begin(reader, false), 03211 _end(reader, true) 03212 { 03213 } 03214 03215 /// internal iterator class 03216 struct const_iterator 03217 { 03218 typedef const_iterator myType; 03219 03220 const_iterator(XMLStreamReader& reader, bool is_end) 03221 : _reader(reader), 03222 _start_level(reader._level), 03223 _is_end(is_end) 03224 { 03225 search_next(); 03226 } 03227 03228 const XMLStreamReader& operator->() const 03229 { 03230 return _reader; 03231 } 03232 03233 XS_String operator*() const 03234 { 03235 return _reader.str(); 03236 } 03237 03238 myType& operator++() 03239 { 03240 if (!_at_end) 03241 search_next(); 03242 03243 return *this; 03244 } 03245 03246 myType operator++(int) 03247 { 03248 myType ret = *this; 03249 03250 if (!_at_end) 03251 search_next(); 03252 03253 return ret; 03254 } 03255 03256 bool operator==(const myType& other) const 03257 { 03258 if (other._is_end) 03259 return _at_end; 03260 else if (_is_end) 03261 return other._at_end; 03262 else 03263 return _reader.str() == other._reader.str(); 03264 } 03265 03266 bool operator!=(const myType& other) const 03267 { 03268 if (other._is_end) 03269 return !_at_end; 03270 else if (_is_end) 03271 return !other._at_end; 03272 else 03273 return _reader.str() != other._reader.str(); 03274 } 03275 03276 protected: 03277 XMLStreamReader& _reader; 03278 int _start_level; 03279 bool _is_end; 03280 bool _at_end; 03281 03282 void search_next() 03283 { 03284 while(!_at_end) { 03285 _reader.next(); 03286 03287 if (_reader._level == _start_level) 03288 _at_end = true; 03289 } 03290 } 03291 }; 03292 03293 const_iterator begin() 03294 { 03295 return _begin; 03296 } 03297 03298 const_iterator end() 03299 { 03300 return _end; 03301 } 03302 03303 protected: 03304 const_iterator _begin; 03305 const_iterator _end; 03306 }; 03307 03308 03309 /// read only iterator access to children nodes to XMLStreamReader nodes with name filtering 03310 struct XMLStreamChildrenFilter 03311 { 03312 XMLStreamChildrenFilter(XMLStreamReader& reader, const XS_String& name) 03313 : _begin(reader, name, false), 03314 _end(reader, name, true) 03315 { 03316 } 03317 03318 /// internal iterator class 03319 struct const_iterator 03320 { 03321 typedef const_iterator myType; 03322 03323 const_iterator(XMLStreamReader& reader, const XS_String& filter_name, bool is_end) 03324 : _reader(reader), 03325 _filter_name(filter_name), 03326 _start_level(reader._level), 03327 _is_end(is_end) 03328 { 03329 search_next(); 03330 } 03331 03332 const XMLStreamReader& operator->() const 03333 { 03334 return _reader; 03335 } 03336 03337 XS_String operator*() const 03338 { 03339 return _reader.str(); 03340 } 03341 03342 myType& operator++() 03343 { 03344 if (!_at_end) 03345 search_next(); 03346 03347 return *this; 03348 } 03349 03350 myType operator++(int) 03351 { 03352 myType ret = *this; 03353 03354 if (!_at_end) 03355 search_next(); 03356 03357 return ret; 03358 } 03359 03360 bool operator==(const myType& other) const 03361 { 03362 if (other._is_end) 03363 return _at_end; 03364 else if (_is_end) 03365 return other._at_end; 03366 else 03367 return _reader.str() == other._reader.str(); 03368 } 03369 03370 bool operator!=(const myType& other) const 03371 { 03372 if (other._is_end) 03373 return !_at_end; 03374 else if (_is_end) 03375 return !other._at_end; 03376 else 03377 return _reader.str() != other._reader.str(); 03378 } 03379 03380 protected: 03381 XMLStreamReader& _reader; 03382 XS_String _filter_name; 03383 int _start_level; 03384 bool _is_end; 03385 bool _at_end; 03386 03387 void search_next() 03388 { 03389 while(!_at_end) { 03390 _reader.next_skip_others(_filter_name); 03391 03392 if (_reader._level == _start_level) 03393 _at_end = true; 03394 } 03395 } 03396 }; 03397 03398 const_iterator begin() 03399 { 03400 return _begin; 03401 } 03402 03403 const_iterator end() 03404 { 03405 return _end; 03406 } 03407 03408 protected: 03409 const_iterator _begin; 03410 const_iterator _end; 03411 }; 03412 03413 03414 /// type converter for boolean data 03415 struct XMLBool 03416 { 03417 XMLBool(bool value=false) 03418 : _value(value) 03419 { 03420 } 03421 03422 XMLBool(LPCXSSTR value, bool def=false) 03423 { 03424 LPCXSSTR p = safe_skip_space(value); 03425 03426 if (*p) 03427 _value = !XS_nicmp(p, XS_TRUE, 4); //_tcslen(XS_TRUE_STR)=4 03428 else 03429 _value = def; 03430 } 03431 03432 XMLBool(const XMLNode* node, const XS_String& attr_name, bool def=false) 03433 { 03434 const XS_String& value = node->get(attr_name); 03435 03436 if (!value.empty()) 03437 _value = !XS_icmp(value.c_str(), XS_TRUE); 03438 else 03439 _value = def; 03440 } 03441 03442 operator bool() const 03443 { 03444 return _value; 03445 } 03446 03447 bool operator!() const 03448 { 03449 return !_value; 03450 } 03451 03452 operator LPCXSSTR() const 03453 { 03454 return _value? XS_TRUE: XS_FALSE; 03455 } 03456 03457 protected: 03458 bool _value; 03459 03460 private: 03461 void operator=(const XMLBool&); // disallow assignment operations 03462 }; 03463 03464 /// type converter for boolean data with write access 03465 struct XMLBoolRef 03466 { 03467 XMLBoolRef(XMLNode* node, const XS_String& attr_name, bool def=false) 03468 : _ref((*node)[attr_name]) 03469 { 03470 if (_ref.empty()) 03471 assign(def); 03472 } 03473 03474 operator bool() const 03475 { 03476 return !XS_icmp(_ref.c_str(), XS_TRUE); 03477 } 03478 03479 bool operator!() const 03480 { 03481 return XS_icmp(_ref.c_str(), XS_TRUE)? true: false; 03482 } 03483 03484 XMLBoolRef& operator=(bool value) 03485 { 03486 assign(value); 03487 03488 return *this; 03489 } 03490 03491 void assign(bool value) 03492 { 03493 _ref.assign(value? XS_TRUE: XS_FALSE); 03494 } 03495 03496 void toggle() 03497 { 03498 assign(!operator bool()); 03499 } 03500 03501 protected: 03502 XS_String& _ref; 03503 }; 03504 03505 03506 /// type converter for integer data 03507 struct XMLInt 03508 { 03509 XMLInt(int value) 03510 : _value(value) 03511 { 03512 } 03513 03514 XMLInt(size_t value) 03515 : _value((int)value) 03516 { 03517 } 03518 03519 XMLInt(LPCXSSTR value, int def=0) 03520 { 03521 LPCXSSTR p = safe_skip_space(value); 03522 03523 if (*p) 03524 _value = XS_toi(p); 03525 else 03526 _value = def; 03527 } 03528 03529 XMLInt(const XMLNode* node, const XS_String& attr_name, int def=0) 03530 { 03531 const XS_String& value = node->get(attr_name); 03532 03533 if (!value.empty()) 03534 _value = XS_toi(value.c_str()); 03535 else 03536 _value = def; 03537 } 03538 03539 operator int() const 03540 { 03541 return _value; 03542 } 03543 03544 operator XS_String() const 03545 { 03546 XS_CHAR buffer[32]; 03547 XS_snprintf(buffer, COUNTOF(buffer), XS_INTFMT, _value); 03548 return XS_String(buffer); 03549 } 03550 03551 protected: 03552 int _value; 03553 03554 private: 03555 void operator=(const XMLInt&); // disallow assignment operations 03556 }; 03557 03558 /// type converter for integer data with write access 03559 struct XMLIntRef 03560 { 03561 XMLIntRef(XMLNode* node, const XS_String& attr_name, int def=0) 03562 : _ref((*node)[attr_name]) 03563 { 03564 if (_ref.empty()) 03565 assign(def); 03566 } 03567 03568 XMLIntRef& operator=(int value) 03569 { 03570 assign(value); 03571 03572 return *this; 03573 } 03574 03575 operator int() const 03576 { 03577 return XS_toi(_ref.c_str()); 03578 } 03579 03580 void assign(int value) 03581 { 03582 XS_CHAR buffer[32]; 03583 XS_snprintf(buffer, COUNTOF(buffer), XS_INTFMT, value); 03584 _ref.assign(buffer); 03585 } 03586 03587 protected: 03588 XS_String& _ref; 03589 }; 03590 03591 03592 /// type converter for integer data 03593 struct XMLInt64 03594 { 03595 XMLInt64(INT64 value) 03596 : _value(value) 03597 { 03598 } 03599 03600 XMLInt64(UINT64 value) 03601 : _value((INT64)value) 03602 { 03603 } 03604 03605 XMLInt64(LPCXSSTR value, INT64 def=0) 03606 { 03607 LPCXSSTR p = safe_skip_space(value); 03608 03609 if (*p) 03610 _value = XS_toi64(p); 03611 else 03612 _value = def; 03613 } 03614 03615 XMLInt64(const XMLNode* node, const XS_String& attr_name, INT64 def=0) 03616 { 03617 const XS_String& value = node->get(attr_name); 03618 03619 if (!value.empty()) 03620 _value = XS_toi64(value.c_str()); 03621 else 03622 _value = def; 03623 } 03624 03625 operator INT64() const 03626 { 03627 return _value; 03628 } 03629 03630 operator XS_String() const 03631 { 03632 XS_CHAR buffer[64]; 03633 XS_snprintf(buffer, COUNTOF(buffer), XS_INT64FMT, _value); 03634 return XS_String(buffer); 03635 } 03636 03637 protected: 03638 INT64 _value; 03639 03640 private: 03641 void operator=(const XMLInt64&); // disallow assignment operations 03642 }; 03643 03644 /// type converter for integer data with write access 03645 struct XMLInt64Ref 03646 { 03647 XMLInt64Ref(XMLNode* node, const XS_String& attr_name, INT64 def=0) 03648 : _ref((*node)[attr_name]) 03649 { 03650 if (_ref.empty()) 03651 assign(def); 03652 } 03653 03654 XMLInt64Ref& operator=(INT64 value) 03655 { 03656 assign(value); 03657 03658 return *this; 03659 } 03660 03661 operator INT64() const 03662 { 03663 return XS_toi64(_ref.c_str()); 03664 } 03665 03666 void assign(INT64 value) 03667 { 03668 XS_CHAR buffer[64]; 03669 XS_snprintf(buffer, COUNTOF(buffer), XS_INT64FMT, value); 03670 _ref.assign(buffer); 03671 } 03672 03673 protected: 03674 XS_String& _ref; 03675 }; 03676 03677 03678 /// type converter for numeric data 03679 struct XMLDouble 03680 { 03681 XMLDouble(double value) 03682 : _value(value) 03683 { 03684 } 03685 03686 XMLDouble(LPCXSSTR value, double def=0.) 03687 { 03688 LPCXSSTR p = safe_skip_space(value); 03689 LPTSTR end; 03690 03691 if (*p) 03692 _value = XS_tod(p, &end); 03693 else 03694 _value = def; 03695 } 03696 03697 XMLDouble(const XMLNode* node, const XS_String& attr_name, double def=0.) 03698 { 03699 LPTSTR end; 03700 const XS_String& value = node->get(attr_name); 03701 03702 if (!value.empty()) 03703 _value = XS_tod(value.c_str(), &end); 03704 else 03705 _value = def; 03706 } 03707 03708 operator double() const 03709 { 03710 return _value; 03711 } 03712 03713 operator XS_String() const 03714 { 03715 XS_CHAR buffer[32]; 03716 XS_snprintf(buffer, COUNTOF(buffer), XS_FLOATFMT, _value); 03717 return XS_String(buffer); 03718 } 03719 03720 protected: 03721 double _value; 03722 03723 private: 03724 void operator=(const XMLDouble&); // disallow assignment operations 03725 }; 03726 03727 /// type converter for numeric data with write access 03728 struct XMLDoubleRef 03729 { 03730 XMLDoubleRef(XMLNode* node, const XS_String& attr_name, double def=0.) 03731 : _ref((*node)[attr_name]) 03732 { 03733 if (_ref.empty()) 03734 assign(def); 03735 } 03736 03737 XMLDoubleRef& operator=(double value) 03738 { 03739 assign(value); 03740 03741 return *this; 03742 } 03743 03744 operator double() const 03745 { 03746 LPTSTR end; 03747 return XS_tod(_ref.c_str(), &end); 03748 } 03749 03750 void assign(double value) 03751 { 03752 XS_CHAR buffer[32]; 03753 XS_snprintf(buffer, COUNTOF(buffer), XS_FLOATFMT, value); 03754 _ref.assign(buffer); 03755 } 03756 03757 protected: 03758 XS_String& _ref; 03759 }; 03760 03761 03762 /// type converter for string data 03763 struct XMLString 03764 { 03765 XMLString(const XS_String& value) 03766 : _value(value) 03767 { 03768 } 03769 03770 XMLString(LPCXSSTR value, LPCXSSTR def=XS_EMPTY) 03771 { 03772 if (value && *value) 03773 _value = value; 03774 else 03775 _value = def; 03776 } 03777 03778 XMLString(const XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_EMPTY) 03779 { 03780 const XS_String& value = node->get(attr_name); 03781 03782 if (!value.empty()) 03783 _value = value; 03784 else 03785 _value = def; 03786 } 03787 03788 operator const XS_String&() const 03789 { 03790 return _value; 03791 } 03792 03793 const XS_String& c_str() const 03794 { 03795 return _value; 03796 } 03797 03798 protected: 03799 XS_String _value; 03800 03801 private: 03802 void operator=(const XMLString&); // disallow assignment operations 03803 }; 03804 03805 /// type converter for string data with write access 03806 struct XMLStringRef 03807 { 03808 XMLStringRef(XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_EMPTY) 03809 : _ref((*node)[attr_name]) 03810 { 03811 if (_ref.empty()) 03812 assign(def); 03813 } 03814 03815 XMLStringRef(const XS_String& node_name, XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_EMPTY) 03816 : _ref(node->subvalue(node_name, attr_name)) 03817 { 03818 if (_ref.empty()) 03819 assign(def); 03820 } 03821 03822 XMLStringRef& operator=(const XS_String& value) 03823 { 03824 assign(value); 03825 03826 return *this; 03827 } 03828 03829 operator const XS_String&() const 03830 { 03831 return _ref; 03832 } 03833 03834 void assign(const XS_String& value) 03835 { 03836 _ref.assign(value); 03837 } 03838 03839 protected: 03840 XS_String& _ref; 03841 }; 03842 03843 03844 // read option (for example configuration) values from XML node attributes 03845 template<typename T> 03846 inline void read_option(T& var, const_XMLPos& cfg, LPCXSSTR key) 03847 { 03848 const XS_String& val = cfg.get(key); 03849 03850 if (!val.empty()) 03851 var = val; 03852 } 03853 03854 // read integer option values from XML node attributes 03855 template<> 03856 inline void read_option(int& var, const_XMLPos& cfg, LPCXSSTR key) 03857 { 03858 const XS_String& val = cfg.get(key); 03859 03860 if (!val.empty()) 03861 var = XS_toi(val.c_str()); 03862 } 03863 03864 03865 inline void XMLPos::set_property(const XS_String& key, int value, const XS_String& name) 03866 { 03867 smart_create(name, XS_KEY, key); 03868 XMLIntRef(_cur, XS_VALUE) = value; 03869 back(); 03870 } 03871 03872 inline void XMLPos::set_property(const XS_String& key, double value, const XS_String& name) 03873 { 03874 smart_create(name, XS_KEY, key); 03875 XMLDoubleRef(_cur, XS_VALUE) = value; 03876 back(); 03877 } 03878 03879 inline void XMLPos::set_property(const XS_String& key, const XS_String& value, const XS_String& name) 03880 { 03881 smart_create(name, XS_KEY, key); 03882 put(XS_VALUE, value); 03883 back(); 03884 } 03885 03886 inline void XMLPos::set_property(const XS_String& key, const XMLBool& value, const XS_String& name) 03887 { 03888 smart_create(name, XS_KEY, key); 03889 XMLBoolRef(_cur, XS_VALUE) = value; 03890 back(); 03891 } 03892 03893 03894 /// a key/value pair for property data access 03895 struct XMLProperty { 03896 XMLProperty(const XMLNode* node) 03897 : _key(node->get(XS_KEY)), 03898 _value(node->get(XS_VALUE)) 03899 { 03900 } 03901 03902 XS_String _key; 03903 XS_String _value; 03904 }; 03905 03906 03907 /// utility class to read property settings from a XML tree 03908 struct XMLPropertyReader 03909 { 03910 XMLPropertyReader(const XMLNode::Children& children) 03911 : _filter(children, XS_PROPERTY), 03912 _begin(_filter.begin(), _filter.end()), 03913 _end(_filter.end(), _filter.end()) 03914 { 03915 } 03916 03917 XMLPropertyReader(const XMLNode* node) 03918 : _filter(node, XS_PROPERTY), 03919 _begin(_filter.begin(), _filter.end()), 03920 _end(_filter.end(), _filter.end()) 03921 { 03922 } 03923 03924 /// internal iterator class 03925 struct const_iterator 03926 { 03927 typedef const_XMLChildrenFilter::const_iterator BaseIterator; 03928 typedef const_iterator myType; 03929 03930 const_iterator(BaseIterator begin, BaseIterator end) 03931 : _cur(begin), 03932 _end(end) 03933 { 03934 } 03935 03936 operator BaseIterator() 03937 { 03938 return _cur; 03939 } 03940 03941 XMLProperty operator*() const 03942 { 03943 return XMLProperty(*_cur); 03944 } 03945 03946 const XMLNode* get_node() const 03947 { 03948 return *_cur; 03949 } 03950 03951 myType& operator++() 03952 { 03953 ++_cur; 03954 03955 return *this; 03956 } 03957 03958 myType operator++(int) 03959 { 03960 myType ret = *this; 03961 03962 ++_cur; 03963 03964 return ret; 03965 } 03966 03967 bool operator==(const myType& other) const 03968 { 03969 return _cur == other._cur; 03970 } 03971 03972 bool operator!=(const myType& other) const 03973 { 03974 return _cur != other._cur; 03975 } 03976 03977 protected: 03978 BaseIterator _cur; 03979 BaseIterator _end; 03980 }; 03981 03982 const_iterator begin() 03983 { 03984 return _begin; 03985 } 03986 03987 const_iterator end() 03988 { 03989 return _end; 03990 } 03991 03992 protected: 03993 const_XMLChildrenFilter _filter; 03994 03995 const_iterator _begin; 03996 const_iterator _end; 03997 }; 03998 03999 04000 /// XML message wrapper 04001 struct XMLMessage : public XMLDoc 04002 { 04003 XMLMessage(const char* name) 04004 : _pos(this) 04005 { 04006 _pos.create(name); 04007 } 04008 04009 std::string toString() const 04010 { 04011 std::ostringstream out; 04012 04013 write(out); 04014 04015 return out.str(); 04016 } 04017 04018 XMLPos _pos; 04019 04020 protected: 04021 XMLMessage() 04022 : _pos(this) 04023 { 04024 } 04025 }; 04026 04027 04028 /// helper structure to read XML messages from strings 04029 struct XMLMessageFromString : public XMLMessage 04030 { 04031 XMLMessageFromString(const std::string& xml_str, const std::string& system_id=std::string()) 04032 { 04033 read_buffer(xml_str.c_str(), xml_str.length(), system_id); 04034 } 04035 }; 04036 04037 04038 /// Reader for XML Messages 04039 struct XMLMessageReader : public XMLPos 04040 { 04041 XMLMessageReader(const std::string& xml_str, const std::string& system_id=std::string()) 04042 : XMLPos(&_msg) 04043 { 04044 _msg.read_buffer(xml_str.c_str(), xml_str.length(), system_id); 04045 } 04046 04047 const XMLDoc& get_document() 04048 { 04049 return _msg; 04050 } 04051 04052 protected: 04053 XMLDoc _msg; 04054 }; 04055 04056 04057 /// on the fly XML writer 04058 struct XMLWriter 04059 { 04060 XMLWriter(std::ostream& out, const XMLFormat& format=XMLFormat()) 04061 : _pofstream(NULL), 04062 _out(out), 04063 _format(format) 04064 { 04065 format.print_header(_out, false); // _format._endl is printed in write_pre() 04066 } 04067 04068 XMLWriter(FILE* pFile, const XMLFormat& format=XMLFormat()) 04069 : _pofstream(new tofstream(pFile)), 04070 _out(*_pofstream), 04071 _format(format) 04072 { 04073 format.print_header(_out, false); // _format._endl is printed in write_pre() 04074 } 04075 04076 XMLWriter(LPCTSTR path, const XMLFormat& format=XMLFormat()) 04077 : _pofstream(new tofstream(path)), 04078 _out(*_pofstream), 04079 _format(format) 04080 { 04081 format.print_header(_out, false); // _format._endl is printed in write_pre() 04082 } 04083 04084 ~XMLWriter() 04085 { 04086 _out << _format._endl; 04087 delete _pofstream; 04088 } 04089 04090 bool good() const 04091 { 04092 return _out.good(); 04093 } 04094 04095 /// create node and move to it 04096 void create(const XS_String& name); 04097 04098 /// go back to previous position 04099 bool back(); 04100 04101 /// attribute setting 04102 void put(const XS_String& attr_name, const XS_String& value) 04103 { 04104 if (!_stack.empty()) 04105 _stack.top()._attributes[attr_name] = value; 04106 } 04107 04108 /// index operator write access to an attribute 04109 XS_String& operator[](const XS_String& attr_name) 04110 { 04111 if (_stack.empty()) 04112 return s_empty_attr; 04113 04114 return _stack.top()._attributes[attr_name]; 04115 } 04116 04117 void set_attributes(const XMLNode::AttributeMap& attrs) 04118 { 04119 if (!_stack.empty()) 04120 _stack.top()._attributes = attrs; 04121 } 04122 04123 /// set element node content 04124 void set_content(const XS_String& s, bool cdata=false) 04125 { 04126 if (!_stack.empty()) 04127 _stack.top()._content = EncodeXMLString(s.c_str(), cdata); 04128 } 04129 04130 /// set element node content from encoded string 04131 void set_encoded_content(const std::string& s) 04132 { 04133 if (!_stack.empty()) 04134 _stack.top()._content = s; 04135 } 04136 04137 /// create node with string content 04138 void create_node_content(const XS_String& node_name, const XS_String& content) 04139 { 04140 create(node_name); 04141 set_content(content); 04142 back(); 04143 } 04144 04145 /// direct string output 04146 void write(const std::string& s); 04147 04148 // public for access in StackEntry 04149 enum WRITESTATE { 04150 NOTHING, /*PRE,*/ ATTRIBUTES, PRE_CLOSED, /*CONTENT,*/ POST 04151 }; 04152 04153 protected: 04154 tofstream* _pofstream; 04155 std::ostream& _out; 04156 XMLFormat _format; 04157 04158 typedef XMLNode::AttributeMap AttrMap; 04159 04160 /// container for XMLWriter state information 04161 struct StackEntry { 04162 XS_String _node_name; 04163 AttrMap _attributes; 04164 std::string _content; 04165 WRITESTATE _state; 04166 bool _children; 04167 04168 StackEntry() : _state(NOTHING), _children(false) {} 04169 }; 04170 04171 std::stack<StackEntry> _stack; 04172 04173 static XS_String s_empty_attr; 04174 04175 void close_pre(StackEntry& entry); 04176 void write_pre(StackEntry& entry); 04177 void write_attributes(StackEntry& entry); 04178 void write_post(StackEntry& entry); 04179 }; 04180 04181 04182 } // namespace XMLStorage 04183 04184 #ifdef _MSC_VER 04185 #pragma warning(pop) // C4512: assignment operator could not be generated 04186 #endif 04187 04188 #define _XMLSTORAGE_H 04189 #endif // _XMLSTORAGE_H
ROS Explorer Source Code Documentation
generated on 02.01.2013 by |