3 // XML storage classes Version 1.1
5 // Copyright (c) 2004, 2005, 2006 Martin Fuchs <martin-fuchs@gmx.net>
9 /// XMLStorage header file
16 Redistribution and use in source and binary forms, with or without
17 modification, are permitted provided that the following conditions are met:
19 * Redistributions of source code must retain the above copyright
20 notice, this list of conditions and the following disclaimer.
21 * Redistributions in binary form must reproduce the above copyright
22 notice, this list of conditions and the following disclaimer in
23 the documentation and/or other materials provided with the
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
30 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 POSSIBILITY OF SUCH DAMAGE.
44 #ifndef _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES
45 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
46 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 1
47 #define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 1
55 #ifndef XS_STRING_UTF8
56 #define XS_STRING_UTF8
60 #include <xercesc/parsers/SAXParser.hpp>
61 #include <xercesc/sax/HandlerBase.hpp>
63 using XERCES_CPP_NAMESPACE_QUALIFIER Locator
;
64 using XERCES_CPP_NAMESPACE_QUALIFIER SAXParser
;
65 using XERCES_CPP_NAMESPACE_QUALIFIER HandlerBase
;
66 using XERCES_CPP_NAMESPACE_QUALIFIER InputSource
;
67 using XERCES_CPP_NAMESPACE_QUALIFIER AttributeList
;
68 using XERCES_CPP_NAMESPACE_QUALIFIER SAXParseException
;
70 typedef XMLCh XML_Char
;
72 #elif defined(XS_USE_EXPAT)
74 #include <expat/expat.h>
80 #pragma warning(disable: 4786)
86 #pragma comment(lib, "xerces-c_2D")
88 #pragma comment(lib, "xerces-c_2")
90 #elif defined(XS_USE_EXPAT)
93 #pragma comment(lib, "libexpatMT")
96 #pragma comment(lib, "libexpat")
100 #ifndef _STRING_DEFINED // _STRING_DEFINED only allowed if using xmlstorage.cpp embedded in the project
101 #if defined(_DEBUG) && defined(_DLL) // DEBUG version only supported with MSVCRTD
103 #pragma comment(lib, "xmlstorage-vc8d")
105 #pragma comment(lib, "xmlstorage-vc6d")
110 #pragma comment(lib, "xmlstorage-vc8")
112 #pragma comment(lib, "xmlstorage-vc6")
116 #pragma comment(lib, "xmlstorage-vc8t")
118 #pragma comment(lib, "xmlstorage-vc6t")
121 // -ML is no more supported by VS2005.
122 #pragma comment(lib, "xmlstorage-vc6l")
125 #endif // _STRING_DEFINED
127 #endif // XS_NO_COMMENT
142 #include <windows.h> // for LPCTSTR
156 #define BUFFER_LEN 2048
160 namespace XMLStorage
{
165 #ifdef XS_STRING_UTF8
168 #define LPXSSTR LPSTR
169 #define LPCXSSTR LPCSTR
170 #define XS_cmp strcmp
171 #define XS_icmp stricmp
172 #define XS_ncmp strncmp
173 #define XS_nicmp strnicmp
175 #define XS_tod strtod
176 #define XS_len strlen
177 #define XS_snprintf _snprintf
178 #define XS_vsnprintf _vsnprintf
179 #define XS_strstr strstr
181 #define XS_CHAR TCHAR
182 #define XS_TEXT(x) TEXT(x)
183 #define LPXSSTR LPTSTR
184 #define LPCXSSTR LPCTSTR
185 #define XS_cmp _tcscmp
186 #define XS_icmp _tcsicmp
187 #define XS_ncmp _tcsncmp
188 #define XS_nicmp _tcsnicmp
190 #define XS_tod _tcstod
191 #define XS_len _tcslen
192 #define XS_snprintf _sntprintf
193 #define XS_vsnprintf _vsntprintf
194 #define XS_strstr _tcsstr
199 #define COUNTOF _countof
201 #define COUNTOF(b) (sizeof(b)/sizeof(b[0]))
206 int inline isxmlsym(unsigned char c
)
208 return isalnum(c
) || c
=='_' || c
=='-';
212 #if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8)
214 #define XS_String String
216 #else // _STRING_DEFINED, !XS_STRING_UTF8
218 /// string class for TCHAR strings
221 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
222 : public std::wstring
227 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
228 typedef std::wstring super
;
230 typedef std::string super
;
235 XS_String(LPCXSSTR s
) {if (s
) super::assign(s
);}
236 XS_String(LPCXSSTR s
, size_t l
) : super(s
, l
) {}
238 XS_String(const super
& other
) : super(other
) {}
239 XS_String(const XS_String
& other
) : super(other
) {}
241 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
242 XS_String(LPCSTR s
) {assign(s
);}
243 XS_String(LPCSTR s
, size_t l
) {assign(s
, l
);}
244 XS_String(const std::string
& other
) {assign(other
.c_str());}
245 XS_String
& operator=(LPCSTR s
) {assign(s
); return *this;}
246 void assign(LPCSTR s
) {if (s
) {size_t bl
=strlen(s
); LPWSTR b
=(LPWSTR
)alloca(sizeof(WCHAR
)*bl
); super::assign(b
, MultiByteToWideChar(CP_ACP
, 0, s
, bl
, b
, bl
));} else erase();}
247 void assign(LPCSTR s
, size_t l
) {if (s
) {size_t bl
=l
; LPWSTR b
=(LPWSTR
)alloca(sizeof(WCHAR
)*bl
); super::assign(b
, MultiByteToWideChar(CP_ACP
, 0, s
, l
, b
, bl
));} else erase();}
249 XS_String(LPCWSTR s
) {assign(s
);}
250 XS_String(LPCWSTR s
, size_t l
) {assign(s
, l
);}
251 XS_String(const std::wstring
& other
) {assign(other
.c_str());}
252 XS_String
& operator=(LPCWSTR s
) {assign(s
); return *this;}
253 #ifdef XS_STRING_UTF8
254 void assign(const XS_String
& s
) {assign(s
.c_str());}
255 void assign(LPCWSTR s
) {if (s
) {size_t bl
=wcslen(s
); LPSTR b
=(LPSTR
)alloca(bl
); super::assign(b
, WideCharToMultiByte(CP_UTF8
, 0, s
, (int)bl
, b
, (int)bl
, 0, 0));} else erase();}
256 void assign(LPCWSTR s
, size_t l
) {size_t bl
=l
; if (s
) {LPSTR b
=(LPSTR
)alloca(bl
); super::assign(b
, WideCharToMultiByte(CP_UTF8
, 0, s
, (int)l
, b
, (int)bl
, 0, 0));} else erase();}
257 #else // if !UNICODE && !XS_STRING_UTF8
258 void assign(LPCWSTR s
) {if (s
) {size_t bl
=wcslen(s
); LPSTR b
=(LPSTR
)alloca(bl
); super::assign(b
, WideCharToMultiByte(CP_ACP
, 0, s
, (int)bl
, b
, (int)bl
, 0, 0));} else erase();}
259 void assign(LPCWSTR s
, size_t l
) {size_t bl
=l
; if (s
) {LPSTR b
=(LPSTR
)alloca(bl
); super::assign(b
, WideCharToMultiByte(CP_ACP
, 0, s
, (int)l
, b
, (int)bl
, 0, 0));} else erase();}
263 XS_String
& operator=(LPCXSSTR s
) {if (s
) super::assign(s
); else erase(); return *this;}
264 XS_String
& operator=(const super
& s
) {super::assign(s
); return *this;}
265 void assign(LPCXSSTR s
) {super::assign(s
);}
266 void assign(LPCXSSTR s
, size_t l
) {super::assign(s
, l
);}
268 operator LPCXSSTR() const {return c_str();}
270 #ifdef XS_STRING_UTF8
271 operator std::wstring() const {size_t bl
=length(); LPWSTR b
=(LPWSTR
)alloca(sizeof(WCHAR
)*bl
); return std::wstring(b
, MultiByteToWideChar(CP_UTF8
, 0, c_str(), bl
, b
, bl
));}
272 #elif defined(UNICODE)
273 operator std::string() const {size_t bl
=length(); LPSTR b
=(LPSTR
)alloca(bl
); return std::string(b
, WideCharToMultiByte(CP_ACP
, 0, c_str(), bl
, b
, bl
, 0, 0));}
275 operator std::wstring() const {size_t bl
=length(); LPWSTR b
=(LPWSTR
)alloca(sizeof(WCHAR
)*bl
); return std::wstring(b
, MultiByteToWideChar(CP_ACP
, 0, c_str(), (int)bl
, b
, (int)bl
));}
278 XS_String
& printf(LPCXSSTR fmt
, ...)
281 XS_CHAR b
[BUFFER_LEN
];
284 super::assign(b
, XS_vsnprintf(b
, COUNTOF(b
), fmt
, l
));
290 XS_String
& vprintf(LPCXSSTR fmt
, va_list l
)
292 XS_CHAR b
[BUFFER_LEN
];
294 super::assign(b
, XS_vsnprintf(b
, COUNTOF(b
), fmt
, l
));
299 XS_String
& appendf(LPCXSSTR fmt
, ...)
302 XS_CHAR b
[BUFFER_LEN
];
305 super::append(b
, XS_vsnprintf(b
, COUNTOF(b
), fmt
, l
));
311 XS_String
& vappendf(LPCXSSTR fmt
, va_list l
)
313 XS_CHAR b
[BUFFER_LEN
];
315 super::append(b
, XS_vsnprintf(b
, COUNTOF(b
), fmt
, l
));
321 #endif // _STRING_DEFINED, !XS_STRING_UTF8
326 #define XS_EMPTY_STR XS_TEXT("")
327 #define XS_TRUE_STR XS_TEXT("true")
328 #define XS_FALSE_STR XS_TEXT("false")
329 #define XS_INTFMT_STR XS_TEXT("%d")
330 #define XS_FLOATFMT_STR XS_TEXT("%f")
332 // work around GCC's wide string constant bug
334 extern const LPCXSSTR XS_EMPTY
;
335 extern const LPCXSSTR XS_TRUE
;
336 extern const LPCXSSTR XS_FALSE
;
337 extern const LPCXSSTR XS_INTFMT
;
338 extern const LPCXSSTR XS_FLOATFMT
;
340 #define XS_EMPTY XS_EMPTY_STR
341 #define XS_TRUE XS_TRUE_STR
342 #define XS_FALSE XS_FALSE_STR
343 #define XS_INTFMT XS_INTFMT_STR
344 #define XS_FLOATFMT XS_FLOATFMT_STR
348 #ifndef XS_STRING_UTF8
350 // from UTF-8 to XS internal string encoding
351 inline void assign_utf8(XS_String
& s
, const char* str
, size_t lutf8
)
354 LPTSTR buffer
= (LPTSTR
)alloca(sizeof(TCHAR
)*lutf8
);
355 int l
= MultiByteToWideChar(CP_UTF8
, 0, str
, (int)lutf8
, buffer
, (int)lutf8
);
357 LPWSTR wbuffer
= (LPWSTR
)alloca(sizeof(WCHAR
)*lutf8
);
358 int l
= MultiByteToWideChar(CP_UTF8
, 0, str
, (int)lutf8
, wbuffer
, (int)lutf8
);
360 int bl
=2*l
; LPSTR buffer
= (LPSTR
)alloca(bl
);
361 l
= WideCharToMultiByte(CP_ACP
, 0, wbuffer
, l
, buffer
, bl
, 0, 0);
367 // from UTF-8 to XS internal string encoding
368 inline void assign_utf8(XS_String
& s
, const char* str
)
370 assign_utf8(s
, str
, strlen(str
));
373 // from XS internal string encoding to UTF-8
374 inline std::string
get_utf8(LPCTSTR s
, size_t l
)
377 size_t bl
=2*l
; LPSTR buffer
= (LPSTR
)alloca(bl
);
378 l
= WideCharToMultiByte(CP_UTF8
, 0, s
, (int)l
, buffer
, (int)bl
, 0, 0);
380 LPWSTR wbuffer
= (LPWSTR
)alloca(sizeof(WCHAR
)*l
);
381 l
= MultiByteToWideChar(CP_ACP
, 0, s
, (int)l
, wbuffer
, (int)l
);
383 size_t bl
=2*l
; LPSTR buffer
= (LPSTR
)alloca(bl
);
384 l
= WideCharToMultiByte(CP_UTF8
, 0, wbuffer
, (int)l
, buffer
, (int)bl
, 0, 0);
387 return std::string(buffer
, l
);
391 // from XS internal string encoding to UTF-8
392 inline std::string
get_utf8(const char* s
, size_t l
)
394 LPWSTR wbuffer
= (LPWSTR
)alloca(sizeof(WCHAR
)*l
);
395 l
= MultiByteToWideChar(CP_ACP
, 0, s
, (int)l
, wbuffer
, (int)l
);
397 size_t bl
=2*l
; LPSTR buffer
= (LPSTR
)alloca(bl
);
398 l
= WideCharToMultiByte(CP_UTF8
, 0, wbuffer
, (int)l
, buffer
, (int)bl
, 0, 0);
400 return std::string(buffer
, l
);
404 // from XS internal string encoding to UTF-8
405 inline std::string
get_utf8(const XS_String
& s
)
407 return get_utf8(s
.c_str(), s
.length());
410 #endif // XS_STRING_UTF8
412 extern std::string
EncodeXMLString(const XS_String
& str
);
413 extern XS_String
DecodeXMLString(const XS_String
& str
);
417 #include <ext/stdio_filebuf.h>
418 typedef __gnu_cxx::stdio_filebuf
<char> STDIO_FILEBUF
;
420 typedef std::filebuf STDIO_FILEBUF
;
423 /// base class for XMLStorage::tifstream and XMLStorage::tofstream
426 FileHolder(LPCTSTR path
, LPCTSTR mode
)
428 #ifdef __STDC_WANT_SECURE_LIB__ // secure CRT functions using VS 2005
429 if (_tfopen_s(&_pfile
, path
, mode
) != 0)
432 _pfile
= _tfopen(path
, mode
);
446 /// input file stream with ANSI/UNICODE file names
447 struct tifstream
: public std::istream
, FileHolder
449 typedef std::istream super
;
451 tifstream(LPCTSTR path
)
453 FileHolder(path
, TEXT("rb")), // binary mode is important for XMLReader::read_buffer() with MinGW libraries
455 _buf(_pfile
, std::ios::in
)
466 /// output file stream with ANSI/UNICODE file names
467 struct tofstream
: public std::ostream
, FileHolder
469 typedef std::ostream super
;
471 tofstream(LPCTSTR path
)
473 FileHolder(path
, TEXT("wb")),
475 _buf(_pfile
, std::ios::out
)
492 // write XML files with 2 spaces indenting
493 #define XML_INDENT_SPACE " "
496 #if defined(XS_USE_XERCES) || defined(XS_USE_EXPAT)
498 #if defined(XML_UNICODE)/*Expat*/ || defined(XS_USE_XERCES)/*Xerces*/ // Are Expat/Xerces XML strings UTF-16 encoded?
499 typedef XS_String String_from_XML_Char
;
501 #elif defined(XS_STRING_UTF8)
502 typedef XS_String String_from_XML_Char
;
506 /// converter from Expat/Xerces strings to XMLStorage internal strings
507 struct String_from_XML_Char
: public XS_String
509 String_from_XML_Char(const XML_Char
* str
)
511 assign_utf8(*this, str
);
517 #endif // defined(XS_USE_XERCES) || defined(XS_USE_EXPAT)
520 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
522 // optimization for faster UNICODE/ASCII string comparison without temporary A/U conversion
523 inline bool operator==(const XS_String
& s1
, const char* s2
)
526 const unsigned char* q
= (const unsigned char*)s2
;
538 /// XML Error with message and location
548 std::string
str() const;
549 friend std::ostream
& operator<<(std::ostream
&, const XMLError
& err
);
558 /// list of XMLError entries
559 struct XMLErrorList
: public std::list
<XMLError
>
561 XS_String
str() const;
565 #ifdef XMLNODE_LOCATION
566 /// location of XML Node including XML file name
570 : _pdisplay_path(NULL
),
576 XMLLocation(const char* display_path
, int line
, int column
)
577 : _pdisplay_path(display_path
),
583 std::string
str() const;
586 const char* _pdisplay_path
; // character pointer for fast reference
600 /// XML Stylesheet entry
603 std::string _href
; // CDATA #REQUIRED
604 std::string _type
; // CDATA #REQUIRED
605 std::string _title
; // CDATA #IMPLIED
606 std::string _media
; // CDATA #IMPLIED
607 std::string _charset
; // CDATA #IMPLIED
608 bool _alternate
; // (yes|no) "no"
610 StyleSheet() : _alternate(false) {}
612 StyleSheet(const std::string
& href
, const std::string
& type
="text/xsl", bool alternate
=false)
615 _alternate(alternate
)
619 bool empty() const {return _href
.empty();}
620 void print(std::ostream
& out
) const;
623 /// list of StyleSheet entries
624 struct StyleSheetList
: public std::list
<StyleSheet
>
626 void set(const StyleSheet
& stylesheet
)
629 push_back(stylesheet
);
634 /// XML document type description
639 // External Document Types are noted, but not parsed.
643 // Internal DTDs are not supported.
645 void parse(const char* str
);
646 bool empty() const {return _name
.empty();}
649 /// Management of XML file headers and formating
652 XMLFormat(PRETTY_FLAGS pretty
=PRETTY_INDENT
, const std::string
& xml_version
="1.0", const std::string
& encoding
="utf-8", const DocType
& doctype
=DocType())
655 _version(xml_version
),
662 void print_header(std::ostream
& out
, bool lf
=true) const;
664 PRETTY_FLAGS _pretty
;
665 const char* _endl
; // line ending string: "\n" or "\r\n"
667 std::string _version
;
668 std::string _encoding
;
672 StyleSheetList _stylesheets
;
674 // std::string _additional;
681 FORMAT_PLAIN
, /// write XML without any white space
682 FORMAT_SMART
, /// preserve original white space and comments if present; pretty print otherwise
683 FORMAT_ORIGINAL
, /// write XML stream preserving original white space and comments
684 FORMAT_PRETTY
/// pretty print node to stream without preserving original white space
688 /// in memory representation of an XML node
689 struct XMLNode
: public XS_String
691 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
692 /// map of XML node attributes
693 // optimized read access without temporary A/U conversion when using ASCII attribute names
694 struct AttributeMap
: public std::map
<XS_String
, XS_String
>
696 typedef std::map
<XS_String
, XS_String
> super
;
698 const_iterator
find(const char* x
) const
700 for(const_iterator it
=begin(); it
!=end(); ++it
)
707 const_iterator
find(const key_type
& x
) const
709 return super::find(x
);
712 iterator
find(const key_type
& x
)
714 return super::find(x
);
717 XS_String
get(const char* x
, LPXSSTR def
=XS_EMPTY_STR
) const
719 const_iterator found
= find(x
);
722 return found
->second
;
728 /// map of XML node attributes
729 struct AttributeMap
: public std::map
<XS_String
, XS_String
>
731 XS_String
get(const char* x
, LPXSSTR def
=XS_EMPTY_STR
) const
733 const_iterator found
= find(x
);
736 return found
->second
;
743 /// internal children node list
744 struct Children
: public std::list
<XMLNode
*>
746 void assign(const Children
& other
)
750 for(Children::const_iterator it
=other
.begin(); it
!=other
.end(); ++it
)
751 push_back(new XMLNode(**it
));
757 XMLNode
* node
= back();
766 // access to protected class members for XMLPos and XMLReader
767 friend struct XMLPos
;
768 friend struct const_XMLPos
;
769 friend struct XMLReaderBase
;
771 XMLNode(const XS_String
& name
)
776 XMLNode(const XS_String
& name
, const std::string
& leading
)
782 XMLNode(const XMLNode
& other
)
784 _attributes(other
._attributes
),
785 _leading(other
._leading
),
786 _content(other
._content
),
787 _end_leading(other
._end_leading
),
788 _trailing(other
._trailing
)
789 #ifdef XMLNODE_LOCATION
790 , _location(other
._location
)
793 for(Children::const_iterator it
=other
._children
.begin(); it
!=other
._children
.end(); ++it
)
794 _children
.push_back(new XMLNode(**it
));
799 while(!_children
.empty()) {
800 delete _children
.back();
801 _children
.pop_back();
809 _end_leading
.erase();
818 XMLNode
& operator=(const XMLNode
& other
)
820 _children
.assign(other
._children
);
822 _attributes
= other
._attributes
;
824 _leading
= other
._leading
;
825 _content
= other
._content
;
826 _end_leading
= other
._end_leading
;
827 _trailing
= other
._trailing
;
832 /// add a new child node
833 void add_child(XMLNode
* child
)
835 _children
.push_back(child
);
838 /// write access to an attribute
839 void put(const XS_String
& attr_name
, const XS_String
& value
)
841 _attributes
[attr_name
] = value
;
844 /// C++ write access to an attribute
845 XS_String
& operator[](const XS_String
& attr_name
)
847 return _attributes
[attr_name
];
850 /// read only access to an attribute
851 template<typename T
> XS_String
get(const T
& attr_name
, LPXSSTR def
=XS_EMPTY_STR
) const
853 AttributeMap::const_iterator found
= _attributes
.find(attr_name
);
855 if (found
!= _attributes
.end())
856 return found
->second
;
861 /// convenient value access in children node
862 XS_String
subvalue(const XS_String
& name
, const XS_String
& attr_name
, int n
=0) const
864 const XMLNode
* node
= find(name
, n
);
867 return node
->get(attr_name
);
872 /// convenient storage of distinct values in children node
873 XS_String
& subvalue(const XS_String
& name
, const XS_String
& attr_name
, int n
=0)
875 XMLNode
* node
= find(name
, n
);
878 node
= new XMLNode(name
);
882 return (*node
)[attr_name
];
885 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
886 /// convenient value access in children node
887 XS_String
subvalue(const char* name
, const char* attr_name
, int n
=0) const
889 const XMLNode
* node
= find(name
, n
);
892 return node
->get(attr_name
);
897 /// convenient storage of distinct values in children node
898 XS_String
& subvalue(const char* name
, const XS_String
& attr_name
, int n
=0)
900 XMLNode
* node
= find(name
, n
);
903 node
= new XMLNode(name
);
907 return (*node
)[attr_name
];
911 const Children
& get_children() const
916 Children
& get_children()
921 const AttributeMap
& get_attributes() const
926 AttributeMap
& get_attributes()
931 XS_String
get_content() const
933 #ifdef XS_STRING_UTF8
934 const XS_String
& ret
= _content
;
937 assign_utf8(ret
, _content
.c_str(), _content
.length());
940 return DecodeXMLString(ret
.c_str());
943 void set_content(const XS_String
& s
)
945 _content
.assign(EncodeXMLString(s
.c_str()));
948 #ifdef XMLNODE_LOCATION
949 const XMLLocation
& get_location() const {return _location
;}
952 /// write node with children tree to output stream
953 std::ostream
& write(std::ostream
& out
, const XMLFormat
& format
, WRITE_MODE mode
=FORMAT_SMART
, int indent
=0) const
957 plain_write_worker(out
);
961 pretty_write_worker(out
, format
, indent
);
964 case FORMAT_ORIGINAL
:
965 write_worker(out
, indent
);
968 default: // FORMAT_SMART
969 smart_write_worker(out
, format
, indent
);
977 AttributeMap _attributes
;
979 std::string _leading
; // UTF-8 encoded
980 std::string _content
; // UTF-8 and entity encoded, may contain CDATA sections; decode with DecodeXMLString()
981 std::string _end_leading
; // UTF-8 encoded
982 std::string _trailing
; // UTF-8 encoded
984 #ifdef XMLNODE_LOCATION
985 XMLLocation _location
;
988 XMLNode
* get_first_child() const
990 if (!_children
.empty())
991 return _children
.front();
996 XMLNode
* find(const XS_String
& name
, int n
=0) const
998 for(Children::const_iterator it
=_children
.begin(); it
!=_children
.end(); ++it
)
1006 XMLNode
* find(const XS_String
& name
, const XS_String
& attr_name
, const XS_String
& attr_value
, int n
=0) const
1008 for(Children::const_iterator it
=_children
.begin(); it
!=_children
.end(); ++it
) {
1009 const XMLNode
& node
= **it
;
1011 if (node
==name
&& node
.get(attr_name
)==attr_value
)
1019 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
1020 XMLNode
* find(const char* name
, int n
=0) const
1022 for(Children::const_iterator it
=_children
.begin(); it
!=_children
.end(); ++it
)
1030 template<typename T
, typename U
>
1031 XMLNode
* find(const char* name
, const T
& attr_name
, const U
& attr_value
, int n
=0) const
1033 for(Children::const_iterator it
=_children
.begin(); it
!=_children
.end(); ++it
) {
1034 const XMLNode
& node
= **it
;
1036 if (node
==name
&& node
.get(attr_name
)==attr_value
)
1045 /// XPath find function (const)
1046 const XMLNode
* find_relative(const char* path
) const;
1048 /// XPath find function
1049 XMLNode
* find_relative(const char* path
)
1050 {return const_cast<XMLNode
*>(const_cast<const XMLNode
*>(this)->find_relative(path
));}
1052 /// relative XPath create function
1053 XMLNode
* create_relative(const char* path
);
1055 void write_worker(std::ostream
& out
, int indent
) const;
1056 void plain_write_worker(std::ostream
& out
) const;
1057 void pretty_write_worker(std::ostream
& out
, const XMLFormat
& format
, int indent
) const;
1058 void smart_write_worker(std::ostream
& out
, const XMLFormat
& format
, int indent
) const;
1062 /// iterator access to children nodes with name filtering
1063 struct XMLChildrenFilter
1065 XMLChildrenFilter(XMLNode::Children
& children
, const XS_String
& name
)
1066 : _begin(children
.begin(), children
.end(), name
),
1067 _end(children
.end(), children
.end(), name
)
1071 XMLChildrenFilter(XMLNode
* node
, const XS_String
& name
)
1072 : _begin(node
->get_children().begin(), node
->get_children().end(), name
),
1073 _end(node
->get_children().end(), node
->get_children().end(), name
)
1077 /// internal iterator class
1080 typedef XMLNode::Children::iterator BaseIterator
;
1082 iterator(BaseIterator begin
, BaseIterator end
, const XS_String
& filter_name
)
1085 _filter_name(filter_name
)
1090 operator BaseIterator()
1095 const XMLNode
* operator*() const
1100 XMLNode
* operator*()
1105 iterator
& operator++()
1113 iterator
operator++(int)
1115 iterator ret
= *this;
1123 bool operator==(const BaseIterator
& other
) const
1125 return _cur
== other
;
1128 bool operator!=(const BaseIterator
& other
) const
1130 return _cur
!= other
;
1136 XS_String _filter_name
;
1140 while(_cur
!=_end
&& **_cur
!=_filter_name
)
1161 /// read only iterator access to children nodes with name filtering
1162 struct const_XMLChildrenFilter
1164 const_XMLChildrenFilter(const XMLNode::Children
& children
, const XS_String
& name
)
1165 : _begin(children
.begin(), children
.end(), name
),
1166 _end(children
.end(), children
.end(), name
)
1170 const_XMLChildrenFilter(const XMLNode
* node
, const XS_String
& name
)
1171 : _begin(node
->get_children().begin(), node
->get_children().end(), name
),
1172 _end(node
->get_children().end(), node
->get_children().end(), name
)
1176 /// internal iterator class
1177 struct const_iterator
1179 typedef XMLNode::Children::const_iterator BaseIterator
;
1181 const_iterator(BaseIterator begin
, BaseIterator end
, const XS_String
& filter_name
)
1184 _filter_name(filter_name
)
1189 operator BaseIterator()
1194 const XMLNode
* operator*() const
1199 const_iterator
& operator++()
1207 const_iterator
operator++(int)
1209 const_iterator ret
= *this;
1217 bool operator==(const BaseIterator
& other
) const
1219 return _cur
== other
;
1222 bool operator!=(const BaseIterator
& other
) const
1224 return _cur
!= other
;
1230 XS_String _filter_name
;
1234 while(_cur
!=_end
&& **_cur
!=_filter_name
)
1239 const_iterator
begin()
1244 const_iterator
end()
1250 const_iterator _begin
;
1251 const_iterator _end
;
1255 /// iterator for XML trees
1258 XMLPos(XMLNode
* root
)
1264 XMLPos(const XMLPos
& other
)
1265 : _root(other
._root
),
1267 { // don't copy _stack
1270 XMLPos(XMLNode
* node
, const XS_String
& name
)
1277 XMLPos(XMLNode
* node
, const XS_String
& name
, const XS_String
& attr_name
, const XS_String
& attr_value
)
1281 smart_create(name
, attr_name
, attr_value
);
1284 XMLPos(const XMLPos
& other
, const XS_String
& name
)
1285 : _root(other
._root
),
1291 XMLPos(const XMLPos
& other
, const XS_String
& name
, const XS_String
& attr_name
, const XS_String
& attr_value
)
1292 : _root(other
._root
),
1295 smart_create(name
, attr_name
, attr_value
);
1298 /// access to current node
1304 const XMLNode
& cur() const
1309 /// C++ access to current node
1310 operator const XMLNode
*() const {return _cur
;}
1311 operator XMLNode
*() {return _cur
;}
1313 const XMLNode
* operator->() const {return _cur
;}
1314 XMLNode
* operator->() {return _cur
;}
1316 const XMLNode
& operator*() const {return *_cur
;}
1317 XMLNode
& operator*() {return *_cur
;}
1319 /// attribute access
1320 XS_String
get(const XS_String
& attr_name
) const
1322 return _cur
->get(attr_name
);
1325 /// attribute setting
1326 void put(const XS_String
& attr_name
, const XS_String
& value
)
1328 _cur
->put(attr_name
, value
);
1331 /// C++ attribute access
1332 template<typename T
> XS_String
get(const T
& attr_name
) const {return (*_cur
)[attr_name
];}
1333 XS_String
& operator[](const XS_String
& attr_name
) {return (*_cur
)[attr_name
];}
1335 /// insert children when building tree
1336 void add_down(XMLNode
* child
)
1338 _cur
->add_child(child
);
1342 /// go back to previous position
1345 if (!_stack
.empty()) {
1346 _cur
= _stack
.top();
1353 /// go down to first child
1356 XMLNode
* node
= _cur
->get_first_child();
1365 /// search for child and go down
1366 bool go_down(const XS_String
& name
, int n
=0)
1368 XMLNode
* node
= _cur
->find(name
, n
);
1377 /// move XPath like to position in XML tree
1378 bool go(const char* path
);
1380 /// create child nodes using XPath notation and move to the deepest child
1381 bool create_relative(const char* path
)
1383 XMLNode
* node
= _cur
->create_relative(path
);
1385 return false; // invalid path specified
1391 /// create node and move to it
1392 void create(const XS_String
& name
)
1394 add_down(new XMLNode(name
));
1397 /// create node if not already existing and move to it
1398 void smart_create(const XS_String
& name
)
1400 XMLNode
* node
= _cur
->find(name
);
1405 add_down(new XMLNode(name
));
1408 /// search matching child node identified by key name and an attribute value
1409 void smart_create(const XS_String
& name
, const XS_String
& attr_name
, const XS_String
& attr_value
)
1411 XMLNode
* node
= _cur
->find(name
, attr_name
, attr_value
);
1416 node
= new XMLNode(name
);
1418 (*node
)[attr_name
] = attr_value
;
1422 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
1423 /// search for child and go down
1424 bool go_down(const char* name
, int n
=0)
1426 XMLNode
* node
= _cur
->find(name
, n
);
1435 /// create node and move to it
1436 void create(const char* name
)
1438 add_down(new XMLNode(name
));
1441 /// create node if not already existing and move to it
1442 void smart_create(const char* name
)
1444 XMLNode
* node
= _cur
->find(name
);
1449 add_down(new XMLNode(name
));
1452 /// search matching child node identified by key name and an attribute value
1453 template<typename T
, typename U
>
1454 void smart_create(const char* name
, const T
& attr_name
, const U
& attr_value
)
1456 XMLNode
* node
= _cur
->find(name
, attr_name
, attr_value
);
1461 XMLNode
* node
= new XMLNode(name
);
1463 (*node
)[attr_name
] = attr_value
;
1468 XS_String
& str() {return *_cur
;}
1469 const XS_String
& str() const {return *_cur
;}
1474 std::stack
<XMLNode
*> _stack
;
1476 /// go to specified node
1477 void go_to(XMLNode
* child
)
1485 /// iterator for XML trees
1488 const_XMLPos(const XMLNode
* root
)
1494 const_XMLPos(const const_XMLPos
& other
)
1495 : _root(other
._root
),
1497 { // don't copy _stack
1500 /// access to current node
1501 const XMLNode
& cur() const
1506 /// C++ access to current node
1507 operator const XMLNode
*() const {return _cur
;}
1509 const XMLNode
* operator->() const {return _cur
;}
1511 const XMLNode
& operator*() const {return *_cur
;}
1513 /// attribute access
1514 XS_String
get(const XS_String
& attr_name
) const
1516 return _cur
->get(attr_name
);
1519 /// C++ attribute access
1520 template<typename T
> XS_String
get(const T
& attr_name
) const {return _cur
->get(attr_name
);}
1522 /// go back to previous position
1525 if (!_stack
.empty()) {
1526 _cur
= _stack
.top();
1533 /// go down to first child
1536 const XMLNode
* node
= _cur
->get_first_child();
1545 /// search for child and go down
1546 bool go_down(const XS_String
& name
, int n
=0)
1548 XMLNode
* node
= _cur
->find(name
, n
);
1557 /// move XPath like to position in XML tree
1558 bool go(const char* path
);
1560 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
1561 /// search for child and go down
1562 bool go_down(const char* name
, int n
=0)
1564 XMLNode
* node
= _cur
->find(name
, n
);
1574 const XS_String
& str() const {return *_cur
;}
1577 const XMLNode
* _root
;
1578 const XMLNode
* _cur
;
1579 std::stack
<const XMLNode
*> _stack
;
1581 /// go to specified node
1582 void go_to(const XMLNode
* child
)
1590 /// type converter for boolean data
1593 XMLBool(bool value
=false)
1598 XMLBool(LPCXSSTR value
, bool def
=false)
1600 if (value
&& *value
)
1601 _value
= !XS_icmp(value
, XS_TRUE
);
1606 XMLBool(const XMLNode
* node
, const XS_String
& attr_name
, bool def
=false)
1608 const XS_String
& value
= node
->get(attr_name
);
1611 _value
= !XS_icmp(value
.c_str(), XS_TRUE
);
1616 operator bool() const
1621 bool operator!() const
1626 operator LPCXSSTR() const
1628 return _value
? XS_TRUE
: XS_FALSE
;
1635 void operator=(const XMLBool
&); // disallow assignment operations
1638 /// type converter for boolean data with write access
1641 XMLBoolRef(XMLNode
* node
, const XS_String
& attr_name
, bool def
=false)
1642 : _ref((*node
)[attr_name
])
1648 operator bool() const
1650 return !XS_icmp(_ref
.c_str(), XS_TRUE
);
1653 bool operator!() const
1655 return XS_icmp(_ref
.c_str(), XS_TRUE
)? true: false;
1658 XMLBoolRef
& operator=(bool value
)
1665 void assign(bool value
)
1667 _ref
.assign(value
? XS_TRUE
: XS_FALSE
);
1672 assign(!operator bool());
1680 /// type converter for integer data
1688 XMLInt(LPCXSSTR value
, int def
=0)
1690 if (value
&& *value
)
1691 _value
= XS_toi(value
);
1696 XMLInt(const XMLNode
* node
, const XS_String
& attr_name
, int def
=0)
1698 const XS_String
& value
= node
->get(attr_name
);
1701 _value
= XS_toi(value
.c_str());
1706 operator int() const
1711 operator XS_String() const
1714 XS_snprintf(buffer
, COUNTOF(buffer
), XS_INTFMT
, _value
);
1722 void operator=(const XMLInt
&); // disallow assignment operations
1725 /// type converter for integer data with write access
1728 XMLIntRef(XMLNode
* node
, const XS_String
& attr_name
, int def
=0)
1729 : _ref((*node
)[attr_name
])
1735 XMLIntRef
& operator=(int value
)
1742 operator int() const
1744 return XS_toi(_ref
.c_str());
1747 void assign(int value
)
1750 XS_snprintf(buffer
, COUNTOF(buffer
), XS_INTFMT
, value
);
1751 _ref
.assign(buffer
);
1759 /// type converter for numeric data
1762 XMLDouble(double value
)
1767 XMLDouble(LPCXSSTR value
, double def
=0.)
1771 if (value
&& *value
)
1772 _value
= XS_tod(value
, &end
);
1777 XMLDouble(const XMLNode
* node
, const XS_String
& attr_name
, double def
=0.)
1780 const XS_String
& value
= node
->get(attr_name
);
1783 _value
= XS_tod(value
.c_str(), &end
);
1788 operator double() const
1793 operator XS_String() const
1796 XS_snprintf(buffer
, COUNTOF(buffer
), XS_FLOATFMT
, _value
);
1804 void operator=(const XMLDouble
&); // disallow assignment operations
1807 /// type converter for numeric data with write access
1810 XMLDoubleRef(XMLNode
* node
, const XS_String
& attr_name
, double def
=0.)
1811 : _ref((*node
)[attr_name
])
1817 XMLDoubleRef
& operator=(double value
)
1824 operator double() const
1827 return XS_tod(_ref
.c_str(), &end
);
1830 void assign(double value
)
1833 XS_snprintf(buffer
, COUNTOF(buffer
), XS_FLOATFMT
, value
);
1834 _ref
.assign(buffer
);
1842 /// type converter for string data
1845 XMLString(const XS_String
& value
)
1850 XMLString(LPCXSSTR value
, LPCXSSTR def
=XS_EMPTY
)
1852 if (value
&& *value
)
1858 XMLString(const XMLNode
* node
, const XS_String
& attr_name
, LPCXSSTR def
=XS_EMPTY
)
1860 const XS_String
& value
= node
->get(attr_name
);
1868 operator const XS_String
&() const
1873 const XS_String
& c_str() const
1882 void operator=(const XMLString
&); // disallow assignment operations
1885 /// type converter for string data with write access
1888 XMStringRef(XMLNode
* node
, const XS_String
& attr_name
, LPCXSSTR def
=XS_EMPTY
)
1889 : _ref((*node
)[attr_name
])
1895 XMStringRef(XMLNode
* node
, const XS_String
& node_name
, const XS_String
& attr_name
, LPCXSSTR def
=XS_EMPTY
)
1896 : _ref(node
->subvalue(node_name
, attr_name
))
1902 XMStringRef
& operator=(const XS_String
& value
)
1909 operator const XS_String
&() const
1914 void assign(const XS_String
& value
)
1924 template<typename T
>
1925 inline void read_option(T
& var
, const_XMLPos
& cfg
, LPCXSSTR key
)
1927 const XS_String
& val
= cfg
.get(key
);
1934 inline void read_option(int& var
, const_XMLPos
& cfg
, LPCXSSTR key
)
1936 const XS_String
& val
= cfg
.get(key
);
1939 var
= XS_toi(val
.c_str());
1944 #pragma warning(disable: 4355)
1947 /// XML reader base class
1948 struct XMLReaderBase
1949 #ifdef XS_USE_XERCES
1950 : public HandlerBase
1953 #ifdef XS_USE_XERCES
1955 XMLReaderBase(XMLNode
* node
, InputSource
* source
, bool adoptSource
=false);
1956 virtual ~XMLReaderBase();
1962 InputSource
* _source
;
1965 virtual void XMLDecl(const XMLCh
* const versionStr
, const XMLCh
* const encodingStr
,
1966 const XMLCh
* const standaloneStr
, const XMLCh
* const actualEncodingStr
);
1968 // Handlers for the SAX DocumentHandler interface
1969 virtual void setDocumentLocator(const Locator
* const locator
);
1970 virtual void startElement(const XMLCh
* const name
, AttributeList
& attributes
);
1971 virtual void endElement(const XMLCh
* const name
);
1972 virtual void characters(const XMLCh
* const chars
, const unsigned int length
);
1973 virtual void ignorableWhitespace(const XMLCh
* const chars
, const unsigned int length
);
1975 // Handlers for the SAX ErrorHandler interface
1976 virtual void error(const SAXParseException
& e
);
1977 virtual void fatalError(const SAXParseException
& e
);
1978 virtual void warning(const SAXParseException
& e
);
1979 virtual void resetErrors();
1981 #elif defined(XS_USE_EXPAT) // !XS_USE_XERCES
1983 XMLReaderBase(XMLNode
* node
);
1984 virtual ~XMLReaderBase();
1989 static void XMLCALL
XML_XmlDeclHandler(void* userData
, const XML_Char
* version
, const XML_Char
* encoding
, int standalone
=-1);
1990 static void XMLCALL
XML_StartElementHandler(void* userData
, const XML_Char
* name
, const XML_Char
** atts
);
1991 static void XMLCALL
XML_EndElementHandler(void* userData
, const XML_Char
* name
);
1992 static void XMLCALL
XML_DefaultHandler(void* userData
, const XML_Char
* s
, int len
);
1994 static std::string
get_expat_error_string(XML_Error error_code
);
1996 #else // XS_USE_EXPAT
1998 XMLReaderBase(XMLNode
* node
)
2000 _endl_defined(false),
2003 _last_tag
= TAG_NONE
;
2006 virtual ~XMLReaderBase();
2013 #ifndef XS_USE_XERCES
2016 std::string
get_position() const;
2018 const XMLFormat
& get_format() const {return _format
;}
2019 const char* get_endl() const {return _endl_defined
? _format
._endl
: "\n";}
2021 const XMLErrorList
& get_errors() const {return _errors
;}
2022 const XMLErrorList
& get_warnings() const {return _warnings
;}
2024 void clear_errors() {_errors
.clear(); _warnings
.clear();}
2026 #ifdef XMLNODE_LOCATION
2027 const char* _display_path
; // character pointer for fast reference in XMLLocation
2029 #ifdef XS_USE_XERCES
2030 const Locator
* _locator
;
2033 XMLLocation
get_location() const;
2039 std::string _content
; // UTF-8 encoded
2040 enum {TAG_NONE
, TAG_START
, TAG_END
} _last_tag
;
2042 XMLErrorList _errors
;
2043 XMLErrorList _warnings
;
2048 #ifdef XS_USE_XERCES
2050 #elif defined(XS_USE_EXPAT)
2051 virtual int read_buffer(char* buffer
, int len
) = 0;
2053 virtual int get() = 0;
2061 virtual void XmlDeclHandler(const char* version
, const char* encoding
, int standalone
);
2062 virtual void StartElementHandler(const XS_String
& name
, const XMLNode::AttributeMap
& attributes
);
2063 virtual void EndElementHandler();
2064 #if defined(XS_USE_XERCES) || defined(XS_USE_EXPAT)
2065 virtual void DefaultHandler(const XML_Char
* s
, int len
);
2067 virtual void DefaultHandler(const std::string
& s
);
2074 #ifdef XS_USE_XERCES
2076 struct XercesXMLReader
: public XMLReaderBase
2078 XercesXMLReader(XMLNode
* node
, InputSource
* source
, bool adoptSource
=false)
2079 : XMLReaderBase(node
, source
, adoptSource
)
2083 XercesXMLReader(XMLNode
* node
, LPCTSTR path
);
2084 XercesXMLReader(XMLNode
* node
, const XMLByte
* buffer
, size_t bytes
, const std::string
& system_id
=std::string());
2087 #define XMLReader XercesXMLReader
2089 #elif defined(XS_USE_EXPAT)
2091 struct ExpatXMLReader
: public XMLReaderBase
2093 ExpatXMLReader(XMLNode
* node
, std::istream
& in
)
2094 : XMLReaderBase(node
),
2099 /// read XML stream into XML tree below _pos
2100 int read_buffer(char* buffer
, int len
)
2105 _in
.read(buffer
, len
);
2107 return _in
.gcount();
2114 #define XMLReader ExpatXMLReader
2116 #else // XS_USE_XERCES, XS_USE_EXPAT
2118 struct XMLReader
: public XMLReaderBase
2120 XMLReader(XMLNode
* node
, std::istream
& in
)
2121 : XMLReaderBase(node
),
2126 /// read one character from XML stream
2136 #endif // XS_USE_XERCES
2139 /// XML document holder
2140 struct XMLDoc
: public XMLNode
2147 XMLDoc(LPCTSTR path
)
2153 #ifdef XS_USE_XERCES
2154 bool read(LPCTSTR path
)
2156 XMLReader
reader(this, path
);
2158 #if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8)
2159 return read(reader
, std::string(ANS(path
)));
2161 return read(reader
, XS_String(path
));
2165 bool read(const char* buffer
, size_t len
, const std::string
& system_id
=std::string())
2167 XMLReader
reader(this, (const XMLByte
*)buffer
, len
, system_id
);
2169 return read(reader
, system_id
);
2172 #else // XS_USE_XERCES
2174 bool read(LPCTSTR path
)
2177 XMLReader
reader(this, in
);
2179 #if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8)
2180 return read(reader
, std::string(ANS(path
)));
2182 return read(reader
, XS_String(path
));
2186 bool read(const char* buffer
, size_t len
, const std::string
& system_id
=std::string())
2188 std::istringstream
in(std::string(buffer
, len
));
2190 return read(in
, system_id
);
2193 bool read(std::istream
& in
, const std::string
& system_id
=std::string())
2195 XMLReader
reader(this, in
);
2197 return read(reader
, system_id
);
2199 #endif // XS_USE_XERCES
2201 bool read(XMLReaderBase
& reader
, const std::string
& display_path
)
2203 #ifdef XMLNODE_LOCATION
2204 // make a string copy to handle temporary string objects
2205 _display_path
= display_path
;
2206 reader
._display_path
= _display_path
.c_str();
2209 reader
.clear_errors();
2212 _format
= reader
.get_format();
2213 _format
._endl
= reader
.get_endl();
2215 if (!reader
.get_errors().empty()) {
2216 _errors
= reader
.get_errors();
2223 /// write XML stream preserving previous white space and comments
2224 std::ostream
& write(std::ostream
& out
, WRITE_MODE mode
=FORMAT_SMART
) const
2226 _format
.print_header(out
, mode
!=FORMAT_PLAIN
);
2228 if (!_children
.empty())
2229 _children
.front()->write(out
, _format
, mode
);
2234 /// write XML stream with formating
2235 std::ostream
& write_formating(std::ostream
& out
) const
2237 return write(out
, FORMAT_PRETTY
);
2240 bool write(LPCTSTR path
, WRITE_MODE mode
=FORMAT_SMART
) const
2242 tofstream
out(path
);
2244 return write(out
, mode
).good();
2247 bool write_formating(LPCTSTR path
) const
2249 tofstream
out(path
);
2251 return write_formating(out
).good();
2255 XMLErrorList _errors
;
2257 #ifdef XMLNODE_LOCATION
2258 std::string _display_path
;
2263 /// XML message wrapper
2264 struct XMLMessage
: public XMLDoc
2266 XMLMessage(const char* name
)
2272 std::string
toString() const
2274 std::ostringstream out
;
2291 /// helper structure to read XML messages from strings
2292 struct XMLMessageFromString
: public XMLMessage
2294 XMLMessageFromString(const std::string
& xml_str
, const std::string
& system_id
=std::string())
2296 read(xml_str
.c_str(), xml_str
.length(), system_id
);
2301 /// Reader for XML Messages
2302 struct XMLMessageReader
: public XMLPos
2304 XMLMessageReader(const std::string
& xml_str
, const std::string
& system_id
=std::string())
2307 _msg
.read(xml_str
.c_str(), xml_str
.length(), system_id
);
2310 const XMLDoc
& get_document()
2320 /// on the fly XML writer
2323 XMLWriter(std::ostream
& out
, const XMLFormat
& format
=XMLFormat())
2328 format
.print_header(_out
, false); // _format._endl is printed in write_pre()
2331 XMLWriter(LPCTSTR path
, const XMLFormat
& format
=XMLFormat())
2332 : _pofstream(new tofstream(path
)),
2336 format
.print_header(_out
, false); // _format._endl is printed in write_pre()
2341 _out
<< _format
._endl
;
2345 /// create node and move to it
2346 void create(const XS_String
& name
)
2348 if (!_stack
.empty()) {
2349 StackEntry
& last
= _stack
.top();
2351 if (last
._state
< PRE_CLOSED
) {
2352 write_attributes(last
);
2360 entry
._node_name
= name
;
2366 /// go back to previous position
2369 if (!_stack
.empty()) {
2370 write_post(_stack
.top());
2378 /// attribute setting
2379 void put(const XS_String
& attr_name
, const XS_String
& value
)
2381 if (!_stack
.empty())
2382 _stack
.top()._attributes
[attr_name
] = value
;
2385 /// C++ write access to an attribute
2386 XS_String
& operator[](const XS_String
& attr_name
)
2389 return s_empty_attr
;
2391 return _stack
.top()._attributes
[attr_name
];
2394 void set_content(const XS_String
& s
)
2396 if (!_stack
.empty())
2397 _stack
.top()._content
= EncodeXMLString(s
.c_str());
2400 // public for access in StackEntry
2402 NOTHING
, /*PRE,*/ ATTRIBUTES
, PRE_CLOSED
, /*CONTENT,*/ POST
2406 tofstream
* _pofstream
;
2408 const XMLFormat
&_format
;
2410 typedef XMLNode::AttributeMap AttrMap
;
2412 /// container for XMLWriter state information
2414 XS_String _node_name
;
2415 AttrMap _attributes
;
2416 std::string _content
;
2420 StackEntry() : _state(NOTHING
), _children(false) {}
2423 std::stack
<StackEntry
> _stack
;
2425 static XS_String s_empty_attr
;
2427 void close_pre(StackEntry
& entry
)
2431 entry
._state
= PRE_CLOSED
;
2434 void write_pre(StackEntry
& entry
)
2436 if (_format
._pretty
>= PRETTY_LINEFEED
)
2437 _out
<< _format
._endl
;
2439 if (_format
._pretty
== PRETTY_INDENT
)
2440 for(size_t i
=_stack
.size(); --i
>0; )
2441 _out
<< XML_INDENT_SPACE
;
2443 _out
<< '<' << EncodeXMLString(entry
._node_name
);
2444 //entry._state = PRE;
2447 void write_attributes(StackEntry
& entry
)
2449 for(AttrMap::const_iterator it
=entry
._attributes
.begin(); it
!=entry
._attributes
.end(); ++it
)
2450 _out
<< ' ' << EncodeXMLString(it
->first
) << "=\"" << EncodeXMLString(it
->second
) << "\"";
2452 entry
._state
= ATTRIBUTES
;
2455 void write_post(StackEntry
& entry
)
2457 if (entry
._state
< ATTRIBUTES
)
2458 write_attributes(entry
);
2460 if (entry
._children
|| !entry
._content
.empty()) {
2461 if (entry
._state
< PRE_CLOSED
)
2464 _out
<< entry
._content
;
2465 //entry._state = CONTENT;
2467 if (_format
._pretty
>=PRETTY_LINEFEED
&& entry
._content
.empty())
2468 _out
<< _format
._endl
;
2470 if (_format
._pretty
==PRETTY_INDENT
&& entry
._content
.empty())
2471 for(size_t i
=_stack
.size(); --i
>0; )
2472 _out
<< XML_INDENT_SPACE
;
2474 _out
<< "</" << EncodeXMLString(entry
._node_name
) << ">";
2479 entry
._state
= POST
;
2484 } // namespace XMLStorage
2486 #define _XMLSTORAGE_H
2487 #endif // _XMLSTORAGE_H