1 /****************************************************************************/
2 /*! \mainpage XMLParser library
3  * \section intro_sec Introduction
4  *
5  * This is a basic XML parser written in ANSI C++ for portability.
6  * It works by using recursion and a node tree for breaking
7  * down the elements of an XML document.
8  *
9  * @version     V2.43
10  * @author      Frank Vanden Berghen
11  *
12  * Copyright (c) 2002, Business-Insight
13  * <a href="http://www.Business-Insight.com">Business-Insight</a>
14  * All rights reserved.
15  * See the file <a href="../../AFPL-license.txt">AFPL-license.txt</a> about the licensing terms
16  *
17  * \section tutorial First Tutorial
18  * You can follow a simple <a href="../../xmlParser.html">Tutorial</a> to know the basics...
19  *
20  * \section usage General usage: How to include the XMLParser library inside your project.
21  *
22  * The library is composed of two files: <a href="../../xmlParser.cpp">xmlParser.cpp</a> and
23  * <a href="../../xmlParser.h">xmlParser.h</a>. These are the ONLY 2 files that you need when
24  * using the library inside your own projects.
25  *
26  * All the functions of the library are documented inside the comments of the file
27  * <a href="../../xmlParser.h">xmlParser.h</a>. These comments can be transformed in
28  * full-fledged HTML documentation using the DOXYGEN software: simply type: "doxygen doxy.cfg"
29  *
30  * By default, the XMLParser library uses (char*) for string representation.To use the (wchar_t*)
31  * version of the library, you need to define the "_UNICODE" preprocessor definition variable
32  * (this is usually done inside your project definition file) (This is done automatically for you
33  * when using Visual Studio).
34  *
35  * \section example Advanced Tutorial and Many Examples of usage.
36  *
37  * Some very small introductory examples are described inside the Tutorial file
38  * <a href="../../xmlParser.html">xmlParser.html</a>
39  *
40  * Some additional small examples are also inside the file <a href="../../xmlTest.cpp">xmlTest.cpp</a>
41  * (for the "char*" version of the library) and inside the file
42  * <a href="../../xmlTestUnicode.cpp">xmlTestUnicode.cpp</a> (for the "wchar_t*"
43  * version of the library). If you have a question, please review these additionnal examples
44  * before sending an e-mail to the author.
45  *
46  * To build the examples:
47  * - linux/unix: type "make"
48  * - solaris: type "make -f makefile.solaris"
49  * - windows: Visual Studio: double-click on xmlParser.dsw
50  *   (under Visual Studio .NET, the .dsp and .dsw files will be automatically converted to .vcproj and .sln files)
51  *
52  * In order to build the examples you need some additional files:
53  * - linux/unix: makefile
54  * - solaris: makefile.solaris
55  * - windows: Visual Studio: *.dsp, xmlParser.dsw and also xmlParser.lib and xmlParser.dll
56  *
57  * \section debugging Debugging with the XMLParser library
58  *
59  * \subsection debugwin Debugging under WINDOWS
60  *
61  * 	Inside Visual C++, the "debug versions" of the memory allocation functions are
62  * 	very slow: Do not forget to compile in "release mode" to get maximum speed.
63  * 	When I had to debug a software that was using the XMLParser Library, it was usually
64  * 	a nightmare because the library was sooOOOoooo slow in debug mode (because of the
65  *  slow memory allocations in Debug mode). To solve this
66  * 	problem, during all the debugging session, I am now using a very fast DLL version of the
67  * 	XMLParser Library (the DLL is compiled in release mode). Using the DLL version of
68  * 	the XMLParser Library allows me to have lightening XML parsing speed even in debug!
69  * 	Other than that, the DLL version is useless: In the release version of my tool,
70  * 	I always use the normal, ".cpp"-based, XMLParser Library (I simply include the
71  * <a href="../../xmlParser.cpp">xmlParser.cpp</a> and
72  * <a href="../../xmlParser.h">xmlParser.h</a> files into the project).
73  *
74  * 	The file <a href="../../XMLNodeAutoexp.txt">XMLNodeAutoexp.txt</a> contains some
75  * "tweaks" that improve substancially the display of the content of the XMLNode objects
76  * inside the Visual Studio Debugger. Believe me, once you have seen inside the debugger
77  * the "smooth" display of the XMLNode objects, you cannot live without it anymore!
78  *
79  * \subsection debuglinux Debugging under LINUX/UNIX
80  *
81  * 	The speed of the debug version of the XMLParser library is tolerable so no extra
82  * work.has been done.
83  *
84  ****************************************************************************/
85 
86 #ifndef __INCLUDE_XML_NODE__
87 #define __INCLUDE_XML_NODE__
88 
89 #include <stdlib.h>
90 
91 #ifdef _UNICODE
92 // If you comment the next "define" line then the library will never "switch to" _UNICODE (wchar_t*) mode (16/32 bits per characters).
93 // This is useful when you get error messages like:
94 //    'XMLNode::openFileHelper' : cannot convert parameter 2 from 'const char [5]' to 'const wchar_t *'
95 // The _XMLWIDECHAR preprocessor variable force the XMLParser library into either utf16/32-mode (the proprocessor variable
96 // must be defined) or utf8-mode(the pre-processor variable must be undefined).
97 #define _XMLWIDECHAR
98 #endif
99 
100 #if defined(WIN32) || defined(UNDER_CE) || defined(_WIN32) || defined(WIN64) || defined(__BORLANDC__)
101 // comment the next line if you are under windows and the compiler is not Microsoft Visual Studio (6.0 or .NET) or Borland
102 #define _XMLWINDOWS
103 #endif
104 
105 #ifdef XMLDLLENTRY
106 #undef XMLDLLENTRY
107 #endif
108 #ifdef _USE_XMLPARSER_DLL
109 #ifdef _DLL_EXPORTS_
110 #define XMLDLLENTRY __declspec(dllexport)
111 #else
112 #define XMLDLLENTRY __declspec(dllimport)
113 #endif
114 #else
115 #define XMLDLLENTRY
116 #endif
117 
118 // uncomment the next line if you want no support for wchar_t* (no need for the <wchar.h> or <tchar.h> libraries anymore to compile)
119 //#define XML_NO_WIDE_CHAR
120 
121 #ifdef XML_NO_WIDE_CHAR
122 #undef _XMLWINDOWS
123 #undef _XMLWIDECHAR
124 #endif
125 
126 #ifdef _XMLWINDOWS
127 #include <tchar.h>
128 #else
129 #define XMLDLLENTRY
130 #ifndef XML_NO_WIDE_CHAR
131 #include <wchar.h> // to have 'wcsrtombs' for ANSI version
132                    // to have 'mbsrtowcs' for WIDECHAR version
133 #endif
134 #endif
135 
136 // Some common types for char set portable code
137 #ifdef _XMLWIDECHAR
138     #define _CXML(c) L ## c
139     #define XMLCSTR const wchar_t *
140     #define XMLSTR  wchar_t *
141     #define XMLCHAR wchar_t
142 #else
143     #define _CXML(c) c
144     #define XMLCSTR const char *
145     #define XMLSTR  char *
146     #define XMLCHAR char
147 #endif
148 #ifndef FALSE
149     #define FALSE 0
150 #endif /* FALSE */
151 #ifndef TRUE
152     #define TRUE 1
153 #endif /* TRUE */
154 
155 
156 /// Enumeration for XML parse errors.
157 typedef enum XMLError
158 {
159     eXMLErrorNone = 0,
160     eXMLErrorMissingEndTag,
161     eXMLErrorNoXMLTagFound,
162     eXMLErrorEmpty,
163     eXMLErrorMissingTagName,
164     eXMLErrorMissingEndTagName,
165     eXMLErrorUnmatchedEndTag,
166     eXMLErrorUnmatchedEndClearTag,
167     eXMLErrorUnexpectedToken,
168     eXMLErrorNoElements,
169     eXMLErrorFileNotFound,
170     eXMLErrorFirstTagNotFound,
171     eXMLErrorUnknownCharacterEntity,
172     eXMLErrorCharacterCodeAbove255,
173     eXMLErrorCharConversionError,
174     eXMLErrorCannotOpenWriteFile,
175     eXMLErrorCannotWriteFile,
176 
177     eXMLErrorBase64DataSizeIsNotMultipleOf4,
178     eXMLErrorBase64DecodeIllegalCharacter,
179     eXMLErrorBase64DecodeTruncatedData,
180     eXMLErrorBase64DecodeBufferTooSmall
181 } XMLError;
182 
183 
184 /// Enumeration used to manage type of data. Use in conjunction with structure XMLNodeContents
185 typedef enum XMLElementType
186 {
187     eNodeChild=0,
188     eNodeAttribute=1,
189     eNodeText=2,
190     eNodeClear=3,
191     eNodeNULL=4
192 } XMLElementType;
193 
194 /// Structure used to obtain error details if the parse fails.
195 typedef struct XMLResults
196 {
197     enum XMLError error;
198     int  nLine,nColumn;
199 } XMLResults;
200 
201 /// Structure for XML clear (unformatted) node (usually comments)
202 typedef struct XMLClear {
203     XMLCSTR lpszValue; XMLCSTR lpszOpenTag; XMLCSTR lpszCloseTag;
204 } XMLClear;
205 
206 /// Structure for XML attribute.
207 typedef struct XMLAttribute {
208     XMLCSTR lpszName; XMLCSTR lpszValue;
209 } XMLAttribute;
210 
211 /// XMLElementPosition are not interchangeable with simple indexes
212 typedef int XMLElementPosition;
213 
214 struct XMLNodeContents;
215 
216 /** @defgroup XMLParserGeneral The XML parser */
217 
218 /// Main Class representing a XML node
219 /**
220  * All operations are performed using this class.
221  * \note The constructors of the XMLNode class are protected, so use instead one of these four methods to get your first instance of XMLNode:
222  * <ul>
223  *    <li> XMLNode::parseString </li>
224  *    <li> XMLNode::parseFile </li>
225  *    <li> XMLNode::openFileHelper </li>
226  *    <li> XMLNode::createXMLTopNode (or XMLNode::createXMLTopNode_WOSD)</li>
227  * </ul> */
228 typedef struct XMLDLLENTRY XMLNode
229 {
230   private:
231 
232     struct XMLNodeDataTag;
233 
234     /// Constructors are protected, so use instead one of: XMLNode::parseString, XMLNode::parseFile, XMLNode::openFileHelper, XMLNode::createXMLTopNode
235     XMLNode(struct XMLNodeDataTag *pParent, XMLSTR lpszName, char isDeclaration);
236     /// Constructors are protected, so use instead one of: XMLNode::parseString, XMLNode::parseFile, XMLNode::openFileHelper, XMLNode::createXMLTopNode
237     XMLNode(struct XMLNodeDataTag *p);
238 
239   public:
240     static XMLCSTR getVersion();///< Return the XMLParser library version number
241 
242     /** @defgroup conversions Parsing XML files/strings to an XMLNode structure and Rendering XMLNode's to files/string.
243      * @ingroup XMLParserGeneral
244      * @{ */
245 
246     /// Parse an XML string and return the root of a XMLNode tree representing the string.
247     static XMLNode parseString   (XMLCSTR  lpXMLString, XMLCSTR tag=NULL, XMLResults *pResults=NULL);
248     /**< The "parseString" function parse an XML string and return the root of a XMLNode tree. The "opposite" of this function is
249      * the function "createXMLString" that re-creates an XML string from an XMLNode tree. If the XML document is corrupted, the
250      * "parseString" method will initialize the "pResults" variable with some information that can be used to trace the error.
251      * If you still want to parse the file, you can use the APPROXIMATE_PARSING option as explained inside the note at the
252      * beginning of the "xmlParser.cpp" file.
253      *
254      * @param lpXMLString the XML string to parse
255      * @param tag  the name of the first tag inside the XML file. If the tag parameter is omitted, this function returns a node that represents the head of the xml document including the declaration term (<? ... ?>).
256      * @param pResults a pointer to a XMLResults variable that will contain some information that can be used to trace the XML parsing error. You can have a user-friendly explanation of the parsing error with the "getError" function.
257      */
258 
259     /// Parse an XML file and return the root of a XMLNode tree representing the file.
260     static XMLNode parseFile     (XMLCSTR     filename, XMLCSTR tag=NULL, XMLResults *pResults=NULL);
261     /**< The "parseFile" function parse an XML file and return the root of a XMLNode tree. The "opposite" of this function is
262      * the function "writeToFile" that re-creates an XML file from an XMLNode tree. If the XML document is corrupted, the
263      * "parseFile" method will initialize the "pResults" variable with some information that can be used to trace the error.
264      * If you still want to parse the file, you can use the APPROXIMATE_PARSING option as explained inside the note at the
265      * beginning of the "xmlParser.cpp" file.
266      *
267      * @param filename the path to the XML file to parse
268      * @param tag the name of the first tag inside the XML file. If the tag parameter is omitted, this function returns a node that represents the head of the xml document including the declaration term (<? ... ?>).
269      * @param pResults a pointer to a XMLResults variable that will contain some information that can be used to trace the XML parsing error. You can have a user-friendly explanation of the parsing error with the "getError" function.
270      */
271 
272     /// Parse an XML file and return the root of a XMLNode tree representing the file. A very crude error checking is made. An attempt to guess the Char Encoding used in the file is made.
273     static XMLNode openFileHelper(XMLCSTR     filename, XMLCSTR tag=NULL);
274     /**< The "openFileHelper" function reports to the screen all the warnings and errors that occurred during parsing of the XML file.
275      * This function also tries to guess char Encoding (UTF-8, ASCII or SHIT-JIS) based on the first 200 bytes of the file. Since each
276      * application has its own way to report and deal with errors, you should rather use the "parseFile" function to parse XML files
277      * and program yourself thereafter an "error reporting" tailored for your needs (instead of using the very crude "error reporting"
278      * mechanism included inside the "openFileHelper" function).
279      *
280      * If the XML document is corrupted, the "openFileHelper" method will:
281      *         - display an error message on the console (or inside a messageBox for windows).
282      *         - stop execution (exit).
283      *
284      * I strongly suggest that you write your own "openFileHelper" method tailored to your needs. If you still want to parse
285      * the file, you can use the APPROXIMATE_PARSING option as explained inside the note at the beginning of the "xmlParser.cpp" file.
286      *
287      * @param filename the path of the XML file to parse.
288      * @param tag the name of the first tag inside the XML file. If the tag parameter is omitted, this function returns a node that represents the head of the xml document including the declaration term (<? ... ?>).
289      */
290 
291     static XMLCSTR getError(XMLError error); ///< this gives you a user-friendly explanation of the parsing error
292 
293     /// Create an XML string starting from the current XMLNode.
294     XMLSTR createXMLString(int nFormat=1, int *pnSize=NULL) const;
295     /**< The returned string should be free'd using the "freeXMLString" function.
296      *
297      *   If nFormat==0, no formatting is required otherwise this returns an user friendly XML string from a given element
298      *   with appropriate white spaces and carriage returns. if pnSize is given it returns the size in character of the string. */
299 
300     /// Save the content of an xmlNode inside a file
301     XMLError writeToFile(XMLCSTR filename,
302                          const char *encoding=NULL,
303                          char nFormat=1) const;
304     /**< If nFormat==0, no formatting is required otherwise this returns an user friendly XML string from a given element with appropriate white spaces and carriage returns.
305      * If the global parameter "characterEncoding==encoding_UTF8", then the "encoding" parameter is ignored and always set to "utf-8".
306      * If the global parameter "characterEncoding==encoding_ShiftJIS", then the "encoding" parameter is ignored and always set to "SHIFT-JIS".
307      * If "_XMLWIDECHAR=1", then the "encoding" parameter is ignored and always set to "utf-16".
308      * If no "encoding" parameter is given the "ISO-8859-1" encoding is used. */
309     /** @} */
310 
311     /** @defgroup navigate Navigate the XMLNode structure
312      * @ingroup XMLParserGeneral
313      * @{ */
314     XMLCSTR getName() const;                                       ///< name of the node
315     XMLCSTR getText(int i=0) const;                                ///< return ith text field
316     int nText() const;                                             ///< nbr of text field
317     XMLNode getParentNode() const;                                 ///< return the parent node
318     XMLNode getChildNode(int i=0) const;                           ///< return ith child node
319     XMLNode getChildNode(XMLCSTR name, int i)  const;              ///< return ith child node with specific name (return an empty node if failing). If i==-1, this returns the last XMLNode with the given name.
320     XMLNode getChildNode(XMLCSTR name, int *i=NULL) const;         ///< return next child node with specific name (return an empty node if failing)
321     XMLNode getChildNodeWithAttribute(XMLCSTR tagName,
322                                       XMLCSTR attributeName,
323                                       XMLCSTR attributeValue=NULL,
324                                       int *i=NULL)  const;         ///< return child node with specific name/attribute (return an empty node if failing)
325     XMLNode getChildNodeByPath(XMLCSTR path, char createNodeIfMissing=0, XMLCHAR sep='/');
326                                                                    ///< return the first child node with specific path
327     XMLNode getChildNodeByPathNonConst(XMLSTR  path, char createNodeIfMissing=0, XMLCHAR sep='/');
328                                                                    ///< return the first child node with specific path.
329 
330     int nChildNode(XMLCSTR name) const;                            ///< return the number of child node with specific name
331     int nChildNode() const;                                        ///< nbr of child node
332     XMLAttribute getAttribute(int i=0) const;                      ///< return ith attribute
333     XMLCSTR      getAttributeName(int i=0) const;                  ///< return ith attribute name
334     XMLCSTR      getAttributeValue(int i=0) const;                 ///< return ith attribute value
335     char  isAttributeSet(XMLCSTR name) const;                      ///< test if an attribute with a specific name is given
336     XMLCSTR getAttribute(XMLCSTR name, int i) const;               ///< return ith attribute content with specific name (return a NULL if failing)
337     XMLCSTR getAttribute(XMLCSTR name, int *i=NULL) const;         ///< return next attribute content with specific name (return a NULL if failing)
338     int nAttribute() const;                                        ///< nbr of attribute
339     XMLClear getClear(int i=0) const;                              ///< return ith clear field (comments)
340     int nClear() const;                                            ///< nbr of clear field
341     XMLNodeContents enumContents(XMLElementPosition i) const;      ///< enumerate all the different contents (attribute,child,text, clear) of the current XMLNode. The order is reflecting the order of the original file/string. NOTE: 0 <= i < nElement();
342     int nElement() const;                                          ///< nbr of different contents for current node
343     char isEmpty() const;                                          ///< is this node Empty?
344     char isDeclaration() const;                                    ///< is this node a declaration <? .... ?>
345     XMLNode deepCopy() const;                                      ///< deep copy (duplicate/clone) a XMLNode
346     static XMLNode emptyNode();                                    ///< return XMLNode::emptyXMLNode;
347     /** @} */
348 
349     ~XMLNode();
350     XMLNode(const XMLNode &A);                                     ///< to allow shallow/fast copy:
351     XMLNode& operator=( const XMLNode& A );                        ///< to allow shallow/fast copy:
352 
XMLNodeXMLNode353     XMLNode(): d(NULL){};
354     static XMLNode emptyXMLNode;
355     static XMLClear emptyXMLClear;
356     static XMLAttribute emptyXMLAttribute;
357 
358     /** @defgroup xmlModify Create or Update the XMLNode structure
359      * @ingroup XMLParserGeneral
360      *  The functions in this group allows you to create from scratch (or update) a XMLNode structure. Start by creating your top
361      *  node with the "createXMLTopNode" function and then add new nodes with the "addChild" function. The parameter 'pos' gives
362      *  the position where the childNode, the text or the XMLClearTag will be inserted. The default value (pos=-1) inserts at the
363      *  end. The value (pos=0) insert at the beginning (Insertion at the beginning is slower than at the end). <br>
364      *
365      *  REMARK: 0 <= pos < nChild()+nText()+nClear() <br>
366      */
367 
368     /** @defgroup creation Creating from scratch a XMLNode structure
369      * @ingroup xmlModify
370      * @{ */
371     static XMLNode createXMLTopNode(XMLCSTR lpszName, char isDeclaration=FALSE);                    ///< Create the top node of an XMLNode structure
372     XMLNode        addChild(XMLCSTR lpszName, char isDeclaration=FALSE, XMLElementPosition pos=-1); ///< Add a new child node
373     XMLNode        addChild(XMLNode nodeToAdd, XMLElementPosition pos=-1);                          ///< If the "nodeToAdd" has some parents, it will be detached from it's parents before being attached to the current XMLNode
374     XMLAttribute  *addAttribute(XMLCSTR lpszName, XMLCSTR lpszValuev);                              ///< Add a new attribute
375     XMLCSTR        addText(XMLCSTR lpszValue, XMLElementPosition pos=-1);                           ///< Add a new text content
376     XMLClear      *addClear(XMLCSTR lpszValue, XMLCSTR lpszOpen=NULL, XMLCSTR lpszClose=NULL, XMLElementPosition pos=-1);
377     /**< Add a new clear tag
378      * @param lpszOpen default value "<![CDATA["
379      * @param lpszClose default value "]]>"
380      */
381     /** @} */
382 
383     /** @defgroup xmlUpdate Updating Nodes
384      * @ingroup xmlModify
385      * Some update functions:
386      * @{
387      */
388     XMLCSTR       updateName(XMLCSTR lpszName);                                                  ///< change node's name
389     XMLAttribute *updateAttribute(XMLAttribute *newAttribute, XMLAttribute *oldAttribute);       ///< if the attribute to update is missing, a new one will be added
390     XMLAttribute *updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName=NULL,int i=0);       ///< if the attribute to update is missing, a new one will be added
391     XMLAttribute *updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName,XMLCSTR lpszOldName);///< set lpszNewName=NULL if you don't want to change the name of the attribute if the attribute to update is missing, a new one will be added
392     XMLCSTR       updateText(XMLCSTR lpszNewValue, int i=0);                                     ///< if the text to update is missing, a new one will be added
393     XMLCSTR       updateText(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue);                        ///< if the text to update is missing, a new one will be added
394     XMLClear     *updateClear(XMLCSTR lpszNewContent, int i=0);                                  ///< if the clearTag to update is missing, a new one will be added
395     XMLClear     *updateClear(XMLClear *newP,XMLClear *oldP);                                    ///< if the clearTag to update is missing, a new one will be added
396     XMLClear     *updateClear(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue);                       ///< if the clearTag to update is missing, a new one will be added
397     /** @} */
398 
399     /** @defgroup xmlDelete Deleting Nodes or Attributes
400      * @ingroup xmlModify
401      * Some deletion functions:
402      * @{
403      */
404     /// The "deleteNodeContent" function forces the deletion of the content of this XMLNode and the subtree.
405     void deleteNodeContent();
406     /**< \note The XMLNode instances that are referring to the part of the subtree that has been deleted CANNOT be used anymore!!. Unexpected results will occur if you continue using them. */
407     void deleteAttribute(int i=0);                   ///< Delete the ith attribute of the current XMLNode
408     void deleteAttribute(XMLCSTR lpszName);          ///< Delete the attribute with the given name (the "strcmp" function is used to find the right attribute)
409     void deleteAttribute(XMLAttribute *anAttribute); ///< Delete the attribute with the name "anAttribute->lpszName" (the "strcmp" function is used to find the right attribute)
410     void deleteText(int i=0);                        ///< Delete the Ith text content of the current XMLNode
411     void deleteText(XMLCSTR lpszValue);              ///< Delete the text content "lpszValue" inside the current XMLNode (direct "pointer-to-pointer" comparison is used to find the right text)
412     void deleteClear(int i=0);                       ///< Delete the Ith clear tag inside the current XMLNode
413     void deleteClear(XMLCSTR lpszValue);             ///< Delete the clear tag "lpszValue" inside the current XMLNode (direct "pointer-to-pointer" comparison is used to find the clear tag)
414     void deleteClear(XMLClear *p);                   ///< Delete the clear tag "p" inside the current XMLNode (direct "pointer-to-pointer" comparison on the lpszName of the clear tag is used to find the clear tag)
415     /** @} */
416 
417     /** @defgroup xmlWOSD ???_WOSD functions.
418      * @ingroup xmlModify
419      *  The strings given as parameters for the "add" and "update" methods that have a name with
420      *  the postfix "_WOSD" (that means "WithOut String Duplication")(for example "addText_WOSD")
421      *  will be free'd by the XMLNode class. For example, it means that this is incorrect:
422      *  \code
423      *     xNode.addText_WOSD("foo");
424      *     xNode.updateAttribute_WOSD("#newcolor" ,NULL,"color");
425      *  \endcode
426      *  In opposition, this is correct:
427      *  \code
428      *     xNode.addText("foo");
429      *     xNode.addText_WOSD(stringDup("foo"));
430      *     xNode.updateAttribute("#newcolor" ,NULL,"color");
431      *     xNode.updateAttribute_WOSD(stringDup("#newcolor"),NULL,"color");
432      *  \endcode
433      *  Typically, you will never do:
434      *  \code
435      *     char *b=(char*)malloc(...);
436      *     xNode.addText(b);
437      *     free(b);
438      *  \endcode
439      *  ... but rather:
440      *  \code
441      *     char *b=(char*)malloc(...);
442      *     xNode.addText_WOSD(b);
443      *  \endcode
444      *  ('free(b)' is performed by the XMLNode class)
445      * @{ */
446     static XMLNode createXMLTopNode_WOSD(XMLSTR lpszName, char isDeclaration=FALSE);                     ///< Create the top node of an XMLNode structure
447     XMLNode        addChild_WOSD(XMLSTR lpszName, char isDeclaration=FALSE, XMLElementPosition pos=-1);  ///< Add a new child node
448     XMLAttribute  *addAttribute_WOSD(XMLSTR lpszName, XMLSTR lpszValue);                                 ///< Add a new attribute
449     XMLCSTR        addText_WOSD(XMLSTR lpszValue, XMLElementPosition pos=-1);                            ///< Add a new text content
450     XMLClear      *addClear_WOSD(XMLSTR lpszValue, XMLCSTR lpszOpen=NULL, XMLCSTR lpszClose=NULL, XMLElementPosition pos=-1); ///< Add a new clear Tag
451 
452     XMLCSTR        updateName_WOSD(XMLSTR lpszName);                                                  ///< change node's name
453     XMLAttribute  *updateAttribute_WOSD(XMLAttribute *newAttribute, XMLAttribute *oldAttribute);      ///< if the attribute to update is missing, a new one will be added
454     XMLAttribute  *updateAttribute_WOSD(XMLSTR lpszNewValue, XMLSTR lpszNewName=NULL,int i=0);        ///< if the attribute to update is missing, a new one will be added
455     XMLAttribute  *updateAttribute_WOSD(XMLSTR lpszNewValue, XMLSTR lpszNewName,XMLCSTR lpszOldName); ///< set lpszNewName=NULL if you don't want to change the name of the attribute if the attribute to update is missing, a new one will be added
456     XMLCSTR        updateText_WOSD(XMLSTR lpszNewValue, int i=0);                                     ///< if the text to update is missing, a new one will be added
457     XMLCSTR        updateText_WOSD(XMLSTR lpszNewValue, XMLCSTR lpszOldValue);                        ///< if the text to update is missing, a new one will be added
458     XMLClear      *updateClear_WOSD(XMLSTR lpszNewContent, int i=0);                                  ///< if the clearTag to update is missing, a new one will be added
459     XMLClear      *updateClear_WOSD(XMLClear *newP,XMLClear *oldP);                                   ///< if the clearTag to update is missing, a new one will be added
460     XMLClear      *updateClear_WOSD(XMLSTR lpszNewValue, XMLCSTR lpszOldValue);                       ///< if the clearTag to update is missing, a new one will be added
461     /** @} */
462 
463     /** @defgroup xmlPosition Position helper functions (use in conjunction with the update&add functions
464      * @ingroup xmlModify
465      * These are some useful functions when you want to insert a childNode, a text or a XMLClearTag in the
466      * middle (at a specified position) of a XMLNode tree already constructed. The value returned by these
467      * methods is to be used as last parameter (parameter 'pos') of addChild, addText or addClear.
468      * @{ */
469     XMLElementPosition positionOfText(int i=0) const;
470     XMLElementPosition positionOfText(XMLCSTR lpszValue) const;
471     XMLElementPosition positionOfClear(int i=0) const;
472     XMLElementPosition positionOfClear(XMLCSTR lpszValue) const;
473     XMLElementPosition positionOfClear(XMLClear *a) const;
474     XMLElementPosition positionOfChildNode(int i=0) const;
475     XMLElementPosition positionOfChildNode(XMLNode x) const;
476     XMLElementPosition positionOfChildNode(XMLCSTR name, int i=0) const; ///< return the position of the ith childNode with the specified name if (name==NULL) return the position of the ith childNode
477     /** @} */
478 
479     /// Enumeration for XML character encoding.
480     typedef enum XMLCharEncoding
481     {
482         char_encoding_error=0,
483         char_encoding_UTF8=1,
484         char_encoding_legacy=2,
485         char_encoding_ShiftJIS=3,
486         char_encoding_GB2312=4,
487         char_encoding_Big5=5,
488         char_encoding_GBK=6     // this is actually the same as Big5
489     } XMLCharEncoding;
490 
491     /** \addtogroup conversions
492      * @{ */
493 
494     /// Sets the global options for the conversions
495     static char setGlobalOptions(XMLCharEncoding characterEncoding=XMLNode::char_encoding_UTF8, char guessWideCharChars=1,
496                                  char dropWhiteSpace=1, char removeCommentsInMiddleOfText=1);
497     /**< The "setGlobalOptions" function allows you to change four global parameters that affect string & file
498      * parsing. First of all, you most-probably will never have to change these 3 global parameters.
499      *
500      * @param guessWideCharChars If "guessWideCharChars"=1 and if this library is compiled in WideChar mode, then the
501      *     XMLNode::parseFile and XMLNode::openFileHelper functions will test if the file contains ASCII
502      *     characters. If this is the case, then the file will be loaded and converted in memory to
503      *     WideChar before being parsed. If 0, no conversion will be performed.
504      *
505      * @param guessWideCharChars If "guessWideCharChars"=1 and if this library is compiled in ASCII/UTF8/char* mode, then the
506      *     XMLNode::parseFile and XMLNode::openFileHelper functions will test if the file contains WideChar
507      *     characters. If this is the case, then the file will be loaded and converted in memory to
508      *     ASCII/UTF8/char* before being parsed. If 0, no conversion will be performed.
509      *
510      * @param characterEncoding This parameter is only meaningful when compiling in char* mode (multibyte character mode).
511      *     In wchar_t* (wide char mode), this parameter is ignored. This parameter should be one of the
512      *     three currently recognized encodings: XMLNode::encoding_UTF8, XMLNode::encoding_ascii,
513      *     XMLNode::encoding_ShiftJIS.
514      *
515      * @param dropWhiteSpace In most situations, text fields containing only white spaces (and carriage returns)
516      *     are useless. Even more, these "empty" text fields are annoying because they increase the
517      *     complexity of the user's code for parsing. So, 99% of the time, it's better to drop
518      *     the "empty" text fields. However The XML specification indicates that no white spaces
519      *     should be lost when parsing the file. So to be perfectly XML-compliant, you should set
520      *     dropWhiteSpace=0. A note of caution: if you set "dropWhiteSpace=0", the parser will be
521      *     slower and your code will be more complex.
522      *
523      * @param removeCommentsInMiddleOfText To explain this parameter, let's consider this code:
524      * \code
525      *        XMLNode x=XMLNode::parseString("<a>foo<!-- hello -->bar<!DOCTYPE world >chu</a>","a");
526      * \endcode
527      *     If removeCommentsInMiddleOfText=0, then we will have:
528      * \code
529      *        x.getText(0) -> "foo"
530      *        x.getText(1) -> "bar"
531      *        x.getText(2) -> "chu"
532      *        x.getClear(0) --> "<!-- hello -->"
533      *        x.getClear(1) --> "<!DOCTYPE world >"
534      * \endcode
535      *     If removeCommentsInMiddleOfText=1, then we will have:
536      * \code
537      *        x.getText(0) -> "foobar"
538      *        x.getText(1) -> "chu"
539      *        x.getClear(0) --> "<!DOCTYPE world >"
540      * \endcode
541      *
542      * \return "0" when there are no errors. If you try to set an unrecognized encoding then the return value will be "1" to signal an error.
543      *
544      * \note Sometime, it's useful to set "guessWideCharChars=0" to disable any conversion
545      * because the test to detect the file-type (ASCII/UTF8/char* or WideChar) may fail (rarely). */
546 
547     /// Guess the character encoding of the string (ascii, utf8 or shift-JIS)
548     static XMLCharEncoding guessCharEncoding(void *buffer, int bufLen, char useXMLEncodingAttribute=1);
549     /**< The "guessCharEncoding" function try to guess the character encoding. You most-probably will never
550      * have to use this function. It then returns the appropriate value of the global parameter
551      * "characterEncoding" described in the XMLNode::setGlobalOptions. The guess is based on the content of a buffer of length
552      * "bufLen" bytes that contains the first bytes (minimum 25 bytes; 200 bytes is a good value) of the
553      * file to be parsed. The XMLNode::openFileHelper function is using this function to automatically compute
554      * the value of the "characterEncoding" global parameter. There are several heuristics used to do the
555      * guess. One of the heuristic is based on the "encoding" attribute. The original XML specifications
556      * forbids to use this attribute to do the guess but you can still use it if you set
557      * "useXMLEncodingAttribute" to 1 (this is the default behavior and the behavior of most parsers).
558      * If an inconsistency in the encoding is detected, then the return value is "0". */
559     /** @} */
560 
561   private:
562       // these are functions and structures used internally by the XMLNode class (don't bother about them):
563 
564       typedef struct XMLNodeDataTag // to allow shallow copy and "intelligent/smart" pointers (automatic delete):
565       {
566           XMLCSTR                lpszName;        // Element name (=NULL if root)
567           int                    nChild,          // Number of child nodes
568                                  nText,           // Number of text fields
569                                  nClear,          // Number of Clear fields (comments)
570                                  nAttribute;      // Number of attributes
571           char                   isDeclaration;   // Whether node is an XML declaration - '<?xml ?>'
572           struct XMLNodeDataTag  *pParent;        // Pointer to parent element (=NULL if root)
573           XMLNode                *pChild;         // Array of child nodes
574           XMLCSTR                *pText;          // Array of text fields
575           XMLClear               *pClear;         // Array of clear fields
576           XMLAttribute           *pAttribute;     // Array of attributes
577           int                    *pOrder;         // order of the child_nodes,text_fields,clear_fields
578           int                    ref_count;       // for garbage collection (smart pointers)
579       } XMLNodeData;
580       XMLNodeData *d;
581 
582       char parseClearTag(void *px, void *pa);
583       char maybeAddTxT(void *pa, XMLCSTR tokenPStr);
584       int ParseXMLElement(void *pXML);
585       void *addToOrder(int memInc, int *_pos, int nc, void *p, int size, XMLElementType xtype);
586       int indexText(XMLCSTR lpszValue) const;
587       int indexClear(XMLCSTR lpszValue) const;
588       XMLNode addChild_priv(int,XMLSTR,char,int);
589       XMLAttribute *addAttribute_priv(int,XMLSTR,XMLSTR);
590       XMLCSTR addText_priv(int,XMLSTR,int);
591       XMLClear *addClear_priv(int,XMLSTR,XMLCSTR,XMLCSTR,int);
592       void emptyTheNode(char force);
593       static inline XMLElementPosition findPosition(XMLNodeData *d, int index, XMLElementType xtype);
594       static int CreateXMLStringR(XMLNodeData *pEntry, XMLSTR lpszMarker, int nFormat);
595       static int removeOrderElement(XMLNodeData *d, XMLElementType t, int index);
596       static void exactMemory(XMLNodeData *d);
597       static int detachFromParent(XMLNodeData *d);
598 } XMLNode;
599 
600 /// This structure is given by the function XMLNode::enumContents.
601 typedef struct XMLNodeContents
602 {
603     /// This dictates what's the content of the XMLNodeContent
604     enum XMLElementType etype;
605     /**< should be an union to access the appropriate data. Compiler does not allow union of object with constructor... too bad. */
606     XMLNode child;
607     XMLAttribute attrib;
608     XMLCSTR text;
609     XMLClear clear;
610 
611 } XMLNodeContents;
612 
613 /** @defgroup StringAlloc String Allocation/Free functions
614  * @ingroup xmlModify
615  * @{ */
616 /// Duplicate (copy in a new allocated buffer) the source string.
617 XMLDLLENTRY XMLSTR stringDup(XMLCSTR source, int cbData=-1);
618 /**< This is
619  * a very handy function when used with all the "XMLNode::*_WOSD" functions (\link xmlWOSD \endlink).
620  * @param cbData If !=0 then cbData is the number of chars to duplicate. New strings allocated with
621  * this function should be free'd using the "freeXMLString" function. */
622 
623 /// to free the string allocated inside the "stringDup" function or the "createXMLString" function.
624 XMLDLLENTRY void freeXMLString(XMLSTR t); // {free(t);}
625 /** @} */
626 
627 /** @defgroup atoX ato? like functions
628  * @ingroup XMLParserGeneral
629  * The "xmlto?" functions are equivalents to the atoi, atol, atof functions.
630  * The only difference is: If the variable "xmlString" is NULL, than the return value
631  * is "defautValue". These 6 functions are only here as "convenience" functions for the
632  * user (they are not used inside the XMLparser). If you don't need them, you can
633  * delete them without any trouble.
634  *
635  * @{ */
636 XMLDLLENTRY char    xmltob(XMLCSTR xmlString,char   defautValue=0);
637 XMLDLLENTRY int     xmltoi(XMLCSTR xmlString,int    defautValue=0);
638 XMLDLLENTRY long    xmltol(XMLCSTR xmlString,long   defautValue=0);
639 XMLDLLENTRY double  xmltof(XMLCSTR xmlString,double defautValue=.0);
640 XMLDLLENTRY XMLCSTR xmltoa(XMLCSTR xmlString,XMLCSTR defautValue=_CXML(""));
641 XMLDLLENTRY XMLCHAR xmltoc(XMLCSTR xmlString,const XMLCHAR defautValue=_CXML('\0'));
642 /** @} */
643 
644 /** @defgroup ToXMLStringTool Helper class to create XML files using "printf", "fprintf", "cout",... functions.
645  * @ingroup XMLParserGeneral
646  * @{ */
647 /// Helper class to create XML files using "printf", "fprintf", "cout",... functions.
648 /** The ToXMLStringTool class helps you creating XML files using "printf", "fprintf", "cout",... functions.
649  * The "ToXMLStringTool" class is processing strings so that all the characters
650  * &,",',<,> are replaced by their XML equivalent:
651  * \verbatim &amp;, &quot;, &apos;, &lt;, &gt; \endverbatim
652  * Using the "ToXMLStringTool class" and the "fprintf function" is THE most efficient
653  * way to produce VERY large XML documents VERY fast.
654  * \note If you are creating from scratch an XML file using the provided XMLNode class
655  * you must not use the "ToXMLStringTool" class (because the "XMLNode" class does the
656  * processing job for you during rendering).*/
657 typedef struct XMLDLLENTRY ToXMLStringTool
658 {
659 public:
ToXMLStringToolToXMLStringTool660     ToXMLStringTool(): buf(NULL),buflen(0){}
661     ~ToXMLStringTool();
662     void freeBuffer();///<call this function when you have finished using this object to release memory used by the internal buffer.
663 
664     XMLSTR toXML(XMLCSTR source);///< returns a pointer to an internal buffer that contains a XML-encoded string based on the "source" parameter.
665 
666     /** The "toXMLUnSafe" function is deprecated because there is a possibility of
667      * "destination-buffer-overflow". It converts the string
668      * "source" to the string "dest". */
669     static XMLSTR toXMLUnSafe(XMLSTR dest,XMLCSTR source); ///< deprecated: use "toXML" instead
670     static int lengthXMLString(XMLCSTR source);            ///< deprecated: use "toXML" instead
671 
672 private:
673     XMLSTR buf;
674     int buflen;
675 } ToXMLStringTool;
676 /** @} */
677 
678 /** @defgroup XMLParserBase64Tool Helper class to include binary data inside XML strings using "Base64 encoding".
679  * @ingroup XMLParserGeneral
680  * @{ */
681 /// Helper class to include binary data inside XML strings using "Base64 encoding".
682 /** The "XMLParserBase64Tool" class allows you to include any binary data (images, sounds,...)
683  * into an XML document using "Base64 encoding". This class is completely
684  * separated from the rest of the xmlParser library and can be removed without any problem.
685  * To include some binary data into an XML file, you must convert the binary data into
686  * standard text (using "encode"). To retrieve the original binary data from the
687  * b64-encoded text included inside the XML file, use "decode". Alternatively, these
688  * functions can also be used to "encrypt/decrypt" some critical data contained inside
689  * the XML (it's not a strong encryption at all, but sometimes it can be useful). */
690 typedef struct XMLDLLENTRY XMLParserBase64Tool
691 {
692 public:
XMLParserBase64ToolXMLParserBase64Tool693     XMLParserBase64Tool(): buf(NULL),buflen(0){}
694     ~XMLParserBase64Tool();
695     void freeBuffer();///< Call this function when you have finished using this object to release memory used by the internal buffer.
696 
697     /**
698      * @param formatted If "formatted"=true, some space will be reserved for a carriage-return every 72 chars. */
699     static int encodeLength(int inBufLen, char formatted=0); ///< return the length of the base64 string that encodes a data buffer of size inBufLen bytes.
700 
701     /**
702      * The "base64Encode" function returns a string containing the base64 encoding of "inByteLen" bytes
703      * from "inByteBuf". If "formatted" parameter is true, then there will be a carriage-return every 72 chars.
704      * The string will be free'd when the XMLParserBase64Tool object is deleted.
705      * All returned strings are sharing the same memory space. */
706     XMLSTR encode(unsigned char *inByteBuf, unsigned int inByteLen, char formatted=0); ///< returns a pointer to an internal buffer containing the base64 string containing the binary data encoded from "inByteBuf"
707 
708     /// returns the number of bytes which will be decoded from "inString".
709     static unsigned int decodeSize(XMLCSTR inString, XMLError *xe=NULL);
710 
711     /**
712      * The "decode" function returns a pointer to a buffer containing the binary data decoded from "inString"
713      * The output buffer will be free'd when the XMLParserBase64Tool object is deleted.
714      * All output buffer are sharing the same memory space.
715      * @param inString If "instring" is malformed, NULL will be returned */
716     unsigned char* decode(XMLCSTR inString, int *outByteLen=NULL, XMLError *xe=NULL); ///< returns a pointer to an internal buffer containing the binary data decoded from "inString"
717 
718     /**
719      * decodes data from "inString" to "outByteBuf". You need to provide the size (in byte) of "outByteBuf"
720      * in "inMaxByteOutBuflen". If "outByteBuf" is not large enough or if data is malformed, then "FALSE"
721      * will be returned; otherwise "TRUE". */
722     static unsigned char decode(XMLCSTR inString, unsigned char *outByteBuf, int inMaxByteOutBuflen, XMLError *xe=NULL); ///< deprecated.
723 
724 private:
725     void *buf;
726     int buflen;
727     void alloc(int newsize);
728 }XMLParserBase64Tool;
729 /** @} */
730 
731 #undef XMLDLLENTRY
732 
733 #endif
734