xmlParser.h 45 KB

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