| 1 | /** | 
|---|
| 2 |  **************************************************************************** | 
|---|
| 3 |  * <P> XML.c - implementation file for basic XML parser written in ANSI C++ | 
|---|
| 4 |  * for portability. It works by using recursion and a node tree for breaking | 
|---|
| 5 |  * down the elements of an XML document.  </P> | 
|---|
| 6 |  * | 
|---|
| 7 |  * @version     V2.33 | 
|---|
| 8 |  * @author      Frank Vanden Berghen | 
|---|
| 9 |  * | 
|---|
| 10 |  * BSD license: | 
|---|
| 11 |  * Copyright (c) 2002, Frank Vanden Berghen | 
|---|
| 12 |  * All rights reserved. | 
|---|
| 13 |  * Redistribution and use in source and binary forms, with or without | 
|---|
| 14 |  * modification, are permitted provided that the following conditions are met: | 
|---|
| 15 |  * | 
|---|
| 16 |  *     * Redistributions of source code must retain the above copyright | 
|---|
| 17 |  *       notice, this list of conditions and the following disclaimer. | 
|---|
| 18 |  *     * Redistributions in binary form must reproduce the above copyright | 
|---|
| 19 |  *       notice, this list of conditions and the following disclaimer in the | 
|---|
| 20 |  *       documentation and/or other materials provided with the distribution. | 
|---|
| 21 |  *     * Neither the name of the Frank Vanden Berghen nor the | 
|---|
| 22 |  *       names of its contributors may be used to endorse or promote products | 
|---|
| 23 |  *       derived from this software without specific prior written permission. | 
|---|
| 24 |  * | 
|---|
| 25 |  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY | 
|---|
| 26 |  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 
|---|
| 27 |  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 
|---|
| 28 |  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY | 
|---|
| 29 |  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 
|---|
| 30 |  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 
|---|
| 31 |  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 
|---|
| 32 |  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
|---|
| 33 |  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 
|---|
| 34 |  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|---|
| 35 |  * | 
|---|
| 36 |  **************************************************************************** | 
|---|
| 37 |  */ | 
|---|
| 38 | #ifndef __INCLUDE_XML_NODE__ | 
|---|
| 39 | #define __INCLUDE_XML_NODE__ | 
|---|
| 40 |  | 
|---|
| 41 | #include <stdlib.h> | 
|---|
| 42 |  | 
|---|
| 43 | #ifdef _UNICODE | 
|---|
| 44 | // If you comment the next "define" line then the library will never "switch to" _UNICODE (wchar_t*) mode (16/32 bits per characters). | 
|---|
| 45 | // This is useful when you get error messages like: | 
|---|
| 46 | //    'XMLNode::openFileHelper' : cannot convert parameter 2 from 'const char [5]' to 'const wchar_t *' | 
|---|
| 47 | // The _XMLWIDECHAR preprocessor variable force the XMLParser library into either utf16/32-mode (the proprocessor variable | 
|---|
| 48 | // must be defined) or utf8-mode(the pre-processor variable must be undefined). | 
|---|
| 49 | //#define _XMLWIDECHAR | 
|---|
| 50 | #endif | 
|---|
| 51 |  | 
|---|
| 52 | #if defined(WIN32) || defined(UNDER_CE) | 
|---|
| 53 | // comment the next line if you are under windows and the compiler is not Microsoft Visual Studio (6.0 or .NET) | 
|---|
| 54 | #define _XMLWINDOWS | 
|---|
| 55 | #endif | 
|---|
| 56 |  | 
|---|
| 57 | #ifdef XMLDLLENTRY | 
|---|
| 58 | #undef XMLDLLENTRY | 
|---|
| 59 | #endif | 
|---|
| 60 | #ifdef _USE_XMLPARSER_DLL | 
|---|
| 61 | #ifdef _DLL_EXPORTS_ | 
|---|
| 62 | #define XMLDLLENTRY __declspec(dllexport) | 
|---|
| 63 | #else | 
|---|
| 64 | #define XMLDLLENTRY __declspec(dllimport) | 
|---|
| 65 | #endif | 
|---|
| 66 | #else | 
|---|
| 67 | #define XMLDLLENTRY | 
|---|
| 68 | #endif | 
|---|
| 69 |  | 
|---|
| 70 | // 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) | 
|---|
| 71 | //#define XML_NO_WIDE_CHAR | 
|---|
| 72 |  | 
|---|
| 73 | #ifdef XML_NO_WIDE_CHAR | 
|---|
| 74 | #undef _XMLWINDOWS | 
|---|
| 75 | #undef _XMLWIDECHAR | 
|---|
| 76 | #endif | 
|---|
| 77 |  | 
|---|
| 78 | #ifdef _XMLWINDOWS | 
|---|
| 79 | #include <tchar.h> | 
|---|
| 80 | #else | 
|---|
| 81 | #define XMLDLLENTRY | 
|---|
| 82 | #ifndef XML_NO_WIDE_CHAR | 
|---|
| 83 | #include <wchar.h> // to have 'wcsrtombs' for ANSI version | 
|---|
| 84 |                    // to have 'mbsrtowcs' for WIDECHAR version | 
|---|
| 85 | #endif | 
|---|
| 86 | #endif | 
|---|
| 87 |  | 
|---|
| 88 | // Some common types for char set portable code | 
|---|
| 89 | #ifdef _XMLWIDECHAR | 
|---|
| 90 |     #ifndef _X | 
|---|
| 91 |         #define _X(c) L ## c | 
|---|
| 92 |     #endif | 
|---|
| 93 |     #define XMLCSTR const wchar_t * | 
|---|
| 94 |     #define XMLSTR  wchar_t * | 
|---|
| 95 |     #define XMLCHAR wchar_t | 
|---|
| 96 | #else | 
|---|
| 97 |     #ifndef _X | 
|---|
| 98 |         #define _X(c) c | 
|---|
| 99 |     #endif | 
|---|
| 100 |     #define XMLCSTR const char * | 
|---|
| 101 |     #define XMLSTR  char * | 
|---|
| 102 |     #define XMLCHAR char | 
|---|
| 103 | #endif | 
|---|
| 104 | #ifndef FALSE | 
|---|
| 105 |     #define FALSE 0 | 
|---|
| 106 | #endif /* FALSE */ | 
|---|
| 107 | #ifndef TRUE | 
|---|
| 108 |     #define TRUE 1 | 
|---|
| 109 | #endif /* TRUE */ | 
|---|
| 110 |  | 
|---|
| 111 |  | 
|---|
| 112 | // Enumeration for XML parse errors. | 
|---|
| 113 | typedef enum XMLError | 
|---|
| 114 | { | 
|---|
| 115 |     eXMLErrorNone = 0, | 
|---|
| 116 |     eXMLErrorMissingEndTag, | 
|---|
| 117 |     eXMLErrorNoXMLTagFound, | 
|---|
| 118 |     eXMLErrorEmpty, | 
|---|
| 119 |     eXMLErrorMissingTagName, | 
|---|
| 120 |     eXMLErrorMissingEndTagName, | 
|---|
| 121 |     eXMLErrorUnmatchedEndTag, | 
|---|
| 122 |     eXMLErrorUnmatchedEndClearTag, | 
|---|
| 123 |     eXMLErrorUnexpectedToken, | 
|---|
| 124 |     eXMLErrorNoElements, | 
|---|
| 125 |     eXMLErrorFileNotFound, | 
|---|
| 126 |     eXMLErrorFirstTagNotFound, | 
|---|
| 127 |     eXMLErrorUnknownCharacterEntity, | 
|---|
| 128 |     eXMLErrorCharConversionError, | 
|---|
| 129 |     eXMLErrorCannotOpenWriteFile, | 
|---|
| 130 |     eXMLErrorCannotWriteFile, | 
|---|
| 131 |  | 
|---|
| 132 |     eXMLErrorBase64DataSizeIsNotMultipleOf4, | 
|---|
| 133 |     eXMLErrorBase64DecodeIllegalCharacter, | 
|---|
| 134 |     eXMLErrorBase64DecodeTruncatedData, | 
|---|
| 135 |     eXMLErrorBase64DecodeBufferTooSmall | 
|---|
| 136 | } XMLError; | 
|---|
| 137 |  | 
|---|
| 138 |  | 
|---|
| 139 | // Enumeration used to manage type of data. Use in conjunction with structure XMLNodeContents | 
|---|
| 140 | typedef enum XMLElementType | 
|---|
| 141 | { | 
|---|
| 142 |     eNodeChild=0, | 
|---|
| 143 |     eNodeAttribute=1, | 
|---|
| 144 |     eNodeText=2, | 
|---|
| 145 |     eNodeClear=3, | 
|---|
| 146 |     eNodeNULL=4 | 
|---|
| 147 | } XMLElementType; | 
|---|
| 148 |  | 
|---|
| 149 | // Structure used to obtain error details if the parse fails. | 
|---|
| 150 | typedef struct XMLResults | 
|---|
| 151 | { | 
|---|
| 152 |     enum XMLError error; | 
|---|
| 153 |     int  nLine,nColumn; | 
|---|
| 154 | } XMLResults; | 
|---|
| 155 |  | 
|---|
| 156 | // Structure for XML clear (unformatted) node (usually comments) | 
|---|
| 157 | typedef struct XMLClear { | 
|---|
| 158 |     XMLCSTR lpszValue; XMLCSTR lpszOpenTag; XMLCSTR lpszCloseTag; | 
|---|
| 159 | } XMLClear; | 
|---|
| 160 |  | 
|---|
| 161 | // Structure for XML attribute. | 
|---|
| 162 | typedef struct XMLAttribute { | 
|---|
| 163 |     XMLCSTR lpszName; XMLCSTR lpszValue; | 
|---|
| 164 | } XMLAttribute; | 
|---|
| 165 |  | 
|---|
| 166 | // XMLElementPosition are not interchangeable with simple indexes | 
|---|
| 167 | typedef int XMLElementPosition; | 
|---|
| 168 |  | 
|---|
| 169 | struct XMLNodeContents; | 
|---|
| 170 |  | 
|---|
| 171 | typedef struct XMLDLLENTRY XMLNode | 
|---|
| 172 | { | 
|---|
| 173 |   private: | 
|---|
| 174 |  | 
|---|
| 175 |     struct XMLNodeDataTag; | 
|---|
| 176 |  | 
|---|
| 177 |     // protected constructors: use one of these four methods to get your first instance of XMLNode: | 
|---|
| 178 |     //  - parseString | 
|---|
| 179 |     //  - parseFile | 
|---|
| 180 |     //  - openFileHelper | 
|---|
| 181 |     //  - createXMLTopNode | 
|---|
| 182 |     XMLNode(struct XMLNodeDataTag *pParent, XMLSTR lpszName, char isDeclaration); | 
|---|
| 183 |     XMLNode(struct XMLNodeDataTag *p); | 
|---|
| 184 |  | 
|---|
| 185 |   public: | 
|---|
| 186 |  | 
|---|
| 187 |     // You can create your first instance of XMLNode with these 4 functions: | 
|---|
| 188 |     // (see complete explanation of parameters below) | 
|---|
| 189 |  | 
|---|
| 190 |     static XMLNode createXMLTopNode(XMLCSTR lpszName, char isDeclaration=FALSE); | 
|---|
| 191 |     static XMLNode parseString   (XMLCSTR  lpXMLString, XMLCSTR tag=NULL, XMLResults *pResults=NULL); | 
|---|
| 192 |     static XMLNode parseFile     (XMLCSTR     filename, XMLCSTR tag=NULL, XMLResults *pResults=NULL); | 
|---|
| 193 |     static XMLNode openFileHelper(XMLCSTR     filename, XMLCSTR tag=NULL                           ); | 
|---|
| 194 |  | 
|---|
| 195 |     // The tag parameter should be the name of the first tag inside the XML file. | 
|---|
| 196 |     // If the tag parameter is omitted, the 3 functions return a node that represents | 
|---|
| 197 |     // the head of the xml document including the declaration term (<? ... ?>). | 
|---|
| 198 |  | 
|---|
| 199 |     // The "openFileHelper" reports to the screen all the warnings & errors that occurred during | 
|---|
| 200 |     // parsing of the XML file. Since each application has its own way to report and deal with errors, | 
|---|
| 201 |     // you should rather use the "parseFile" function to parse XML files and program yourself thereafter | 
|---|
| 202 |     // an "error reporting" tailored for your needs (instead of using the very crude "error reporting" | 
|---|
| 203 |     // mechanism included inside the "openFileHelper" function). | 
|---|
| 204 |  | 
|---|
| 205 |     // If the XML document is corrupted: | 
|---|
| 206 |     //   * The "openFileHelper" method will: | 
|---|
| 207 |     //         - display an error message on the console (or inside a messageBox for windows). | 
|---|
| 208 |     //         - stop execution (exit). | 
|---|
| 209 |     //     I suggest that you write your own "openFileHelper" method tailored to your needs. | 
|---|
| 210 |     //   * The 2 other methods will initialize the "pResults" variable with some information that | 
|---|
| 211 |     //     can be used to trace the error. | 
|---|
| 212 |     //   * If you still want to parse the file, you can use the APPROXIMATE_PARSING option as | 
|---|
| 213 |     //     explained inside the note at the beginning of the "xmlParser.cpp" file. | 
|---|
| 214 |     // You can have a user-friendly explanation of the parsing error with this function: | 
|---|
| 215 |     static XMLCSTR getError(XMLError error); | 
|---|
| 216 |     static XMLCSTR getVersion(); | 
|---|
| 217 |  | 
|---|
| 218 |     XMLCSTR getName() const;                                         // name of the node | 
|---|
| 219 |     XMLCSTR getText(int i=0) const;                                  // return ith text field | 
|---|
| 220 |     int nText() const;                                               // nbr of text field | 
|---|
| 221 |     XMLNode getParentNode() const;                                   // return the parent node | 
|---|
| 222 |     XMLNode getChildNode(int i=0) const;                             // return ith child node | 
|---|
| 223 |     XMLNode getChildNode(XMLCSTR name, int i)  const;                // return ith child node with specific name | 
|---|
| 224 |                                                                      //     (return an empty node if failing) | 
|---|
| 225 |     XMLNode getChildNode(XMLCSTR name, int *i=NULL) const;           // return next child node with specific name | 
|---|
| 226 |                                                                      //     (return an empty node if failing) | 
|---|
| 227 |     XMLNode getChildNodeWithAttribute(XMLCSTR tagName,               // return child node with specific name/attribute | 
|---|
| 228 |                                       XMLCSTR attributeName,         //     (return an empty node if failing) | 
|---|
| 229 |                                       XMLCSTR attributeValue=NULL,   // | 
|---|
| 230 |                                       int *i=NULL)  const;           // | 
|---|
| 231 |     int nChildNode(XMLCSTR name) const;                              // return the number of child node with specific name | 
|---|
| 232 |     int nChildNode() const;                                          // nbr of child node | 
|---|
| 233 |     XMLAttribute getAttribute(int i=0) const;                        // return ith attribute | 
|---|
| 234 |     XMLCSTR      getAttributeName(int i=0) const;                    // return ith attribute name | 
|---|
| 235 |     XMLCSTR      getAttributeValue(int i=0) const;                   // return ith attribute value | 
|---|
| 236 |     char  isAttributeSet(XMLCSTR name) const;                        // test if an attribute with a specific name is given | 
|---|
| 237 |     XMLCSTR getAttribute(XMLCSTR name, int i) const;                 // return ith attribute content with specific name | 
|---|
| 238 |                                                                      //     (return a NULL if failing) | 
|---|
| 239 |     XMLCSTR getAttribute(XMLCSTR name, int *i=NULL) const;           // return next attribute content with specific name | 
|---|
| 240 |                                                                      //     (return a NULL if failing) | 
|---|
| 241 |     int nAttribute() const;                                          // nbr of attribute | 
|---|
| 242 |     XMLClear getClear(int i=0) const;                                // return ith clear field (comments) | 
|---|
| 243 |     int nClear() const;                                              // nbr of clear field | 
|---|
| 244 |     XMLSTR createXMLString(int nFormat=1, int *pnSize=NULL) const;   // create XML string starting from current XMLNode | 
|---|
| 245 |                                                                      // if nFormat==0, no formatting is required | 
|---|
| 246 |                                                                      // otherwise this returns an user friendly XML string from a | 
|---|
| 247 |                                                                      // given element with appropriate white spaces and carriage returns. | 
|---|
| 248 |                                                                      // if pnSize is given it returns the size in character of the string. | 
|---|
| 249 |     XMLError writeToFile(XMLCSTR filename, const char *encoding=NULL, char nFormat=1) const; | 
|---|
| 250 |                                                                      // Save the content of an xmlNode inside a file. | 
|---|
| 251 |                                                                      // The nFormat parameter has the same meaning as in the | 
|---|
| 252 |                                                                      // createXMLString function. If the global parameter | 
|---|
| 253 |                                                                      // "characterEncoding==encoding_UTF8", then the "encoding" parameter is | 
|---|
| 254 |                                                                      // ignored and always set to "utf-8". If the global parameter | 
|---|
| 255 |                                                                      // "characterEncoding==encoding_ShiftJIS", then the "encoding" parameter | 
|---|
| 256 |                                                                      // is ignored and always set to "SHIFT-JIS". If "_XMLWIDECHAR=1", then | 
|---|
| 257 |                                                                      // the "encoding" parameter is ignored and always set to "utf-16". | 
|---|
| 258 |                                                                      // If no "encoding" parameter is given the "ISO-8859-1" encoding is used. | 
|---|
| 259 |     XMLNodeContents enumContents(XMLElementPosition i) const;           // enumerate all the different contents (attribute,child,text, | 
|---|
| 260 |                                                                      //     clear) of the current XMLNode. The order is reflecting | 
|---|
| 261 |                                                                      //     the order of the original file/string. | 
|---|
| 262 |                                                                      //     NOTE: 0 <= i < nElement(); | 
|---|
| 263 |     int nElement() const;                                            // nbr of different contents for current node | 
|---|
| 264 |     char isEmpty() const;                                            // is this node Empty? | 
|---|
| 265 |     char isDeclaration() const;                                      // is this node a declaration <? .... ?> | 
|---|
| 266 |     XMLNode deepCopy() const;                                        // deep copy (duplicate/clone) a XMLNode | 
|---|
| 267 |     static XMLNode emptyNode();                                      // return XMLNode::emptyXMLNode; | 
|---|
| 268 |  | 
|---|
| 269 | // to allow shallow/fast copy: | 
|---|
| 270 |     ~XMLNode(); | 
|---|
| 271 |     XMLNode(const XMLNode &A); | 
|---|
| 272 |     XMLNode& operator=( const XMLNode& A ); | 
|---|
| 273 |  | 
|---|
| 274 |     XMLNode(): d(NULL){}; | 
|---|
| 275 |     static XMLNode emptyXMLNode; | 
|---|
| 276 |     static XMLClear emptyXMLClear; | 
|---|
| 277 |     static XMLAttribute emptyXMLAttribute; | 
|---|
| 278 |  | 
|---|
| 279 |     // The following functions allows you to create from scratch (or update) a XMLNode structure | 
|---|
| 280 |     // Start by creating your top node with the "createXMLTopNode" function and then add new nodes with the "addChild" function. | 
|---|
| 281 |     // The parameter 'pos' gives the position where the childNode, the text or the XMLClearTag will be inserted. | 
|---|
| 282 |     // The default value (pos=-1) inserts at the end. The value (pos=0) insert at the beginning (Insertion at the beginning is slower than at the end). | 
|---|
| 283 |     // REMARK: 0 <= pos < nChild()+nText()+nClear() | 
|---|
| 284 |     XMLNode       addChild(XMLCSTR lpszName, char isDeclaration=FALSE, XMLElementPosition pos=-1); | 
|---|
| 285 |     XMLAttribute *addAttribute(XMLCSTR lpszName, XMLCSTR lpszValuev); | 
|---|
| 286 |     XMLCSTR       addText(XMLCSTR lpszValue, XMLElementPosition pos=-1); | 
|---|
| 287 |     XMLClear     *addClear(XMLCSTR lpszValue, XMLCSTR lpszOpen=NULL, XMLCSTR lpszClose=NULL, XMLElementPosition pos=-1); | 
|---|
| 288 |                                                                        // default values: lpszOpen ="<![CDATA[" | 
|---|
| 289 |                                                                        //                 lpszClose="]]>" | 
|---|
| 290 |     XMLNode       addChild(XMLNode nodeToAdd, XMLElementPosition pos=-1); // If the "nodeToAdd" has some parents, it will be detached | 
|---|
| 291 |                                                                        // from it's parents before being attached to the current XMLNode | 
|---|
| 292 |     // Some update functions: | 
|---|
| 293 |     XMLCSTR       updateName(XMLCSTR lpszName);                                                    // change node's name | 
|---|
| 294 |     XMLAttribute *updateAttribute(XMLAttribute *newAttribute, XMLAttribute *oldAttribute);         // if the attribute to update is missing, a new one will be added | 
|---|
| 295 |     XMLAttribute *updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName=NULL,int i=0);         // if the attribute to update is missing, a new one will be added | 
|---|
| 296 |     XMLAttribute *updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName,XMLCSTR lpszOldName);  // set lpszNewName=NULL if you don't want to change the name of the attribute | 
|---|
| 297 |                                                                                                    // if the attribute to update is missing, a new one will be added | 
|---|
| 298 |     XMLCSTR       updateText(XMLCSTR lpszNewValue, int i=0);                                       // if the text to update is missing, a new one will be added | 
|---|
| 299 |     XMLCSTR       updateText(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue);                          // if the text to update is missing, a new one will be added | 
|---|
| 300 |     XMLClear     *updateClear(XMLCSTR lpszNewContent, int i=0);                                    // if the clearTag to update is missing, a new one will be added | 
|---|
| 301 |     XMLClear     *updateClear(XMLClear *newP,XMLClear *oldP);                                      // if the clearTag to update is missing, a new one will be added | 
|---|
| 302 |     XMLClear     *updateClear(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue);                         // if the clearTag to update is missing, a new one will be added | 
|---|
| 303 |  | 
|---|
| 304 |     // Some deletion functions: | 
|---|
| 305 |     void deleteNodeContent();  // delete the content of this XMLNode and the subtree. | 
|---|
| 306 |     void deleteAttribute(XMLCSTR lpszName); | 
|---|
| 307 |     void deleteAttribute(int i=0); | 
|---|
| 308 |     void deleteAttribute(XMLAttribute *anAttribute); | 
|---|
| 309 |     void deleteText(int i=0); | 
|---|
| 310 |     void deleteText(XMLCSTR lpszValue); | 
|---|
| 311 |     void deleteClear(int i=0); | 
|---|
| 312 |     void deleteClear(XMLClear *p); | 
|---|
| 313 |     void deleteClear(XMLCSTR lpszValue); | 
|---|
| 314 |  | 
|---|
| 315 |     // The strings given as parameters for the following add and update methods (all these methods have | 
|---|
| 316 |     // a name with the postfix "_WOSD" that means "WithOut String Duplication" ) will be free'd by the | 
|---|
| 317 |     // XMLNode class. For example, it means that this is incorrect: | 
|---|
| 318 |     //    xNode.addText_WOSD("foo"); | 
|---|
| 319 |     //    xNode.updateAttribute_WOSD("#newcolor" ,NULL,"color"); | 
|---|
| 320 |     // In opposition, this is correct: | 
|---|
| 321 |     //    xNode.addText("foo"); | 
|---|
| 322 |     //    xNode.addText_WOSD(stringDup("foo")); | 
|---|
| 323 |     //    xNode.updateAttribute("#newcolor" ,NULL,"color"); | 
|---|
| 324 |     //    xNode.updateAttribute_WOSD(stringDup("#newcolor"),NULL,"color"); | 
|---|
| 325 |     // Typically, you will never do: | 
|---|
| 326 |     //    char *b=(char*)malloc(...); | 
|---|
| 327 |     //    xNode.addText(b); | 
|---|
| 328 |     //    free(b); | 
|---|
| 329 |     // ... but rather: | 
|---|
| 330 |     //    char *b=(char*)malloc(...); | 
|---|
| 331 |     //    xNode.addText_WOSD(b); | 
|---|
| 332 |     //    ('free(b)' is performed by the XMLNode class) | 
|---|
| 333 |  | 
|---|
| 334 |     static XMLNode createXMLTopNode_WOSD(XMLSTR lpszName, char isDeclaration=FALSE); | 
|---|
| 335 |     XMLNode        addChild_WOSD(XMLSTR lpszName, char isDeclaration=FALSE, XMLElementPosition pos=-1); | 
|---|
| 336 |     XMLAttribute  *addAttribute_WOSD(XMLSTR lpszName, XMLSTR lpszValue); | 
|---|
| 337 |     XMLCSTR        addText_WOSD(XMLSTR lpszValue, XMLElementPosition pos=-1); | 
|---|
| 338 |     XMLClear      *addClear_WOSD(XMLSTR lpszValue, XMLCSTR lpszOpen=NULL, XMLCSTR lpszClose=NULL, XMLElementPosition pos=-1); | 
|---|
| 339 |  | 
|---|
| 340 |     XMLCSTR        updateName_WOSD(XMLSTR lpszName); | 
|---|
| 341 |     XMLAttribute  *updateAttribute_WOSD(XMLAttribute *newAttribute, XMLAttribute *oldAttribute); | 
|---|
| 342 |     XMLAttribute  *updateAttribute_WOSD(XMLSTR lpszNewValue, XMLSTR lpszNewName=NULL,int i=0); | 
|---|
| 343 |     XMLAttribute  *updateAttribute_WOSD(XMLSTR lpszNewValue, XMLSTR lpszNewName,XMLCSTR lpszOldName); | 
|---|
| 344 |     XMLCSTR        updateText_WOSD(XMLSTR lpszNewValue, int i=0); | 
|---|
| 345 |     XMLCSTR        updateText_WOSD(XMLSTR lpszNewValue, XMLCSTR lpszOldValue); | 
|---|
| 346 |     XMLClear      *updateClear_WOSD(XMLSTR lpszNewContent, int i=0); | 
|---|
| 347 |     XMLClear      *updateClear_WOSD(XMLClear *newP,XMLClear *oldP); | 
|---|
| 348 |     XMLClear      *updateClear_WOSD(XMLSTR lpszNewValue, XMLCSTR lpszOldValue); | 
|---|
| 349 |  | 
|---|
| 350 |     // These are some useful functions when you want to insert a childNode, a text or a XMLClearTag in the | 
|---|
| 351 |     // middle (at a specified position) of a XMLNode tree already constructed. The value returned by these | 
|---|
| 352 |     // methods is to be used as last parameter (parameter 'pos') of addChild, addText or addClear. | 
|---|
| 353 |     XMLElementPosition positionOfText(int i=0) const; | 
|---|
| 354 |     XMLElementPosition positionOfText(XMLCSTR lpszValue) const; | 
|---|
| 355 |     XMLElementPosition positionOfClear(int i=0) const; | 
|---|
| 356 |     XMLElementPosition positionOfClear(XMLCSTR lpszValue) const; | 
|---|
| 357 |     XMLElementPosition positionOfClear(XMLClear *a) const; | 
|---|
| 358 |     XMLElementPosition positionOfChildNode(int i=0) const; | 
|---|
| 359 |     XMLElementPosition positionOfChildNode(XMLNode x) const; | 
|---|
| 360 |     XMLElementPosition positionOfChildNode(XMLCSTR name, int i=0) const; // return the position of the ith childNode with the specified name | 
|---|
| 361 |                                                                       // if (name==NULL) return the position of the ith childNode | 
|---|
| 362 |  | 
|---|
| 363 |     // The setGlobalOptions function allows you to change tree global parameters that affect string&file | 
|---|
| 364 |     // parsing. First of all, you most-probably will never have to change these 3 global parameters. | 
|---|
| 365 |     // The return value of the setGlobalOptions function is "0" when there are no errors. If you try to | 
|---|
| 366 |     // set an unrecognized encoding then the return value will be "1" to signal an error. | 
|---|
| 367 |     // | 
|---|
| 368 |     // About the "guessWideCharChars" parameter: | 
|---|
| 369 |     //     If "guessWideCharChars=1" and if this library is compiled in WideChar mode, then the | 
|---|
| 370 |     //     "parseFile" and "openFileHelper" functions will test if the file contains ASCII | 
|---|
| 371 |     //     characters. If this is the case, then the file will be loaded and converted in memory to | 
|---|
| 372 |     //     WideChar before being parsed. If "guessWideCharChars=0", no conversion will | 
|---|
| 373 |     //     be performed. | 
|---|
| 374 |     // | 
|---|
| 375 |     //     If "guessWideCharChars=1" and if this library is compiled in ASCII/UTF8/char* mode, then the | 
|---|
| 376 |     //     "parseFile" and "openFileHelper" functions will test if the file contains WideChar | 
|---|
| 377 |     //     characters. If this is the case, then the file will be loaded and converted in memory to | 
|---|
| 378 |     //     ASCII/UTF8/char* before being parsed. If "guessWideCharChars=0", no conversion will | 
|---|
| 379 |     //     be performed | 
|---|
| 380 |     // | 
|---|
| 381 |     //     Sometime, it's useful to set "guessWideCharChars=0" to disable any conversion | 
|---|
| 382 |     //     because the test to detect the file-type (ASCII/UTF8/char* or WideChar) may fail (rarely). | 
|---|
| 383 |     // | 
|---|
| 384 |     // About the "characterEncoding" parameter: | 
|---|
| 385 |     //     This parameter is only meaningful when compiling in char* mode (multibyte character mode). | 
|---|
| 386 |     //     In wchar_t* (wide char mode), this parameter is ignored. This parameter should be one of the | 
|---|
| 387 |     //     three currently recognized encodings: XMLNode::encoding_UTF8, XMLNode::encoding_ascii, | 
|---|
| 388 |     //     XMLNode::encoding_ShiftJIS. | 
|---|
| 389 |     // | 
|---|
| 390 |     // About the "dropWhiteSpace" parameter: | 
|---|
| 391 |     //     In most situations, text fields containing only white spaces (and carriage returns) | 
|---|
| 392 |     //     are useless. Even more, these "empty" text fields are annoying because they increase the | 
|---|
| 393 |     //     complexity of the user's code for parsing. So, 99% of the time, it's better to drop | 
|---|
| 394 |     //     the "empty" text fields. However The XML specification indicates that no white spaces | 
|---|
| 395 |     //     should be lost when parsing the file. So to be perfectly XML-compliant, you should set | 
|---|
| 396 |     //     dropWhiteSpace=0. A note of caution: if you set "dropWhiteSpace=0", the parser will be | 
|---|
| 397 |     //     slower and your code will be more complex. | 
|---|
| 398 |  | 
|---|
| 399 |     // Enumeration for XML character encoding. | 
|---|
| 400 |     typedef enum XMLCharEncoding { encoding_UTF8=1, encoding_ascii=2, encoding_ShiftJIS=3 } XMLCharEncoding; | 
|---|
| 401 |  | 
|---|
| 402 |     static char setGlobalOptions(XMLCharEncoding characterEncoding=XMLNode::encoding_UTF8, char guessWideCharChars=1, char dropWhiteSpace=1); | 
|---|
| 403 |  | 
|---|
| 404 |     // The next function try to guess the character encoding. You most-probably will never | 
|---|
| 405 |     // have to use this function. It then returns the appropriate value of the global parameter | 
|---|
| 406 |     // "characterEncoding" described above. The guess is based on the content of a buffer of length | 
|---|
| 407 |     // "bufLen" bytes that contains the first bytes (minimum 25 bytes; 200 bytes is a good value) of the | 
|---|
| 408 |     // file to be parsed. The "openFileHelper" function is using this function to automatically compute | 
|---|
| 409 |     // the value of the "characterEncoding" global parameter. There are several heuristics used to do the | 
|---|
| 410 |     // guess. One of the heuristic is based on the "encoding" attribute. The original XML specifications | 
|---|
| 411 |     // forbids to use this attribute to do the guess but you can still use it if you set | 
|---|
| 412 |     // "useXMLEncodingAttribute" to 1 (this is the default behavior and the behavior of most parsers). | 
|---|
| 413 |     // If an inconsistency in the encoding is detected, then the return value is "0". | 
|---|
| 414 |  | 
|---|
| 415 |     static XMLCharEncoding guessCharEncoding(void *buffer, int bufLen, char useXMLEncodingAttribute=1); | 
|---|
| 416 |  | 
|---|
| 417 |   private: | 
|---|
| 418 |  | 
|---|
| 419 | // these are functions and structures used internally by the XMLNode class (don't bother about them): | 
|---|
| 420 |  | 
|---|
| 421 |       typedef struct XMLNodeDataTag // to allow shallow copy and "intelligent/smart" pointers (automatic delete): | 
|---|
| 422 |       { | 
|---|
| 423 |           XMLCSTR                lpszName;        // Element name (=NULL if root) | 
|---|
| 424 |           int                    nChild,          // Number of child nodes | 
|---|
| 425 |                                  nText,           // Number of text fields | 
|---|
| 426 |                                  nClear,          // Number of Clear fields (comments) | 
|---|
| 427 |                                  nAttribute;      // Number of attributes | 
|---|
| 428 |           char                   isDeclaration;   // Whether node is an XML declaration - '<?xml ?>' | 
|---|
| 429 |           struct XMLNodeDataTag  *pParent;        // Pointer to parent element (=NULL if root) | 
|---|
| 430 |           XMLNode                *pChild;         // Array of child nodes | 
|---|
| 431 |           XMLCSTR                *pText;          // Array of text fields | 
|---|
| 432 |           XMLClear               *pClear;         // Array of clear fields | 
|---|
| 433 |           XMLAttribute           *pAttribute;     // Array of attributes | 
|---|
| 434 |           int                    *pOrder;         // order of the child_nodes,text_fields,clear_fields | 
|---|
| 435 |           int                    ref_count;       // for garbage collection (smart pointers) | 
|---|
| 436 |       } XMLNodeData; | 
|---|
| 437 |       XMLNodeData *d; | 
|---|
| 438 |  | 
|---|
| 439 |       char parseClearTag(void *px, void *pa); | 
|---|
| 440 |       char maybeAddTxT(void *pa, XMLCSTR tokenPStr); | 
|---|
| 441 |       int ParseXMLElement(void *pXML); | 
|---|
| 442 |       void *addToOrder(int memInc, int *_pos, int nc, void *p, int size, XMLElementType xtype); | 
|---|
| 443 |       int indexText(XMLCSTR lpszValue) const; | 
|---|
| 444 |       int indexClear(XMLCSTR lpszValue) const; | 
|---|
| 445 |       XMLNode addChild_priv(int,XMLSTR,char,int); | 
|---|
| 446 |       XMLAttribute *addAttribute_priv(int,XMLSTR,XMLSTR); | 
|---|
| 447 |       XMLCSTR addText_priv(int,XMLSTR,int); | 
|---|
| 448 |       XMLClear *addClear_priv(int,XMLSTR,XMLCSTR,XMLCSTR,int); | 
|---|
| 449 |       void deleteNodeContent_priv(char,char); | 
|---|
| 450 |       static inline XMLElementPosition findPosition(XMLNodeData *d, int index, XMLElementType xtype); | 
|---|
| 451 |       static int CreateXMLStringR(XMLNodeData *pEntry, XMLSTR lpszMarker, int nFormat); | 
|---|
| 452 |       static int removeOrderElement(XMLNodeData *d, XMLElementType t, int index); | 
|---|
| 453 |       static void exactMemory(XMLNodeData *d); | 
|---|
| 454 |       static int detachFromParent(XMLNodeData *d); | 
|---|
| 455 | } XMLNode; | 
|---|
| 456 |  | 
|---|
| 457 | // This structure is given by the function "enumContents". | 
|---|
| 458 | typedef struct XMLNodeContents | 
|---|
| 459 | { | 
|---|
| 460 |     // This dictates what's the content of the XMLNodeContent | 
|---|
| 461 |     enum XMLElementType etype; | 
|---|
| 462 |     // should be an union to access the appropriate data. | 
|---|
| 463 |     // compiler does not allow union of object with constructor... too bad. | 
|---|
| 464 |     XMLNode child; | 
|---|
| 465 |     XMLAttribute attrib; | 
|---|
| 466 |     XMLCSTR text; | 
|---|
| 467 |     XMLClear clear; | 
|---|
| 468 |  | 
|---|
| 469 | } XMLNodeContents; | 
|---|
| 470 |  | 
|---|
| 471 | XMLDLLENTRY void freeXMLString(XMLSTR t); // {free(t);} | 
|---|
| 472 |  | 
|---|
| 473 | // Duplicate (copy in a new allocated buffer) the source string. This is | 
|---|
| 474 | // a very handy function when used with all the "XMLNode::*_WOSD" functions. | 
|---|
| 475 | // (If (cbData!=0) then cbData is the number of chars to duplicate) | 
|---|
| 476 | XMLDLLENTRY XMLSTR stringDup(XMLCSTR source, int cbData=0); | 
|---|
| 477 |  | 
|---|
| 478 | // The following class is processing strings so that all the characters | 
|---|
| 479 | // &,",',<,> are replaced by their XML equivalent: &, ", ', <, >. | 
|---|
| 480 | // This  class is useful when creating from scratch an XML file using the | 
|---|
| 481 | // "printf", "fprintf", "cout",... functions. If you are creating from scratch an | 
|---|
| 482 | // XML file using the provided XMLNode class you must not use the "ToXMLStringTool" | 
|---|
| 483 | // class (the "XMLNode" class does the processing job for you during rendering). | 
|---|
| 484 | // Using the "ToXMLStringTool class" and the "fprintf function" is THE most efficient | 
|---|
| 485 | // way to produce VERY large XML documents VERY fast. | 
|---|
| 486 | typedef struct XMLDLLENTRY ToXMLStringTool | 
|---|
| 487 | { | 
|---|
| 488 | public: | 
|---|
| 489 |     ToXMLStringTool(): buf(NULL),buflen(0){} | 
|---|
| 490 |     ~ToXMLStringTool(); | 
|---|
| 491 |     void freeBuffer(); | 
|---|
| 492 |  | 
|---|
| 493 |     XMLSTR toXML(XMLCSTR source); | 
|---|
| 494 |  | 
|---|
| 495 |     // The next function is deprecated because there is a possibility of | 
|---|
| 496 |     // "destination-buffer-overflow". It converts the string | 
|---|
| 497 |     // "source" to the string "dest". | 
|---|
| 498 |     static XMLSTR toXMLUnSafe(XMLSTR dest,XMLCSTR source); | 
|---|
| 499 |  | 
|---|
| 500 | private: | 
|---|
| 501 |     XMLSTR buf; | 
|---|
| 502 |     int buflen; | 
|---|
| 503 | }ToXMLStringTool; | 
|---|
| 504 |  | 
|---|
| 505 | // Below is a class that allows you to include any binary data (images, sounds,...) | 
|---|
| 506 | // into an XML document using "Base64 encoding". This class is completely | 
|---|
| 507 | // separated from the rest of the xmlParser library and can be removed without any problem. | 
|---|
| 508 | // To include some binary data into an XML file, you must convert the binary data into | 
|---|
| 509 | // standard text (using "encode"). To retrieve the original binary data from the | 
|---|
| 510 | // b64-encoded text included inside the XML file use "decode". Alternatively, these | 
|---|
| 511 | // functions can also be used to "encrypt/decrypt" some critical data contained inside | 
|---|
| 512 | // the XML (it's not a strong encryption at all, but sometimes it can be useful). | 
|---|
| 513 |  | 
|---|
| 514 | typedef struct XMLDLLENTRY XMLParserBase64Tool | 
|---|
| 515 | { | 
|---|
| 516 | public: | 
|---|
| 517 |     XMLParserBase64Tool(): buf(NULL),buflen(0){} | 
|---|
| 518 |     ~XMLParserBase64Tool(); | 
|---|
| 519 |     void freeBuffer(); | 
|---|
| 520 |  | 
|---|
| 521 |     // returns the length of the base64 string that encodes a data buffer of size inBufLen bytes. | 
|---|
| 522 |     // If "formatted" parameter is true, some space will be reserved for a carriage-return every 72 chars. | 
|---|
| 523 |     static int encodeLength(int inBufLen, char formatted=0); | 
|---|
| 524 |  | 
|---|
| 525 |     // The "base64Encode" function returns a string containing the base64 encoding of "inByteLen" bytes | 
|---|
| 526 |     // from "inByteBuf". If "formatted" parameter is true, then there will be a carriage-return every 72 chars. | 
|---|
| 527 |     // The string will be free'd when the XMLParserBase64Tool object is deleted. | 
|---|
| 528 |     // All returned strings are sharing the same memory space. | 
|---|
| 529 |     XMLSTR encode(unsigned char *inByteBuf, unsigned int inByteLen, char formatted=0); | 
|---|
| 530 |  | 
|---|
| 531 |     // returns the number of bytes which will be decoded from "inString". | 
|---|
| 532 |     static unsigned int decodeSize(XMLCSTR inString, XMLError *xe=NULL); | 
|---|
| 533 |  | 
|---|
| 534 |     // returns a pointer to a buffer containing the binary data decoded from "inString" | 
|---|
| 535 |     // If "inString" is malformed NULL will be returned | 
|---|
| 536 |     // The output buffer will be free'd when the XMLParserBase64Tool object is deleted. | 
|---|
| 537 |     // All output buffer are sharing the same memory space. | 
|---|
| 538 |     unsigned char* decode(XMLCSTR inString, int *outByteLen=NULL, XMLError *xe=NULL); | 
|---|
| 539 |  | 
|---|
| 540 |     // The next function is deprecated. | 
|---|
| 541 |     // decodes data from "inString" to "outByteBuf". You need to provide the size (in byte) of "outByteBuf" | 
|---|
| 542 |     // in "inMaxByteOutBuflen". If "outByteBuf" is not large enough or if data is malformed, then "FALSE" | 
|---|
| 543 |     // will be returned; otherwise "TRUE". | 
|---|
| 544 |     static unsigned char decode(XMLCSTR inString, unsigned char *outByteBuf, int inMaxByteOutBuflen, XMLError *xe=NULL); | 
|---|
| 545 |  | 
|---|
| 546 | private: | 
|---|
| 547 |     void *buf; | 
|---|
| 548 |     int buflen; | 
|---|
| 549 |     void alloc(int newsize); | 
|---|
| 550 | }XMLParserBase64Tool; | 
|---|
| 551 |  | 
|---|
| 552 | #undef XMLDLLENTRY | 
|---|
| 553 |  | 
|---|
| 554 | #endif | 
|---|