blob: 3e41e13f8f587b7eab8e60419dc1c6041b6b2f5f [file] [log] [blame]
Lee Thomason5b0a6772012-11-19 13:54:42 -08001#if defined( _MSC_VER )
Serhat Eser Erdemca5d6842014-04-17 14:06:15 +02002 #if !defined( _CRT_SECURE_NO_WARNINGS )
3 #define _CRT_SECURE_NO_WARNINGS // This test file is not intended to be secure.
4 #endif
Lee Thomason5b0a6772012-11-19 13:54:42 -08005#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08006
Lee Thomason5b0a6772012-11-19 13:54:42 -08007#include "tinyxml2.h"
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -07008#include <cstdlib>
9#include <cstring>
10#include <ctime>
U-Lama\Leee13c3e62011-12-28 14:36:55 -080011
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080012#if defined( _MSC_VER )
Lee Thomasone9699e62012-07-25 12:24:23 -070013 #include <direct.h> // _mkdir
Lee Thomason1ff38e02012-02-14 18:18:16 -080014 #include <crtdbg.h>
Lee Thomason6f381b72012-03-02 12:59:39 -080015 #define WIN32_LEAN_AND_MEAN
16 #include <windows.h>
Lee Thomason1ff38e02012-02-14 18:18:16 -080017 _CrtMemState startMemState;
18 _CrtMemState endMemState;
Martinsh Shaiters39ddc262013-01-15 21:53:08 +020019#elif defined(MINGW32) || defined(__MINGW32__)
20 #include <io.h> // mkdir
Lee Thomasone9699e62012-07-25 12:24:23 -070021#else
22 #include <sys/stat.h> // mkdir
Lee Thomason1ff38e02012-02-14 18:18:16 -080023#endif
Lee Thomasone9ecdab2012-02-13 18:11:20 -080024
U-Lama\Leee13c3e62011-12-28 14:36:55 -080025using namespace tinyxml2;
Lee Thomasonec5a7b42012-02-13 18:16:52 -080026int gPass = 0;
27int gFail = 0;
28
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -080029
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070030bool XMLTest (const char* testString, const char* expected, const char* found, bool echo=true, bool extraNL=false )
Lee Thomason1ff38e02012-02-14 18:18:16 -080031{
32 bool pass = !strcmp( expected, found );
33 if ( pass )
34 printf ("[pass]");
35 else
36 printf ("[fail]");
37
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070038 if ( !echo ) {
Lee Thomason1ff38e02012-02-14 18:18:16 -080039 printf (" %s\n", testString);
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070040 }
41 else {
42 if ( extraNL ) {
43 printf( " %s\n", testString );
44 printf( "%s\n", expected );
45 printf( "%s\n", found );
46 }
47 else {
48 printf (" %s [%s][%s]\n", testString, expected, found);
49 }
50 }
Lee Thomason1ff38e02012-02-14 18:18:16 -080051
52 if ( pass )
53 ++gPass;
54 else
55 ++gFail;
56 return pass;
57}
58
59
Lee Thomason21be8822012-07-15 17:27:22 -070060template< class T > bool XMLTest( const char* testString, T expected, T found, bool echo=true )
Lee Thomason1ff38e02012-02-14 18:18:16 -080061{
62 bool pass = ( expected == found );
63 if ( pass )
64 printf ("[pass]");
65 else
66 printf ("[fail]");
67
U-Stream\Lee09a11c52012-02-17 08:31:16 -080068 if ( !echo )
Lee Thomason1ff38e02012-02-14 18:18:16 -080069 printf (" %s\n", testString);
70 else
Lee Thomasonc8312792012-07-16 12:44:41 -070071 printf (" %s [%d][%d]\n", testString, static_cast<int>(expected), static_cast<int>(found) );
Lee Thomason1ff38e02012-02-14 18:18:16 -080072
73 if ( pass )
74 ++gPass;
75 else
76 ++gFail;
77 return pass;
78}
Lee Thomasonec5a7b42012-02-13 18:16:52 -080079
U-Lama\Leee13c3e62011-12-28 14:36:55 -080080
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -080081void NullLineEndings( char* p )
82{
83 while( p && *p ) {
84 if ( *p == '\n' || *p == '\r' ) {
85 *p = 0;
86 return;
87 }
88 ++p;
89 }
90}
91
92
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070093int example_1()
94{
95 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -030096 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070097
98 return doc.ErrorID();
99}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200100/** @page Example-1 Load an XML File
101 * @dontinclude ./xmltest.cpp
102 * Basic XML file loading.
103 * The basic syntax to load an XML file from
104 * disk and check for an error. (ErrorID()
105 * will return 0 for no error.)
106 * @skip example_1()
107 * @until }
108 */
109
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700110
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700111int example_2()
112{
113 static const char* xml = "<element/>";
114 XMLDocument doc;
115 doc.Parse( xml );
116
117 return doc.ErrorID();
118}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200119/** @page Example-2 Parse an XML from char buffer
120 * @dontinclude ./xmltest.cpp
121 * Basic XML string parsing.
122 * The basic syntax to parse an XML for
123 * a char* and check for an error. (ErrorID()
124 * will return 0 for no error.)
125 * @skip example_2()
126 * @until }
127 */
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700128
129
130int example_3()
131{
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700132 static const char* xml =
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700133 "<?xml version=\"1.0\"?>"
134 "<!DOCTYPE PLAY SYSTEM \"play.dtd\">"
135 "<PLAY>"
136 "<TITLE>A Midsummer Night's Dream</TITLE>"
137 "</PLAY>";
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700138
139 XMLDocument doc;
140 doc.Parse( xml );
141
142 XMLElement* titleElement = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" );
143 const char* title = titleElement->GetText();
144 printf( "Name of play (1): %s\n", title );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700145
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700146 XMLText* textNode = titleElement->FirstChild()->ToText();
147 title = textNode->Value();
148 printf( "Name of play (2): %s\n", title );
149
150 return doc.ErrorID();
151}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200152/** @page Example-3 Get information out of XML
153 @dontinclude ./xmltest.cpp
154 In this example, we navigate a simple XML
155 file, and read some interesting text. Note
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700156 that this example doesn't use error
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200157 checking; working code should check for null
158 pointers when walking an XML tree, or use
159 XMLHandle.
160
161 (The XML is an excerpt from "dream.xml").
162
163 @skip example_3()
164 @until </PLAY>";
165
166 The structure of the XML file is:
167
168 <ul>
169 <li>(declaration)</li>
170 <li>(dtd stuff)</li>
171 <li>Element "PLAY"</li>
172 <ul>
173 <li>Element "TITLE"</li>
174 <ul>
175 <li>Text "A Midsummer Night's Dream"</li>
176 </ul>
177 </ul>
178 </ul>
179
180 For this example, we want to print out the
181 title of the play. The text of the title (what
182 we want) is child of the "TITLE" element which
183 is a child of the "PLAY" element.
184
185 We want to skip the declaration and dtd, so the
186 method FirstChildElement() is a good choice. The
187 FirstChildElement() of the Document is the "PLAY"
188 Element, the FirstChildElement() of the "PLAY" Element
189 is the "TITLE" Element.
190
191 @until ( "TITLE" );
192
193 We can then use the convenience function GetText()
194 to get the title of the play.
195
196 @until title );
197
198 Text is just another Node in the XML DOM. And in
199 fact you should be a little cautious with it, as
200 text nodes can contain elements.
201
202 @verbatim
203 Consider: A Midsummer Night's <b>Dream</b>
204 @endverbatim
205
206 It is more correct to actually query the Text Node
207 if in doubt:
208
209 @until title );
210
211 Noting that here we use FirstChild() since we are
212 looking for XMLText, not an element, and ToText()
213 is a cast from a Node to a XMLText.
214*/
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700215
216
Lee Thomason21be8822012-07-15 17:27:22 -0700217bool example_4()
218{
219 static const char* xml =
220 "<information>"
221 " <attributeApproach v='2' />"
222 " <textApproach>"
223 " <v>2</v>"
224 " </textApproach>"
225 "</information>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700226
Lee Thomason21be8822012-07-15 17:27:22 -0700227 XMLDocument doc;
228 doc.Parse( xml );
229
230 int v0 = 0;
231 int v1 = 0;
232
233 XMLElement* attributeApproachElement = doc.FirstChildElement()->FirstChildElement( "attributeApproach" );
234 attributeApproachElement->QueryIntAttribute( "v", &v0 );
235
236 XMLElement* textApproachElement = doc.FirstChildElement()->FirstChildElement( "textApproach" );
237 textApproachElement->FirstChildElement( "v" )->QueryIntText( &v1 );
238
239 printf( "Both values are the same: %d and %d\n", v0, v1 );
240
241 return !doc.Error() && ( v0 == v1 );
242}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200243/** @page Example-4 Read attributes and text information.
244 @dontinclude ./xmltest.cpp
245
246 There are fundamentally 2 ways of writing a key-value
247 pair into an XML file. (Something that's always annoyed
248 me about XML.) Either by using attributes, or by writing
249 the key name into an element and the value into
250 the text node wrapped by the element. Both approaches
251 are illustrated in this example, which shows two ways
252 to encode the value "2" into the key "v":
253
254 @skip example_4()
255 @until "</information>";
256
257 TinyXML-2 has accessors for both approaches.
258
259 When using an attribute, you navigate to the XMLElement
260 with that attribute and use the QueryIntAttribute()
261 group of methods. (Also QueryFloatAttribute(), etc.)
262
263 @skip XMLElement* attributeApproachElement
264 @until &v0 );
265
266 When using the text approach, you need to navigate
267 down one more step to the XMLElement that contains
268 the text. Note the extra FirstChildElement( "v" )
269 in the code below. The value of the text can then
270 be safely queried with the QueryIntText() group
271 of methods. (Also QueryFloatText(), etc.)
272
273 @skip XMLElement* textApproachElement
274 @until &v1 );
275*/
Lee Thomason21be8822012-07-15 17:27:22 -0700276
277
Lee Thomason178e4cc2013-01-25 16:19:05 -0800278int main( int argc, const char ** argv )
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800279{
Lee Thomason (grinliz)0a4df402012-02-27 20:50:52 -0800280 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason1ff38e02012-02-14 18:18:16 -0800281 _CrtMemCheckpoint( &startMemState );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700282 #endif
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800283
Martinsh Shaiters39ddc262013-01-15 21:53:08 +0200284 #if defined(_MSC_VER) || defined(MINGW32) || defined(__MINGW32__)
ddiproiettoa8ae1f62013-05-05 18:42:52 +0300285 #if defined __MINGW64_VERSION_MAJOR && defined __MINGW64_VERSION_MINOR
286 //MINGW64: both 32 and 64-bit
287 mkdir( "resources/out/" );
288 #else
289 _mkdir( "resources/out/" );
290 #endif
Lee Thomasone9699e62012-07-25 12:24:23 -0700291 #else
292 mkdir( "resources/out/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
293 #endif
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400294
Lee Thomason178e4cc2013-01-25 16:19:05 -0800295 if ( argc > 1 ) {
296 XMLDocument* doc = new XMLDocument();
297 clock_t startTime = clock();
298 doc->LoadFile( argv[1] );
299 clock_t loadTime = clock();
300 int errorID = doc->ErrorID();
301 delete doc; doc = 0;
302 clock_t deleteTime = clock();
303
304 printf( "Test file '%s' loaded. ErrorID=%d\n", argv[1], errorID );
305 if ( !errorID ) {
Lee Thomason (grinliz)d6bd7362013-05-11 20:23:13 -0700306 printf( "Load time=%u\n", (unsigned)(loadTime - startTime) );
307 printf( "Delete time=%u\n", (unsigned)(deleteTime - loadTime) );
308 printf( "Total time=%u\n", (unsigned)(deleteTime - startTime) );
Lee Thomason178e4cc2013-01-25 16:19:05 -0800309 }
310 exit(0);
311 }
312
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300313 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason7f7b1622012-03-24 12:49:03 -0700314 if ( !fp ) {
315 printf( "Error opening test file 'dream.xml'.\n"
316 "Is your working directory the same as where \n"
317 "the xmltest.cpp and dream.xml file are?\n\n"
318 #if defined( _MSC_VER )
319 "In windows Visual Studio you may need to set\n"
320 "Properties->Debugging->Working Directory to '..'\n"
321 #endif
322 );
323 exit( 1 );
324 }
325 fclose( fp );
326
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700327 XMLTest( "Example-1", 0, example_1() );
328 XMLTest( "Example-2", 0, example_2() );
329 XMLTest( "Example-3", 0, example_3() );
Lee Thomason21be8822012-07-15 17:27:22 -0700330 XMLTest( "Example-4", true, example_4() );
Lee Thomason87e475a2012-03-20 11:55:29 -0700331
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700332 /* ------ Example 2: Lookup information. ---- */
Lee Thomason87e475a2012-03-20 11:55:29 -0700333
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800334 {
Lee Thomason43f59302012-02-06 18:18:11 -0800335 static const char* test[] = { "<element />",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400336 "<element></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800337 "<element><subelement/></element>",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400338 "<element><subelement></subelement></element>",
339 "<element><subelement><subsub/></subelement></element>",
340 "<!--comment beside elements--><element><subelement></subelement></element>",
341 "<!--comment beside elements, this time with spaces--> \n <element> <subelement> \n </subelement> </element>",
342 "<element attrib1='foo' attrib2=\"bar\" ></element>",
343 "<element attrib1='foo' attrib2=\"bar\" ><subelement attrib3='yeehaa' /></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800344 "<element>Text inside element.</element>",
345 "<element><b></b></element>",
346 "<element>Text inside and <b>bolded</b> in the element.</element>",
347 "<outer><element>Text inside and <b>bolded</b> in the element.</element></outer>",
Lee Thomason8ee79892012-01-25 17:44:30 -0800348 "<element>This &amp; That.</element>",
Lee Thomason18d68bd2012-01-26 18:17:26 -0800349 "<element attrib='This&lt;That' />",
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800350 0
351 };
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800352 for( int i=0; test[i]; ++i ) {
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800353 XMLDocument doc;
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800354 doc.Parse( test[i] );
Lee Thomason5cae8972012-01-24 18:03:07 -0800355 doc.Print();
Lee Thomasonec975ce2012-01-23 11:42:06 -0800356 printf( "----------------------------------------------\n" );
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800357 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800358 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800359#if 1
Lee Thomasond6277762012-02-22 16:00:12 -0800360 {
361 static const char* test = "<!--hello world\n"
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400362 " line 2\r"
363 " line 3\r\n"
364 " line 4\n\r"
365 " line 5\r-->";
Lee Thomasond6277762012-02-22 16:00:12 -0800366
367 XMLDocument doc;
368 doc.Parse( test );
369 doc.Print();
370 }
371
Lee Thomason2c85a712012-01-31 08:24:24 -0800372 {
373 static const char* test = "<element>Text before.</element>";
374 XMLDocument doc;
375 doc.Parse( test );
376 XMLElement* root = doc.FirstChildElement();
377 XMLElement* newElement = doc.NewElement( "Subelement" );
378 root->InsertEndChild( newElement );
379 doc.Print();
380 }
Lee Thomasond1983222012-02-06 08:41:24 -0800381 {
382 XMLDocument* doc = new XMLDocument();
383 static const char* test = "<element><sub/></element>";
384 doc->Parse( test );
385 delete doc;
386 }
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800387 {
Lee Thomason1ff38e02012-02-14 18:18:16 -0800388 // Test: Programmatic DOM
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800389 // Build:
390 // <element>
391 // <!--comment-->
392 // <sub attrib="1" />
393 // <sub attrib="2" />
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800394 // <sub attrib="3" >& Text!</sub>
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800395 // <element>
396
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800397 XMLDocument* doc = new XMLDocument();
Lee Thomason1ff38e02012-02-14 18:18:16 -0800398 XMLNode* element = doc->InsertEndChild( doc->NewElement( "element" ) );
399
400 XMLElement* sub[3] = { doc->NewElement( "sub" ), doc->NewElement( "sub" ), doc->NewElement( "sub" ) };
401 for( int i=0; i<3; ++i ) {
402 sub[i]->SetAttribute( "attrib", i );
403 }
404 element->InsertEndChild( sub[2] );
405 XMLNode* comment = element->InsertFirstChild( doc->NewComment( "comment" ) );
406 element->InsertAfterChild( comment, sub[0] );
407 element->InsertAfterChild( sub[0], sub[1] );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800408 sub[2]->InsertFirstChild( doc->NewText( "& Text!" ));
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800409 doc->Print();
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800410 XMLTest( "Programmatic DOM", "comment", doc->FirstChildElement( "element" )->FirstChild()->Value() );
411 XMLTest( "Programmatic DOM", "0", doc->FirstChildElement( "element" )->FirstChildElement()->Attribute( "attrib" ) );
412 XMLTest( "Programmatic DOM", 2, doc->FirstChildElement()->LastChildElement( "sub" )->IntAttribute( "attrib" ) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700413 XMLTest( "Programmatic DOM", "& Text!",
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800414 doc->FirstChildElement()->LastChildElement( "sub" )->FirstChild()->ToText()->Value() );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800415
416 // And now deletion:
417 element->DeleteChild( sub[2] );
418 doc->DeleteNode( comment );
419
420 element->FirstChildElement()->SetAttribute( "attrib", true );
421 element->LastChildElement()->DeleteAttribute( "attrib" );
422
423 XMLTest( "Programmatic DOM", true, doc->FirstChildElement()->FirstChildElement()->BoolAttribute( "attrib" ) );
424 int value = 10;
425 int result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value );
Lee Thomason21be8822012-07-15 17:27:22 -0700426 XMLTest( "Programmatic DOM", result, (int)XML_NO_ATTRIBUTE );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800427 XMLTest( "Programmatic DOM", value, 10 );
428
429 doc->Print();
430
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700431 {
432 XMLPrinter streamer;
433 doc->Print( &streamer );
434 printf( "%s", streamer.CStr() );
435 }
436 {
437 XMLPrinter streamer( 0, true );
438 doc->Print( &streamer );
439 XMLTest( "Compact mode", "<element><sub attrib=\"1\"/><sub/></element>", streamer.CStr(), false );
440 }
Lee Thomason (grinliz)6b8b0122012-09-08 21:21:00 -0700441 doc->SaveFile( "./resources/out/pretty.xml" );
442 doc->SaveFile( "./resources/out/compact.xml", true );
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800443 delete doc;
444 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800445 {
446 // Test: Dream
447 // XML1 : 1,187,569 bytes in 31,209 allocations
448 // XML2 : 469,073 bytes in 323 allocations
449 //int newStart = gNew;
450 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300451 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800452
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400453 doc.SaveFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800454 doc.PrintError();
455
456 XMLTest( "Dream", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400457 doc.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800458 XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false );
459 XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
460 doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
461 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400462 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800463 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400464 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800465
466 XMLDocument doc2;
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400467 doc2.LoadFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800468 XMLTest( "Dream-out", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400469 doc2.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800470 XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false );
471 XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
472 doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
473 XMLTest( "Dream-out", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400474 doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800475
476 //gNewTotal = gNew - newStart;
477 }
Lee Thomason6f381b72012-03-02 12:59:39 -0800478
479
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800480 {
481 const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
482 "<passages count=\"006\" formatversion=\"20020620\">\n"
483 " <wrong error>\n"
484 "</passages>";
485
486 XMLDocument doc;
487 doc.Parse( error );
Lee Thomason2fa81722012-11-09 12:37:46 -0800488 XMLTest( "Bad XML", doc.ErrorID(), XML_ERROR_PARSING_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800489 }
490
491 {
492 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
493
494 XMLDocument doc;
495 doc.Parse( str );
496
497 XMLElement* ele = doc.FirstChildElement();
498
499 int iVal, result;
500 double dVal;
501
502 result = ele->QueryDoubleAttribute( "attr0", &dVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700503 XMLTest( "Query attribute: int as double", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800504 XMLTest( "Query attribute: int as double", (int)dVal, 1 );
505 result = ele->QueryDoubleAttribute( "attr1", &dVal );
Thomas Roßa5221862013-05-11 10:22:12 +0200506 XMLTest( "Query attribute: double as double", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800507 XMLTest( "Query attribute: double as double", (int)dVal, 2 );
508 result = ele->QueryIntAttribute( "attr1", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700509 XMLTest( "Query attribute: double as int", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800510 XMLTest( "Query attribute: double as int", iVal, 2 );
511 result = ele->QueryIntAttribute( "attr2", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700512 XMLTest( "Query attribute: not a number", result, (int)XML_WRONG_ATTRIBUTE_TYPE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800513 result = ele->QueryIntAttribute( "bar", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700514 XMLTest( "Query attribute: does not exist", result, (int)XML_NO_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800515 }
516
517 {
518 const char* str = "<doc/>";
519
520 XMLDocument doc;
521 doc.Parse( str );
522
523 XMLElement* ele = doc.FirstChildElement();
524
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800525 int iVal, iVal2;
526 double dVal, dVal2;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800527
528 ele->SetAttribute( "str", "strValue" );
529 ele->SetAttribute( "int", 1 );
530 ele->SetAttribute( "double", -1.0 );
531
532 const char* cStr = ele->Attribute( "str" );
533 ele->QueryIntAttribute( "int", &iVal );
534 ele->QueryDoubleAttribute( "double", &dVal );
535
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800536 ele->QueryAttribute( "int", &iVal2 );
537 ele->QueryAttribute( "double", &dVal2 );
538
Lee Thomason8ba7f7d2012-03-24 13:04:04 -0700539 XMLTest( "Attribute match test", ele->Attribute( "str", "strValue" ), "strValue" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800540 XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
541 XMLTest( "Attribute round trip. int.", 1, iVal );
542 XMLTest( "Attribute round trip. double.", -1, (int)dVal );
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800543 XMLTest( "Alternate query", true, iVal == iVal2 );
544 XMLTest( "Alternate query", true, dVal == dVal2 );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800545 }
546
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800547 {
548 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300549 doc.LoadFile( "resources/utf8test.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800550
551 // Get the attribute "value" from the "Russian" element and check it.
552 XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700553 const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800554 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
555
556 XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
557
558 const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U,
559 0xd1U, 0x81U, 0xd1U, 0x81U,
560 0xd0U, 0xbaU, 0xd0U, 0xb8U,
561 0xd0U, 0xb9U, 0 };
562 const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
563
564 XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
565 XMLTest( "UTF-8: Browsing russian element name.",
566 russianText,
567 text->Value() );
568
569 // Now try for a round trip.
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400570 doc.SaveFile( "resources/out/utf8testout.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800571
572 // Check the round trip.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800573 int okay = 0;
574
Thomas Roßa6dd8c62012-07-26 20:42:18 +0200575 FILE* saved = fopen( "resources/out/utf8testout.xml", "r" );
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300576 FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800577
578 if ( saved && verify )
579 {
580 okay = 1;
PKEuSc28ba3a2012-07-16 03:08:47 -0700581 char verifyBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800582 while ( fgets( verifyBuf, 256, verify ) )
583 {
PKEuSc28ba3a2012-07-16 03:08:47 -0700584 char savedBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800585 fgets( savedBuf, 256, saved );
586 NullLineEndings( verifyBuf );
587 NullLineEndings( savedBuf );
588
589 if ( strcmp( verifyBuf, savedBuf ) )
590 {
591 printf( "verify:%s<\n", verifyBuf );
592 printf( "saved :%s<\n", savedBuf );
593 okay = 0;
594 break;
595 }
596 }
597 }
598 if ( saved )
599 fclose( saved );
600 if ( verify )
601 fclose( verify );
602 XMLTest( "UTF-8: Verified multi-language round trip.", 1, okay );
603 }
604
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800605 // --------GetText()-----------
606 {
607 const char* str = "<foo>This is text</foo>";
608 XMLDocument doc;
609 doc.Parse( str );
610 const XMLElement* element = doc.RootElement();
611
612 XMLTest( "GetText() normal use.", "This is text", element->GetText() );
613
614 str = "<foo><b>This is text</b></foo>";
615 doc.Parse( str );
616 element = doc.RootElement();
617
618 XMLTest( "GetText() contained element.", element->GetText() == 0, true );
619 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800620
Lee Thomasond6277762012-02-22 16:00:12 -0800621
Uli Kusterer321072e2014-01-21 01:57:38 +0100622 // --------SetText()-----------
623 {
624 const char* str = "<foo></foo>";
625 XMLDocument doc;
626 doc.Parse( str );
627 XMLElement* element = doc.RootElement();
628
Lee Thomason9c0678a2014-01-24 10:18:27 -0800629 element->SetText("darkness.");
630 XMLTest( "SetText() normal use (open/close).", "darkness.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100631
Lee Thomason9c0678a2014-01-24 10:18:27 -0800632 element->SetText("blue flame.");
633 XMLTest( "SetText() replace.", "blue flame.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100634
635 str = "<foo/>";
636 doc.Parse( str );
637 element = doc.RootElement();
638
Lee Thomason9c0678a2014-01-24 10:18:27 -0800639 element->SetText("The driver");
640 XMLTest( "SetText() normal use. (self-closing)", "The driver", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100641
Lee Thomason9c0678a2014-01-24 10:18:27 -0800642 element->SetText("<b>horses</b>");
643 XMLTest( "SetText() replace with tag-like text.", "<b>horses</b>", element->GetText() );
644 //doc.Print();
Uli Kusterer321072e2014-01-21 01:57:38 +0100645
646 str = "<foo><bar>Text in nested element</bar></foo>";
647 doc.Parse( str );
648 element = doc.RootElement();
649
Lee Thomason9c0678a2014-01-24 10:18:27 -0800650 element->SetText("wolves");
651 XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800652
653 str = "<foo/>";
654 doc.Parse( str );
655 element = doc.RootElement();
656
657 element->SetText( "str" );
658 XMLTest( "SetText types", "str", element->GetText() );
659
660 element->SetText( 1 );
661 XMLTest( "SetText types", "1", element->GetText() );
662
663 element->SetText( 1U );
664 XMLTest( "SetText types", "1", element->GetText() );
665
666 element->SetText( true );
667 XMLTest( "SetText types", "1", element->GetText() ); // TODO: should be 'true'?
668
669 element->SetText( 1.5f );
670 XMLTest( "SetText types", "1.5", element->GetText() );
671
672 element->SetText( 1.5 );
673 XMLTest( "SetText types", "1.5", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100674 }
675
676
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800677 // ---------- CDATA ---------------
678 {
679 const char* str = "<xmlElement>"
680 "<![CDATA["
681 "I am > the rules!\n"
682 "...since I make symbolic puns"
683 "]]>"
684 "</xmlElement>";
685 XMLDocument doc;
686 doc.Parse( str );
687 doc.Print();
Lee Thomasond6277762012-02-22 16:00:12 -0800688
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700689 XMLTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800690 "I am > the rules!\n...since I make symbolic puns",
Lee Thomasond6277762012-02-22 16:00:12 -0800691 false );
692 }
693
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800694 // ----------- CDATA -------------
695 {
696 const char* str = "<xmlElement>"
697 "<![CDATA["
698 "<b>I am > the rules!</b>\n"
699 "...since I make symbolic puns"
700 "]]>"
701 "</xmlElement>";
702 XMLDocument doc;
703 doc.Parse( str );
704 doc.Print();
705
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700706 XMLTest( "CDATA parse. [ tixml1:1480107 ]", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800707 "<b>I am > the rules!</b>\n...since I make symbolic puns",
708 false );
709 }
710
711 // InsertAfterChild causes crash.
712 {
713 // InsertBeforeChild and InsertAfterChild causes crash.
714 XMLDocument doc;
715 XMLElement* parent = doc.NewElement( "Parent" );
716 doc.InsertFirstChild( parent );
717
718 XMLElement* childText0 = doc.NewElement( "childText0" );
719 XMLElement* childText1 = doc.NewElement( "childText1" );
720
721 XMLNode* childNode0 = parent->InsertEndChild( childText0 );
722 XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
723
724 XMLTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent->LastChild() ), true );
725 }
Lee Thomasond6277762012-02-22 16:00:12 -0800726
727 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800728 // Entities not being written correctly.
729 // From Lynn Allen
Lee Thomasond6277762012-02-22 16:00:12 -0800730
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800731 const char* passages =
732 "<?xml version=\"1.0\" standalone=\"no\" ?>"
733 "<passages count=\"006\" formatversion=\"20020620\">"
734 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
735 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
736 "</passages>";
Lee Thomasond6277762012-02-22 16:00:12 -0800737
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800738 XMLDocument doc;
739 doc.Parse( passages );
740 XMLElement* psg = doc.RootElement()->FirstChildElement();
741 const char* context = psg->Attribute( "context" );
742 const char* expected = "Line 5 has \"quotation marks\" and 'apostrophe marks'. It also has <, >, and &, as well as a fake copyright \xC2\xA9.";
Lee Thomasond6277762012-02-22 16:00:12 -0800743
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800744 XMLTest( "Entity transformation: read. ", expected, context, true );
Lee Thomasond6277762012-02-22 16:00:12 -0800745
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400746 FILE* textfile = fopen( "resources/out/textfile.txt", "w" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800747 if ( textfile )
748 {
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800749 XMLPrinter streamer( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800750 psg->Accept( &streamer );
751 fclose( textfile );
752 }
Thomas Roß0922b732012-09-23 16:31:22 +0200753
754 textfile = fopen( "resources/out/textfile.txt", "r" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800755 TIXMLASSERT( textfile );
756 if ( textfile )
757 {
758 char buf[ 1024 ];
759 fgets( buf, 1024, textfile );
760 XMLTest( "Entity transformation: write. ",
761 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
762 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
763 buf, false );
PKEuSc28ba3a2012-07-16 03:08:47 -0700764 fclose( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800765 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800766 }
767
768 {
Lee Thomason6f381b72012-03-02 12:59:39 -0800769 // Suppress entities.
770 const char* passages =
771 "<?xml version=\"1.0\" standalone=\"no\" ?>"
772 "<passages count=\"006\" formatversion=\"20020620\">"
773 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
774 "</passages>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700775
Lee Thomason6f381b72012-03-02 12:59:39 -0800776 XMLDocument doc( false );
777 doc.Parse( passages );
778
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700779 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ),
Lee Thomason6f381b72012-03-02 12:59:39 -0800780 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;." );
781 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value(),
782 "Crazy &ttk;" );
783 doc.Print();
784 }
785
786 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400787 const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800788
789 XMLDocument doc;
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400790 doc.Parse( test );
791 XMLTest( "dot in names", doc.Error(), false );
792 XMLTest( "dot in names", doc.FirstChildElement()->Name(), "a.elem" );
793 XMLTest( "dot in names", doc.FirstChildElement()->Attribute( "xmi.version" ), "2.0" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800794 }
795
796 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400797 const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800798
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400799 XMLDocument doc;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800800 doc.Parse( test );
801
802 XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
803 XMLTest( "Entity with one digit.",
804 text->Value(), "1.1 Start easy ignore fin thickness\n",
805 false );
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400806 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800807
808 {
809 // DOCTYPE not preserved (950171)
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700810 //
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800811 const char* doctype =
812 "<?xml version=\"1.0\" ?>"
813 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
814 "<!ELEMENT title (#PCDATA)>"
815 "<!ELEMENT books (title,authors)>"
816 "<element />";
817
818 XMLDocument doc;
819 doc.Parse( doctype );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400820 doc.SaveFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800821 doc.DeleteChild( doc.RootElement() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400822 doc.LoadFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800823 doc.Print();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700824
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800825 const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
826 XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
827
828 }
829
830 {
831 // Comments do not stream out correctly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700832 const char* doctype =
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800833 "<!-- Somewhat<evil> -->";
834 XMLDocument doc;
835 doc.Parse( doctype );
836
837 XMLComment* comment = doc.FirstChild()->ToComment();
838
839 XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
840 }
841 {
842 // Double attributes
843 const char* doctype = "<element attr='red' attr='blue' />";
844
845 XMLDocument doc;
846 doc.Parse( doctype );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700847
Lee Thomason2fa81722012-11-09 12:37:46 -0800848 XMLTest( "Parsing repeated attributes.", XML_ERROR_PARSING_ATTRIBUTE, doc.ErrorID() ); // is an error to tinyxml (didn't use to be, but caused issues)
Lee Thomason (grinliz)0a4df402012-02-27 20:50:52 -0800849 doc.PrintError();
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800850 }
851
852 {
853 // Embedded null in stream.
854 const char* doctype = "<element att\0r='red' attr='blue' />";
855
856 XMLDocument doc;
857 doc.Parse( doctype );
858 XMLTest( "Embedded null throws error.", true, doc.Error() );
859 }
860
861 {
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700862 // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800863 const char* str = " ";
864 XMLDocument doc;
865 doc.Parse( str );
Lee Thomason2fa81722012-11-09 12:37:46 -0800866 XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800867 }
868
869 {
870 // Low entities
871 XMLDocument doc;
872 doc.Parse( "<test>&#x0e;</test>" );
873 const char result[] = { 0x0e, 0 };
874 XMLTest( "Low entities.", doc.FirstChildElement()->GetText(), result );
875 doc.Print();
876 }
877
878 {
879 // Attribute values with trailing quotes not handled correctly
880 XMLDocument doc;
881 doc.Parse( "<foo attribute=bar\" />" );
882 XMLTest( "Throw error with bad end quotes.", doc.Error(), true );
883 }
884
885 {
886 // [ 1663758 ] Failure to report error on bad XML
887 XMLDocument xml;
888 xml.Parse("<x>");
889 XMLTest("Missing end tag at end of input", xml.Error(), true);
890 xml.Parse("<x> ");
891 XMLTest("Missing end tag with trailing whitespace", xml.Error(), true);
892 xml.Parse("<x></y>");
Lee Thomason2fa81722012-11-09 12:37:46 -0800893 XMLTest("Mismatched tags", xml.ErrorID(), XML_ERROR_MISMATCHED_ELEMENT);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700894 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800895
896
897 {
898 // [ 1475201 ] TinyXML parses entities in comments
899 XMLDocument xml;
900 xml.Parse("<!-- declarations for <head> & <body> -->"
901 "<!-- far &amp; away -->" );
902
903 XMLNode* e0 = xml.FirstChild();
904 XMLNode* e1 = e0->NextSibling();
905 XMLComment* c0 = e0->ToComment();
906 XMLComment* c1 = e1->ToComment();
907
908 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
909 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
910 }
911
912 {
913 XMLDocument xml;
914 xml.Parse( "<Parent>"
915 "<child1 att=''/>"
916 "<!-- With this comment, child2 will not be parsed! -->"
917 "<child2 att=''/>"
918 "</Parent>" );
919 xml.Print();
920
921 int count = 0;
922
923 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
924 ele;
925 ele = ele->NextSibling() )
926 {
927 ++count;
928 }
929
930 XMLTest( "Comments iterate correctly.", 3, count );
931 }
932
933 {
934 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
935 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
936 buf[60] = 239;
937 buf[61] = 0;
938
939 XMLDocument doc;
940 doc.Parse( (const char*)buf);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700941 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800942
943
944 {
945 // bug 1827248 Error while parsing a little bit malformed file
946 // Actually not malformed - should work.
947 XMLDocument xml;
948 xml.Parse( "<attributelist> </attributelist >" );
949 XMLTest( "Handle end tag whitespace", false, xml.Error() );
950 }
951
952 {
953 // This one must not result in an infinite loop
954 XMLDocument xml;
955 xml.Parse( "<infinite>loop" );
956 XMLTest( "Infinite loop test.", true, true );
957 }
958#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800959 {
960 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
961 XMLDocument doc;
962 doc.Parse( pub );
963
964 XMLDocument clone;
965 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
966 XMLNode* copy = node->ShallowClone( &clone );
967 clone.InsertEndChild( copy );
968 }
969
970 clone.Print();
971
972 int count=0;
973 const XMLNode* a=clone.FirstChild();
974 const XMLNode* b=doc.FirstChild();
975 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
976 ++count;
977 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
978 }
979 XMLTest( "Clone and Equal", 4, count );
980 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800981
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700982 {
983 // This shouldn't crash.
984 XMLDocument doc;
985 if(XML_NO_ERROR != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
986 {
987 doc.PrintError();
988 }
989 XMLTest( "Error in snprinf handling.", true, doc.Error() );
990 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700991
Lee Thomason5e3803c2012-04-16 08:57:05 -0700992 {
993 // Attribute ordering.
994 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
995 XMLDocument doc;
996 doc.Parse( xml );
997 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700998
Lee Thomason5e3803c2012-04-16 08:57:05 -0700999 const XMLAttribute* a = ele->FirstAttribute();
1000 XMLTest( "Attribute order", "1", a->Value() );
1001 a = a->Next();
1002 XMLTest( "Attribute order", "2", a->Value() );
1003 a = a->Next();
1004 XMLTest( "Attribute order", "3", a->Value() );
1005 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001006
Lee Thomason5e3803c2012-04-16 08:57:05 -07001007 ele->DeleteAttribute( "attrib2" );
1008 a = ele->FirstAttribute();
1009 XMLTest( "Attribute order", "1", a->Value() );
1010 a = a->Next();
1011 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001012
Lee Thomason5e3803c2012-04-16 08:57:05 -07001013 ele->DeleteAttribute( "attrib1" );
1014 ele->DeleteAttribute( "attrib3" );
1015 XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
1016 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001017
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001018 {
1019 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -07001020 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
1021 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
1022 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
1023 XMLDocument doc0;
1024 doc0.Parse( xml0 );
1025 XMLDocument doc1;
1026 doc1.Parse( xml1 );
1027 XMLDocument doc2;
1028 doc2.Parse( xml2 );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001029
Lee Thomason78a773d2012-07-02 10:10:19 -07001030 XMLElement* ele = 0;
1031 ele = doc0.FirstChildElement();
1032 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
1033 ele = doc1.FirstChildElement();
1034 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
1035 ele = doc2.FirstChildElement();
1036 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001037 }
1038
1039 {
1040 // Make sure we don't go into an infinite loop.
1041 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
1042 XMLDocument doc;
1043 doc.Parse( xml );
1044 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
1045 XMLElement* ele1 = ele0->NextSiblingElement();
1046 bool equal = ele0->ShallowEqual( ele1 );
1047
1048 XMLTest( "Infinite loop in shallow equal.", true, equal );
1049 }
1050
Lee Thomason5708f812012-03-28 17:46:41 -07001051 // -------- Handles ------------
1052 {
1053 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1054 XMLDocument doc;
1055 doc.Parse( xml );
Lee Thomason5708f812012-03-28 17:46:41 -07001056
1057 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
1058 XMLTest( "Handle, success, mutable", ele->Value(), "sub" );
1059
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001060 XMLHandle docH( doc );
1061 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001062 XMLTest( "Handle, dne, mutable", false, ele != 0 );
Lee Thomason5708f812012-03-28 17:46:41 -07001063 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001064
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001065 {
1066 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1067 XMLDocument doc;
1068 doc.Parse( xml );
1069 XMLConstHandle docH( doc );
1070
1071 const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
1072 XMLTest( "Handle, success, const", ele->Value(), "sub" );
1073
1074 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001075 XMLTest( "Handle, dne, const", false, ele != 0 );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001076 }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001077 {
1078 // Default Declaration & BOM
1079 XMLDocument doc;
1080 doc.InsertEndChild( doc.NewDeclaration() );
1081 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001082
Lee Thomasonf68c4382012-04-28 14:37:11 -07001083 XMLPrinter printer;
1084 doc.Print( &printer );
1085
1086 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1087 XMLTest( "BOM and default declaration", printer.CStr(), result, false );
Lee Thomason (grinliz)48ea0bc2012-05-26 14:41:14 -07001088 XMLTest( "CStrSize", printer.CStrSize(), 42, false );
Lee Thomasonf68c4382012-04-28 14:37:11 -07001089 }
Lee Thomason21be8822012-07-15 17:27:22 -07001090 {
1091 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1092 XMLDocument doc;
1093 doc.Parse( xml );
1094 XMLTest( "Ill formed XML", true, doc.Error() );
1095 }
1096
1097 // QueryXYZText
1098 {
1099 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1100 XMLDocument doc;
1101 doc.Parse( xml );
1102
1103 const XMLElement* pointElement = doc.RootElement();
1104
1105 int intValue = 0;
1106 unsigned unsignedValue = 0;
1107 float floatValue = 0;
1108 double doubleValue = 0;
1109 bool boolValue = false;
1110
1111 pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1112 pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1113 pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1114 pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1115 pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1116
1117
1118 XMLTest( "QueryIntText", intValue, 1, false );
1119 XMLTest( "QueryUnsignedText", unsignedValue, (unsigned)1, false );
1120 XMLTest( "QueryFloatText", floatValue, 1.2f, false );
1121 XMLTest( "QueryDoubleText", doubleValue, 1.2, false );
1122 XMLTest( "QueryBoolText", boolValue, true, false );
1123 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001124
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001125 {
1126 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1127 XMLDocument doc;
1128 doc.Parse( xml );
1129 XMLTest( "Non-alpha element lead letter parses.", doc.Error(), false );
1130 }
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001131
1132 {
1133 const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1134 XMLDocument doc;
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001135 doc.Parse( xml );
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001136 XMLTest("Non-alpha attribute lead character parses.", doc.Error(), false);
1137 }
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001138
1139 {
1140 const char* xml = "<3lement></3lement>";
1141 XMLDocument doc;
1142 doc.Parse( xml );
1143 XMLTest("Element names with lead digit fail to parse.", doc.Error(), true);
1144 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -07001145
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001146 {
1147 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1148 XMLDocument doc;
1149 doc.Parse( xml, 10 );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001150 XMLTest( "Set length of incoming data", doc.Error(), false );
1151 }
1152
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001153 {
1154 XMLDocument doc;
1155 doc.LoadFile( "resources/dream.xml" );
1156 doc.Clear();
1157 XMLTest( "Document Clear()'s", doc.NoChildren(), true );
1158 }
1159
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001160 // ----------- Whitespace ------------
1161 {
1162 const char* xml = "<element>"
1163 "<a> This \nis &apos; text &apos; </a>"
1164 "<b> This is &apos; text &apos; \n</b>"
1165 "<c>This is &apos; \n\n text &apos;</c>"
1166 "</element>";
1167 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1168 doc.Parse( xml );
1169
1170 const XMLElement* element = doc.FirstChildElement();
1171 for( const XMLElement* parent = element->FirstChildElement();
1172 parent;
1173 parent = parent->NextSiblingElement() )
1174 {
1175 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1176 }
1177 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001178
Lee Thomasonae9ab072012-10-24 10:17:53 -07001179#if 0
1180 {
1181 // Passes if assert doesn't fire.
1182 XMLDocument xmlDoc;
1183
1184 xmlDoc.NewDeclaration();
1185 xmlDoc.NewComment("Configuration file");
1186
1187 XMLElement *root = xmlDoc.NewElement("settings");
1188 root->SetAttribute("version", 2);
1189 }
1190#endif
1191
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001192 {
1193 const char* xml = "<element> </element>";
1194 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1195 doc.Parse( xml );
1196 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1197 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001198
Lee Thomason5b0a6772012-11-19 13:54:42 -08001199 {
1200 // An assert should not fire.
1201 const char* xml = "<element/>";
1202 XMLDocument doc;
1203 doc.Parse( xml );
1204 XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope.
1205 XMLTest( "Tracking unused elements", true, ele != 0, false );
1206 }
1207
Lee Thomasona6412ac2012-12-13 15:39:11 -08001208
1209 {
1210 const char* xml = "<parent><child>abc</child></parent>";
1211 XMLDocument doc;
1212 doc.Parse( xml );
1213 XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
1214
1215 XMLPrinter printer;
1216 ele->Accept( &printer );
1217 XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1218 }
1219
1220
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001221 {
1222 XMLDocument doc;
1223 XMLError error = doc.LoadFile( "resources/empty.xml" );
1224 XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
Lee Thomason331596e2014-09-11 14:56:43 -07001225 XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() );
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001226 }
1227
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001228 {
1229 // BOM preservation
1230 static const char* xml_bom_preservation = "\xef\xbb\xbf<element/>\n";
1231 {
1232 XMLDocument doc;
1233 XMLTest( "BOM preservation (parse)", XML_NO_ERROR, doc.Parse( xml_bom_preservation ), false );
1234 XMLPrinter printer;
1235 doc.Print( &printer );
1236
1237 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1238 doc.SaveFile( "resources/bomtest.xml" );
1239 }
1240 {
1241 XMLDocument doc;
1242 doc.LoadFile( "resources/bomtest.xml" );
1243 XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
1244
1245 XMLPrinter printer;
1246 doc.Print( &printer );
1247 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1248 }
1249 }
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001250
Michael Daumlinged523282013-10-23 07:47:29 +02001251 {
1252 // Insertion with Removal
1253 const char* xml = "<?xml version=\"1.0\" ?>"
1254 "<root>"
1255 "<one>"
1256 "<subtree>"
1257 "<elem>element 1</elem>text<!-- comment -->"
1258 "</subtree>"
1259 "</one>"
1260 "<two/>"
1261 "</root>";
1262 const char* xmlInsideTwo = "<?xml version=\"1.0\" ?>"
1263 "<root>"
1264 "<one/>"
1265 "<two>"
1266 "<subtree>"
1267 "<elem>element 1</elem>text<!-- comment -->"
1268 "</subtree>"
1269 "</two>"
1270 "</root>";
1271 const char* xmlAfterOne = "<?xml version=\"1.0\" ?>"
1272 "<root>"
1273 "<one/>"
1274 "<subtree>"
1275 "<elem>element 1</elem>text<!-- comment -->"
1276 "</subtree>"
1277 "<two/>"
1278 "</root>";
1279 const char* xmlAfterTwo = "<?xml version=\"1.0\" ?>"
1280 "<root>"
1281 "<one/>"
1282 "<two/>"
1283 "<subtree>"
1284 "<elem>element 1</elem>text<!-- comment -->"
1285 "</subtree>"
1286 "</root>";
1287
1288 XMLDocument doc;
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001289 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001290 XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1291 XMLElement* two = doc.RootElement()->FirstChildElement("two");
1292 two->InsertFirstChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001293 XMLPrinter printer1(0, true);
1294 doc.Accept(&printer1);
1295 XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
Michael Daumlinged523282013-10-23 07:47:29 +02001296
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001297 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001298 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1299 two = doc.RootElement()->FirstChildElement("two");
1300 doc.RootElement()->InsertAfterChild(two, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001301 XMLPrinter printer2(0, true);
1302 doc.Accept(&printer2);
1303 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001304
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001305 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001306 XMLNode* one = doc.RootElement()->FirstChildElement("one");
1307 subtree = one->FirstChildElement("subtree");
1308 doc.RootElement()->InsertAfterChild(one, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001309 XMLPrinter printer3(0, true);
1310 doc.Accept(&printer3);
1311 XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001312
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001313 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001314 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1315 two = doc.RootElement()->FirstChildElement("two");
1316 doc.RootElement()->InsertEndChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001317 XMLPrinter printer4(0, true);
1318 doc.Accept(&printer4);
1319 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001320 }
1321
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001322 {
1323 const char* xml = "<svg width = \"128\" height = \"128\">"
1324 " <text> </text>"
1325 "</svg>";
1326 XMLDocument doc;
1327 doc.Parse(xml);
1328 doc.Print();
1329 }
1330
1331#if 1
1332 // the question being explored is what kind of print to use:
1333 // https://github.com/leethomason/tinyxml2/issues/63
1334 {
1335 //const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
1336 const char* xml = "<element/>";
1337 XMLDocument doc;
1338 doc.Parse( xml );
1339 doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
1340 doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
1341 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
1342 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
1343 doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
1344 doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
1345
1346 doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
1347 doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
1348 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
1349 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
1350 doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
1351 doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
1352
1353 doc.Print();
1354
1355 /* The result of this test is platform, compiler, and library version dependent. :("
1356 XMLPrinter printer;
1357 doc.Print( &printer );
1358 XMLTest( "Float and double formatting.",
1359 "<element attrA-f64=\"123456789.12345679\" attrB-f64=\"1001000000\" attrC-f64=\"1e+20\" attrD-f64=\"0.123456789\" attrA-f32=\"1.2345679e+08\" attrB-f32=\"1.001e+09\" attrC-f32=\"1e+20\" attrD-f32=\"0.12345679\"/>\n",
1360 printer.CStr(),
1361 true );
1362 */
1363 }
1364#endif
1365
1366
1367
Lee Thomason6f381b72012-03-02 12:59:39 -08001368 // ----------- Performance tracking --------------
1369 {
1370#if defined( _MSC_VER )
1371 __int64 start, end, freq;
1372 QueryPerformanceFrequency( (LARGE_INTEGER*) &freq );
1373#endif
1374
Bruno Diasa2d4e6e2012-05-07 04:58:11 -03001375 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason6f381b72012-03-02 12:59:39 -08001376 fseek( fp, 0, SEEK_END );
1377 long size = ftell( fp );
1378 fseek( fp, 0, SEEK_SET );
1379
1380 char* mem = new char[size+1];
1381 fread( mem, size, 1, fp );
1382 fclose( fp );
1383 mem[size] = 0;
1384
1385#if defined( _MSC_VER )
1386 QueryPerformanceCounter( (LARGE_INTEGER*) &start );
1387#else
1388 clock_t cstart = clock();
1389#endif
1390 static const int COUNT = 10;
1391 for( int i=0; i<COUNT; ++i ) {
1392 XMLDocument doc;
1393 doc.Parse( mem );
1394 }
1395#if defined( _MSC_VER )
1396 QueryPerformanceCounter( (LARGE_INTEGER*) &end );
1397#else
1398 clock_t cend = clock();
1399#endif
1400
1401 delete [] mem;
1402
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001403 static const char* note =
Lee Thomason6f381b72012-03-02 12:59:39 -08001404#ifdef DEBUG
1405 "DEBUG";
1406#else
1407 "Release";
1408#endif
1409
1410#if defined( _MSC_VER )
1411 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, 1000.0 * (double)(end-start) / ( (double)freq * (double)COUNT) );
1412#else
1413 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart)/(double)COUNT );
1414#endif
1415 }
1416
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -08001417 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001418 _CrtMemCheckpoint( &endMemState );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001419 //_CrtMemDumpStatistics( &endMemState );
1420
1421 _CrtMemState diffMemState;
1422 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
1423 _CrtMemDumpStatistics( &diffMemState );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001424 //printf( "new total=%d\n", gNewTotal );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001425 #endif
1426
1427 printf ("\nPass %d, Fail %d\n", gPass, gFail);
Lee Thomason (grinliz)db304252013-07-31 12:24:52 -07001428
1429 return gFail;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08001430}