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 &, ", ', <, > \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