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 |
---|