blob: 6fdc162106cb22120e533192bf867bba5ab8497b [file] [log] [blame]
Lee Thomason5b0a6772012-11-19 13:54:42 -08001#if defined( _MSC_VER )
2 #define _CRT_SECURE_NO_WARNINGS // This test file is not intended to be secure.
3#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08004
Lee Thomason5b0a6772012-11-19 13:54:42 -08005#include "tinyxml2.h"
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -07006#include <cstdlib>
7#include <cstring>
8#include <ctime>
U-Lama\Leee13c3e62011-12-28 14:36:55 -08009
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080010#if defined( _MSC_VER )
Lee Thomasone9699e62012-07-25 12:24:23 -070011 #include <direct.h> // _mkdir
Lee Thomason1ff38e02012-02-14 18:18:16 -080012 #include <crtdbg.h>
Lee Thomason6f381b72012-03-02 12:59:39 -080013 #define WIN32_LEAN_AND_MEAN
14 #include <windows.h>
Lee Thomason1ff38e02012-02-14 18:18:16 -080015 _CrtMemState startMemState;
16 _CrtMemState endMemState;
Martinsh Shaiters39ddc262013-01-15 21:53:08 +020017#elif defined(MINGW32) || defined(__MINGW32__)
18 #include <io.h> // mkdir
Lee Thomasone9699e62012-07-25 12:24:23 -070019#else
20 #include <sys/stat.h> // mkdir
Lee Thomason1ff38e02012-02-14 18:18:16 -080021#endif
Lee Thomasone9ecdab2012-02-13 18:11:20 -080022
U-Lama\Leee13c3e62011-12-28 14:36:55 -080023using namespace tinyxml2;
Lee Thomasonec5a7b42012-02-13 18:16:52 -080024int gPass = 0;
25int gFail = 0;
26
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -080027
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070028bool XMLTest (const char* testString, const char* expected, const char* found, bool echo=true, bool extraNL=false )
Lee Thomason1ff38e02012-02-14 18:18:16 -080029{
30 bool pass = !strcmp( expected, found );
31 if ( pass )
32 printf ("[pass]");
33 else
34 printf ("[fail]");
35
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070036 if ( !echo ) {
Lee Thomason1ff38e02012-02-14 18:18:16 -080037 printf (" %s\n", testString);
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070038 }
39 else {
40 if ( extraNL ) {
41 printf( " %s\n", testString );
42 printf( "%s\n", expected );
43 printf( "%s\n", found );
44 }
45 else {
46 printf (" %s [%s][%s]\n", testString, expected, found);
47 }
48 }
Lee Thomason1ff38e02012-02-14 18:18:16 -080049
50 if ( pass )
51 ++gPass;
52 else
53 ++gFail;
54 return pass;
55}
56
57
Lee Thomason21be8822012-07-15 17:27:22 -070058template< class T > bool XMLTest( const char* testString, T expected, T found, bool echo=true )
Lee Thomason1ff38e02012-02-14 18:18:16 -080059{
60 bool pass = ( expected == found );
61 if ( pass )
62 printf ("[pass]");
63 else
64 printf ("[fail]");
65
U-Stream\Lee09a11c52012-02-17 08:31:16 -080066 if ( !echo )
Lee Thomason1ff38e02012-02-14 18:18:16 -080067 printf (" %s\n", testString);
68 else
Lee Thomasonc8312792012-07-16 12:44:41 -070069 printf (" %s [%d][%d]\n", testString, static_cast<int>(expected), static_cast<int>(found) );
Lee Thomason1ff38e02012-02-14 18:18:16 -080070
71 if ( pass )
72 ++gPass;
73 else
74 ++gFail;
75 return pass;
76}
Lee Thomasonec5a7b42012-02-13 18:16:52 -080077
U-Lama\Leee13c3e62011-12-28 14:36:55 -080078
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -080079void NullLineEndings( char* p )
80{
81 while( p && *p ) {
82 if ( *p == '\n' || *p == '\r' ) {
83 *p = 0;
84 return;
85 }
86 ++p;
87 }
88}
89
90
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070091int example_1()
92{
93 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -030094 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070095
96 return doc.ErrorID();
97}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +020098/** @page Example-1 Load an XML File
99 * @dontinclude ./xmltest.cpp
100 * Basic XML file loading.
101 * The basic syntax to load an XML file from
102 * disk and check for an error. (ErrorID()
103 * will return 0 for no error.)
104 * @skip example_1()
105 * @until }
106 */
107
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700108
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700109int example_2()
110{
111 static const char* xml = "<element/>";
112 XMLDocument doc;
113 doc.Parse( xml );
114
115 return doc.ErrorID();
116}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200117/** @page Example-2 Parse an XML from char buffer
118 * @dontinclude ./xmltest.cpp
119 * Basic XML string parsing.
120 * The basic syntax to parse an XML for
121 * a char* and check for an error. (ErrorID()
122 * will return 0 for no error.)
123 * @skip example_2()
124 * @until }
125 */
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700126
127
128int example_3()
129{
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700130 static const char* xml =
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700131 "<?xml version=\"1.0\"?>"
132 "<!DOCTYPE PLAY SYSTEM \"play.dtd\">"
133 "<PLAY>"
134 "<TITLE>A Midsummer Night's Dream</TITLE>"
135 "</PLAY>";
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700136
137 XMLDocument doc;
138 doc.Parse( xml );
139
140 XMLElement* titleElement = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" );
141 const char* title = titleElement->GetText();
142 printf( "Name of play (1): %s\n", title );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700143
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700144 XMLText* textNode = titleElement->FirstChild()->ToText();
145 title = textNode->Value();
146 printf( "Name of play (2): %s\n", title );
147
148 return doc.ErrorID();
149}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200150/** @page Example-3 Get information out of XML
151 @dontinclude ./xmltest.cpp
152 In this example, we navigate a simple XML
153 file, and read some interesting text. Note
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700154 that this example doesn't use error
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200155 checking; working code should check for null
156 pointers when walking an XML tree, or use
157 XMLHandle.
158
159 (The XML is an excerpt from "dream.xml").
160
161 @skip example_3()
162 @until </PLAY>";
163
164 The structure of the XML file is:
165
166 <ul>
167 <li>(declaration)</li>
168 <li>(dtd stuff)</li>
169 <li>Element "PLAY"</li>
170 <ul>
171 <li>Element "TITLE"</li>
172 <ul>
173 <li>Text "A Midsummer Night's Dream"</li>
174 </ul>
175 </ul>
176 </ul>
177
178 For this example, we want to print out the
179 title of the play. The text of the title (what
180 we want) is child of the "TITLE" element which
181 is a child of the "PLAY" element.
182
183 We want to skip the declaration and dtd, so the
184 method FirstChildElement() is a good choice. The
185 FirstChildElement() of the Document is the "PLAY"
186 Element, the FirstChildElement() of the "PLAY" Element
187 is the "TITLE" Element.
188
189 @until ( "TITLE" );
190
191 We can then use the convenience function GetText()
192 to get the title of the play.
193
194 @until title );
195
196 Text is just another Node in the XML DOM. And in
197 fact you should be a little cautious with it, as
198 text nodes can contain elements.
199
200 @verbatim
201 Consider: A Midsummer Night's <b>Dream</b>
202 @endverbatim
203
204 It is more correct to actually query the Text Node
205 if in doubt:
206
207 @until title );
208
209 Noting that here we use FirstChild() since we are
210 looking for XMLText, not an element, and ToText()
211 is a cast from a Node to a XMLText.
212*/
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700213
214
Lee Thomason21be8822012-07-15 17:27:22 -0700215bool example_4()
216{
217 static const char* xml =
218 "<information>"
219 " <attributeApproach v='2' />"
220 " <textApproach>"
221 " <v>2</v>"
222 " </textApproach>"
223 "</information>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700224
Lee Thomason21be8822012-07-15 17:27:22 -0700225 XMLDocument doc;
226 doc.Parse( xml );
227
228 int v0 = 0;
229 int v1 = 0;
230
231 XMLElement* attributeApproachElement = doc.FirstChildElement()->FirstChildElement( "attributeApproach" );
232 attributeApproachElement->QueryIntAttribute( "v", &v0 );
233
234 XMLElement* textApproachElement = doc.FirstChildElement()->FirstChildElement( "textApproach" );
235 textApproachElement->FirstChildElement( "v" )->QueryIntText( &v1 );
236
237 printf( "Both values are the same: %d and %d\n", v0, v1 );
238
239 return !doc.Error() && ( v0 == v1 );
240}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200241/** @page Example-4 Read attributes and text information.
242 @dontinclude ./xmltest.cpp
243
244 There are fundamentally 2 ways of writing a key-value
245 pair into an XML file. (Something that's always annoyed
246 me about XML.) Either by using attributes, or by writing
247 the key name into an element and the value into
248 the text node wrapped by the element. Both approaches
249 are illustrated in this example, which shows two ways
250 to encode the value "2" into the key "v":
251
252 @skip example_4()
253 @until "</information>";
254
255 TinyXML-2 has accessors for both approaches.
256
257 When using an attribute, you navigate to the XMLElement
258 with that attribute and use the QueryIntAttribute()
259 group of methods. (Also QueryFloatAttribute(), etc.)
260
261 @skip XMLElement* attributeApproachElement
262 @until &v0 );
263
264 When using the text approach, you need to navigate
265 down one more step to the XMLElement that contains
266 the text. Note the extra FirstChildElement( "v" )
267 in the code below. The value of the text can then
268 be safely queried with the QueryIntText() group
269 of methods. (Also QueryFloatText(), etc.)
270
271 @skip XMLElement* textApproachElement
272 @until &v1 );
273*/
Lee Thomason21be8822012-07-15 17:27:22 -0700274
275
Lee Thomason178e4cc2013-01-25 16:19:05 -0800276int main( int argc, const char ** argv )
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800277{
Lee Thomason (grinliz)0a4df402012-02-27 20:50:52 -0800278 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason1ff38e02012-02-14 18:18:16 -0800279 _CrtMemCheckpoint( &startMemState );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700280 #endif
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800281
Martinsh Shaiters39ddc262013-01-15 21:53:08 +0200282 #if defined(_MSC_VER) || defined(MINGW32) || defined(__MINGW32__)
ddiproiettoa8ae1f62013-05-05 18:42:52 +0300283 #if defined __MINGW64_VERSION_MAJOR && defined __MINGW64_VERSION_MINOR
284 //MINGW64: both 32 and 64-bit
285 mkdir( "resources/out/" );
286 #else
287 _mkdir( "resources/out/" );
288 #endif
Lee Thomasone9699e62012-07-25 12:24:23 -0700289 #else
290 mkdir( "resources/out/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
291 #endif
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400292
Lee Thomason178e4cc2013-01-25 16:19:05 -0800293 if ( argc > 1 ) {
294 XMLDocument* doc = new XMLDocument();
295 clock_t startTime = clock();
296 doc->LoadFile( argv[1] );
297 clock_t loadTime = clock();
298 int errorID = doc->ErrorID();
299 delete doc; doc = 0;
300 clock_t deleteTime = clock();
301
302 printf( "Test file '%s' loaded. ErrorID=%d\n", argv[1], errorID );
303 if ( !errorID ) {
Lee Thomason (grinliz)d6bd7362013-05-11 20:23:13 -0700304 printf( "Load time=%u\n", (unsigned)(loadTime - startTime) );
305 printf( "Delete time=%u\n", (unsigned)(deleteTime - loadTime) );
306 printf( "Total time=%u\n", (unsigned)(deleteTime - startTime) );
Lee Thomason178e4cc2013-01-25 16:19:05 -0800307 }
308 exit(0);
309 }
310
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300311 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason7f7b1622012-03-24 12:49:03 -0700312 if ( !fp ) {
313 printf( "Error opening test file 'dream.xml'.\n"
314 "Is your working directory the same as where \n"
315 "the xmltest.cpp and dream.xml file are?\n\n"
316 #if defined( _MSC_VER )
317 "In windows Visual Studio you may need to set\n"
318 "Properties->Debugging->Working Directory to '..'\n"
319 #endif
320 );
321 exit( 1 );
322 }
323 fclose( fp );
324
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700325 XMLTest( "Example-1", 0, example_1() );
326 XMLTest( "Example-2", 0, example_2() );
327 XMLTest( "Example-3", 0, example_3() );
Lee Thomason21be8822012-07-15 17:27:22 -0700328 XMLTest( "Example-4", true, example_4() );
Lee Thomason87e475a2012-03-20 11:55:29 -0700329
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700330 /* ------ Example 2: Lookup information. ---- */
Lee Thomason87e475a2012-03-20 11:55:29 -0700331
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800332 {
Lee Thomason43f59302012-02-06 18:18:11 -0800333 static const char* test[] = { "<element />",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400334 "<element></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800335 "<element><subelement/></element>",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400336 "<element><subelement></subelement></element>",
337 "<element><subelement><subsub/></subelement></element>",
338 "<!--comment beside elements--><element><subelement></subelement></element>",
339 "<!--comment beside elements, this time with spaces--> \n <element> <subelement> \n </subelement> </element>",
340 "<element attrib1='foo' attrib2=\"bar\" ></element>",
341 "<element attrib1='foo' attrib2=\"bar\" ><subelement attrib3='yeehaa' /></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800342 "<element>Text inside element.</element>",
343 "<element><b></b></element>",
344 "<element>Text inside and <b>bolded</b> in the element.</element>",
345 "<outer><element>Text inside and <b>bolded</b> in the element.</element></outer>",
Lee Thomason8ee79892012-01-25 17:44:30 -0800346 "<element>This &amp; That.</element>",
Lee Thomason18d68bd2012-01-26 18:17:26 -0800347 "<element attrib='This&lt;That' />",
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800348 0
349 };
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800350 for( int i=0; test[i]; ++i ) {
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800351 XMLDocument doc;
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800352 doc.Parse( test[i] );
Lee Thomason5cae8972012-01-24 18:03:07 -0800353 doc.Print();
Lee Thomasonec975ce2012-01-23 11:42:06 -0800354 printf( "----------------------------------------------\n" );
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800355 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800356 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800357#if 1
Lee Thomasond6277762012-02-22 16:00:12 -0800358 {
359 static const char* test = "<!--hello world\n"
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400360 " line 2\r"
361 " line 3\r\n"
362 " line 4\n\r"
363 " line 5\r-->";
Lee Thomasond6277762012-02-22 16:00:12 -0800364
365 XMLDocument doc;
366 doc.Parse( test );
367 doc.Print();
368 }
369
Lee Thomason2c85a712012-01-31 08:24:24 -0800370 {
371 static const char* test = "<element>Text before.</element>";
372 XMLDocument doc;
373 doc.Parse( test );
374 XMLElement* root = doc.FirstChildElement();
375 XMLElement* newElement = doc.NewElement( "Subelement" );
376 root->InsertEndChild( newElement );
377 doc.Print();
378 }
Lee Thomasond1983222012-02-06 08:41:24 -0800379 {
380 XMLDocument* doc = new XMLDocument();
381 static const char* test = "<element><sub/></element>";
382 doc->Parse( test );
383 delete doc;
384 }
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800385 {
Lee Thomason1ff38e02012-02-14 18:18:16 -0800386 // Test: Programmatic DOM
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800387 // Build:
388 // <element>
389 // <!--comment-->
390 // <sub attrib="1" />
391 // <sub attrib="2" />
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800392 // <sub attrib="3" >& Text!</sub>
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800393 // <element>
394
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800395 XMLDocument* doc = new XMLDocument();
Lee Thomason1ff38e02012-02-14 18:18:16 -0800396 XMLNode* element = doc->InsertEndChild( doc->NewElement( "element" ) );
397
398 XMLElement* sub[3] = { doc->NewElement( "sub" ), doc->NewElement( "sub" ), doc->NewElement( "sub" ) };
399 for( int i=0; i<3; ++i ) {
400 sub[i]->SetAttribute( "attrib", i );
401 }
402 element->InsertEndChild( sub[2] );
403 XMLNode* comment = element->InsertFirstChild( doc->NewComment( "comment" ) );
404 element->InsertAfterChild( comment, sub[0] );
405 element->InsertAfterChild( sub[0], sub[1] );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800406 sub[2]->InsertFirstChild( doc->NewText( "& Text!" ));
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800407 doc->Print();
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800408 XMLTest( "Programmatic DOM", "comment", doc->FirstChildElement( "element" )->FirstChild()->Value() );
409 XMLTest( "Programmatic DOM", "0", doc->FirstChildElement( "element" )->FirstChildElement()->Attribute( "attrib" ) );
410 XMLTest( "Programmatic DOM", 2, doc->FirstChildElement()->LastChildElement( "sub" )->IntAttribute( "attrib" ) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700411 XMLTest( "Programmatic DOM", "& Text!",
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800412 doc->FirstChildElement()->LastChildElement( "sub" )->FirstChild()->ToText()->Value() );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800413
414 // And now deletion:
415 element->DeleteChild( sub[2] );
416 doc->DeleteNode( comment );
417
418 element->FirstChildElement()->SetAttribute( "attrib", true );
419 element->LastChildElement()->DeleteAttribute( "attrib" );
420
421 XMLTest( "Programmatic DOM", true, doc->FirstChildElement()->FirstChildElement()->BoolAttribute( "attrib" ) );
422 int value = 10;
423 int result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value );
Lee Thomason21be8822012-07-15 17:27:22 -0700424 XMLTest( "Programmatic DOM", result, (int)XML_NO_ATTRIBUTE );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800425 XMLTest( "Programmatic DOM", value, 10 );
426
427 doc->Print();
428
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700429 {
430 XMLPrinter streamer;
431 doc->Print( &streamer );
432 printf( "%s", streamer.CStr() );
433 }
434 {
435 XMLPrinter streamer( 0, true );
436 doc->Print( &streamer );
437 XMLTest( "Compact mode", "<element><sub attrib=\"1\"/><sub/></element>", streamer.CStr(), false );
438 }
Lee Thomason (grinliz)6b8b0122012-09-08 21:21:00 -0700439 doc->SaveFile( "./resources/out/pretty.xml" );
440 doc->SaveFile( "./resources/out/compact.xml", true );
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800441 delete doc;
442 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800443 {
444 // Test: Dream
445 // XML1 : 1,187,569 bytes in 31,209 allocations
446 // XML2 : 469,073 bytes in 323 allocations
447 //int newStart = gNew;
448 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300449 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800450
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400451 doc.SaveFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800452 doc.PrintError();
453
454 XMLTest( "Dream", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400455 doc.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800456 XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false );
457 XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
458 doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
459 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400460 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800461 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
464 XMLDocument doc2;
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400465 doc2.LoadFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800466 XMLTest( "Dream-out", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400467 doc2.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800468 XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false );
469 XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
470 doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
471 XMLTest( "Dream-out", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400472 doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800473
474 //gNewTotal = gNew - newStart;
475 }
Lee Thomason6f381b72012-03-02 12:59:39 -0800476
477
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800478 {
479 const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
480 "<passages count=\"006\" formatversion=\"20020620\">\n"
481 " <wrong error>\n"
482 "</passages>";
483
484 XMLDocument doc;
485 doc.Parse( error );
Lee Thomason2fa81722012-11-09 12:37:46 -0800486 XMLTest( "Bad XML", doc.ErrorID(), XML_ERROR_PARSING_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800487 }
488
489 {
490 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
491
492 XMLDocument doc;
493 doc.Parse( str );
494
495 XMLElement* ele = doc.FirstChildElement();
496
497 int iVal, result;
498 double dVal;
499
500 result = ele->QueryDoubleAttribute( "attr0", &dVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700501 XMLTest( "Query attribute: int as double", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800502 XMLTest( "Query attribute: int as double", (int)dVal, 1 );
503 result = ele->QueryDoubleAttribute( "attr1", &dVal );
Thomas Roßa5221862013-05-11 10:22:12 +0200504 XMLTest( "Query attribute: double as double", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800505 XMLTest( "Query attribute: double as double", (int)dVal, 2 );
506 result = ele->QueryIntAttribute( "attr1", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700507 XMLTest( "Query attribute: double as int", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800508 XMLTest( "Query attribute: double as int", iVal, 2 );
509 result = ele->QueryIntAttribute( "attr2", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700510 XMLTest( "Query attribute: not a number", result, (int)XML_WRONG_ATTRIBUTE_TYPE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800511 result = ele->QueryIntAttribute( "bar", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700512 XMLTest( "Query attribute: does not exist", result, (int)XML_NO_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800513 }
514
515 {
516 const char* str = "<doc/>";
517
518 XMLDocument doc;
519 doc.Parse( str );
520
521 XMLElement* ele = doc.FirstChildElement();
522
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800523 int iVal, iVal2;
524 double dVal, dVal2;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800525
526 ele->SetAttribute( "str", "strValue" );
527 ele->SetAttribute( "int", 1 );
528 ele->SetAttribute( "double", -1.0 );
529
530 const char* cStr = ele->Attribute( "str" );
531 ele->QueryIntAttribute( "int", &iVal );
532 ele->QueryDoubleAttribute( "double", &dVal );
533
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800534 ele->QueryAttribute( "int", &iVal2 );
535 ele->QueryAttribute( "double", &dVal2 );
536
Lee Thomason8ba7f7d2012-03-24 13:04:04 -0700537 XMLTest( "Attribute match test", ele->Attribute( "str", "strValue" ), "strValue" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800538 XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
539 XMLTest( "Attribute round trip. int.", 1, iVal );
540 XMLTest( "Attribute round trip. double.", -1, (int)dVal );
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800541 XMLTest( "Alternate query", true, iVal == iVal2 );
542 XMLTest( "Alternate query", true, dVal == dVal2 );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800543 }
544
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800545 {
546 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300547 doc.LoadFile( "resources/utf8test.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800548
549 // Get the attribute "value" from the "Russian" element and check it.
550 XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700551 const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800552 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
553
554 XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
555
556 const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U,
557 0xd1U, 0x81U, 0xd1U, 0x81U,
558 0xd0U, 0xbaU, 0xd0U, 0xb8U,
559 0xd0U, 0xb9U, 0 };
560 const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
561
562 XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
563 XMLTest( "UTF-8: Browsing russian element name.",
564 russianText,
565 text->Value() );
566
567 // Now try for a round trip.
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400568 doc.SaveFile( "resources/out/utf8testout.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800569
570 // Check the round trip.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800571 int okay = 0;
572
Thomas Roßa6dd8c62012-07-26 20:42:18 +0200573 FILE* saved = fopen( "resources/out/utf8testout.xml", "r" );
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300574 FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800575
576 if ( saved && verify )
577 {
578 okay = 1;
PKEuSc28ba3a2012-07-16 03:08:47 -0700579 char verifyBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800580 while ( fgets( verifyBuf, 256, verify ) )
581 {
PKEuSc28ba3a2012-07-16 03:08:47 -0700582 char savedBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800583 fgets( savedBuf, 256, saved );
584 NullLineEndings( verifyBuf );
585 NullLineEndings( savedBuf );
586
587 if ( strcmp( verifyBuf, savedBuf ) )
588 {
589 printf( "verify:%s<\n", verifyBuf );
590 printf( "saved :%s<\n", savedBuf );
591 okay = 0;
592 break;
593 }
594 }
595 }
596 if ( saved )
597 fclose( saved );
598 if ( verify )
599 fclose( verify );
600 XMLTest( "UTF-8: Verified multi-language round trip.", 1, okay );
601 }
602
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800603 // --------GetText()-----------
604 {
605 const char* str = "<foo>This is text</foo>";
606 XMLDocument doc;
607 doc.Parse( str );
608 const XMLElement* element = doc.RootElement();
609
610 XMLTest( "GetText() normal use.", "This is text", element->GetText() );
611
612 str = "<foo><b>This is text</b></foo>";
613 doc.Parse( str );
614 element = doc.RootElement();
615
616 XMLTest( "GetText() contained element.", element->GetText() == 0, true );
617 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800618
Lee Thomasond6277762012-02-22 16:00:12 -0800619
Uli Kusterer321072e2014-01-21 01:57:38 +0100620 // --------SetText()-----------
621 {
622 const char* str = "<foo></foo>";
623 XMLDocument doc;
624 doc.Parse( str );
625 XMLElement* element = doc.RootElement();
626
Lee Thomason9c0678a2014-01-24 10:18:27 -0800627 element->SetText("darkness.");
628 XMLTest( "SetText() normal use (open/close).", "darkness.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100629
Lee Thomason9c0678a2014-01-24 10:18:27 -0800630 element->SetText("blue flame.");
631 XMLTest( "SetText() replace.", "blue flame.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100632
633 str = "<foo/>";
634 doc.Parse( str );
635 element = doc.RootElement();
636
Lee Thomason9c0678a2014-01-24 10:18:27 -0800637 element->SetText("The driver");
638 XMLTest( "SetText() normal use. (self-closing)", "The driver", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100639
Lee Thomason9c0678a2014-01-24 10:18:27 -0800640 element->SetText("<b>horses</b>");
641 XMLTest( "SetText() replace with tag-like text.", "<b>horses</b>", element->GetText() );
642 //doc.Print();
Uli Kusterer321072e2014-01-21 01:57:38 +0100643
644 str = "<foo><bar>Text in nested element</bar></foo>";
645 doc.Parse( str );
646 element = doc.RootElement();
647
Lee Thomason9c0678a2014-01-24 10:18:27 -0800648 element->SetText("wolves");
649 XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800650
651 str = "<foo/>";
652 doc.Parse( str );
653 element = doc.RootElement();
654
655 element->SetText( "str" );
656 XMLTest( "SetText types", "str", element->GetText() );
657
658 element->SetText( 1 );
659 XMLTest( "SetText types", "1", element->GetText() );
660
661 element->SetText( 1U );
662 XMLTest( "SetText types", "1", element->GetText() );
663
664 element->SetText( true );
665 XMLTest( "SetText types", "1", element->GetText() ); // TODO: should be 'true'?
666
667 element->SetText( 1.5f );
668 XMLTest( "SetText types", "1.5", element->GetText() );
669
670 element->SetText( 1.5 );
671 XMLTest( "SetText types", "1.5", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100672 }
673
674
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800675 // ---------- CDATA ---------------
676 {
677 const char* str = "<xmlElement>"
678 "<![CDATA["
679 "I am > the rules!\n"
680 "...since I make symbolic puns"
681 "]]>"
682 "</xmlElement>";
683 XMLDocument doc;
684 doc.Parse( str );
685 doc.Print();
Lee Thomasond6277762012-02-22 16:00:12 -0800686
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700687 XMLTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800688 "I am > the rules!\n...since I make symbolic puns",
Lee Thomasond6277762012-02-22 16:00:12 -0800689 false );
690 }
691
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800692 // ----------- CDATA -------------
693 {
694 const char* str = "<xmlElement>"
695 "<![CDATA["
696 "<b>I am > the rules!</b>\n"
697 "...since I make symbolic puns"
698 "]]>"
699 "</xmlElement>";
700 XMLDocument doc;
701 doc.Parse( str );
702 doc.Print();
703
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700704 XMLTest( "CDATA parse. [ tixml1:1480107 ]", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800705 "<b>I am > the rules!</b>\n...since I make symbolic puns",
706 false );
707 }
708
709 // InsertAfterChild causes crash.
710 {
711 // InsertBeforeChild and InsertAfterChild causes crash.
712 XMLDocument doc;
713 XMLElement* parent = doc.NewElement( "Parent" );
714 doc.InsertFirstChild( parent );
715
716 XMLElement* childText0 = doc.NewElement( "childText0" );
717 XMLElement* childText1 = doc.NewElement( "childText1" );
718
719 XMLNode* childNode0 = parent->InsertEndChild( childText0 );
720 XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
721
722 XMLTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent->LastChild() ), true );
723 }
Lee Thomasond6277762012-02-22 16:00:12 -0800724
725 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800726 // Entities not being written correctly.
727 // From Lynn Allen
Lee Thomasond6277762012-02-22 16:00:12 -0800728
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800729 const char* passages =
730 "<?xml version=\"1.0\" standalone=\"no\" ?>"
731 "<passages count=\"006\" formatversion=\"20020620\">"
732 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
733 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
734 "</passages>";
Lee Thomasond6277762012-02-22 16:00:12 -0800735
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800736 XMLDocument doc;
737 doc.Parse( passages );
738 XMLElement* psg = doc.RootElement()->FirstChildElement();
739 const char* context = psg->Attribute( "context" );
740 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 -0800741
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800742 XMLTest( "Entity transformation: read. ", expected, context, true );
Lee Thomasond6277762012-02-22 16:00:12 -0800743
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400744 FILE* textfile = fopen( "resources/out/textfile.txt", "w" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800745 if ( textfile )
746 {
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800747 XMLPrinter streamer( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800748 psg->Accept( &streamer );
749 fclose( textfile );
750 }
Thomas Roß0922b732012-09-23 16:31:22 +0200751
752 textfile = fopen( "resources/out/textfile.txt", "r" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800753 TIXMLASSERT( textfile );
754 if ( textfile )
755 {
756 char buf[ 1024 ];
757 fgets( buf, 1024, textfile );
758 XMLTest( "Entity transformation: write. ",
759 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
760 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
761 buf, false );
PKEuSc28ba3a2012-07-16 03:08:47 -0700762 fclose( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800763 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800764 }
765
766 {
Lee Thomason6f381b72012-03-02 12:59:39 -0800767 // Suppress entities.
768 const char* passages =
769 "<?xml version=\"1.0\" standalone=\"no\" ?>"
770 "<passages count=\"006\" formatversion=\"20020620\">"
771 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
772 "</passages>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700773
Lee Thomason6f381b72012-03-02 12:59:39 -0800774 XMLDocument doc( false );
775 doc.Parse( passages );
776
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700777 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ),
Lee Thomason6f381b72012-03-02 12:59:39 -0800778 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;." );
779 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value(),
780 "Crazy &ttk;" );
781 doc.Print();
782 }
783
784 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400785 const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800786
787 XMLDocument doc;
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400788 doc.Parse( test );
789 XMLTest( "dot in names", doc.Error(), false );
790 XMLTest( "dot in names", doc.FirstChildElement()->Name(), "a.elem" );
791 XMLTest( "dot in names", doc.FirstChildElement()->Attribute( "xmi.version" ), "2.0" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800792 }
793
794 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400795 const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800796
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400797 XMLDocument doc;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800798 doc.Parse( test );
799
800 XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
801 XMLTest( "Entity with one digit.",
802 text->Value(), "1.1 Start easy ignore fin thickness\n",
803 false );
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400804 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800805
806 {
807 // DOCTYPE not preserved (950171)
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700808 //
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800809 const char* doctype =
810 "<?xml version=\"1.0\" ?>"
811 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
812 "<!ELEMENT title (#PCDATA)>"
813 "<!ELEMENT books (title,authors)>"
814 "<element />";
815
816 XMLDocument doc;
817 doc.Parse( doctype );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400818 doc.SaveFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800819 doc.DeleteChild( doc.RootElement() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400820 doc.LoadFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800821 doc.Print();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700822
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800823 const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
824 XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
825
826 }
827
828 {
829 // Comments do not stream out correctly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700830 const char* doctype =
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800831 "<!-- Somewhat<evil> -->";
832 XMLDocument doc;
833 doc.Parse( doctype );
834
835 XMLComment* comment = doc.FirstChild()->ToComment();
836
837 XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
838 }
839 {
840 // Double attributes
841 const char* doctype = "<element attr='red' attr='blue' />";
842
843 XMLDocument doc;
844 doc.Parse( doctype );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700845
Lee Thomason2fa81722012-11-09 12:37:46 -0800846 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 -0800847 doc.PrintError();
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800848 }
849
850 {
851 // Embedded null in stream.
852 const char* doctype = "<element att\0r='red' attr='blue' />";
853
854 XMLDocument doc;
855 doc.Parse( doctype );
856 XMLTest( "Embedded null throws error.", true, doc.Error() );
857 }
858
859 {
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700860 // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800861 const char* str = " ";
862 XMLDocument doc;
863 doc.Parse( str );
Lee Thomason2fa81722012-11-09 12:37:46 -0800864 XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800865 }
866
867 {
868 // Low entities
869 XMLDocument doc;
870 doc.Parse( "<test>&#x0e;</test>" );
871 const char result[] = { 0x0e, 0 };
872 XMLTest( "Low entities.", doc.FirstChildElement()->GetText(), result );
873 doc.Print();
874 }
875
876 {
877 // Attribute values with trailing quotes not handled correctly
878 XMLDocument doc;
879 doc.Parse( "<foo attribute=bar\" />" );
880 XMLTest( "Throw error with bad end quotes.", doc.Error(), true );
881 }
882
883 {
884 // [ 1663758 ] Failure to report error on bad XML
885 XMLDocument xml;
886 xml.Parse("<x>");
887 XMLTest("Missing end tag at end of input", xml.Error(), true);
888 xml.Parse("<x> ");
889 XMLTest("Missing end tag with trailing whitespace", xml.Error(), true);
890 xml.Parse("<x></y>");
Lee Thomason2fa81722012-11-09 12:37:46 -0800891 XMLTest("Mismatched tags", xml.ErrorID(), XML_ERROR_MISMATCHED_ELEMENT);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700892 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800893
894
895 {
896 // [ 1475201 ] TinyXML parses entities in comments
897 XMLDocument xml;
898 xml.Parse("<!-- declarations for <head> & <body> -->"
899 "<!-- far &amp; away -->" );
900
901 XMLNode* e0 = xml.FirstChild();
902 XMLNode* e1 = e0->NextSibling();
903 XMLComment* c0 = e0->ToComment();
904 XMLComment* c1 = e1->ToComment();
905
906 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
907 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
908 }
909
910 {
911 XMLDocument xml;
912 xml.Parse( "<Parent>"
913 "<child1 att=''/>"
914 "<!-- With this comment, child2 will not be parsed! -->"
915 "<child2 att=''/>"
916 "</Parent>" );
917 xml.Print();
918
919 int count = 0;
920
921 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
922 ele;
923 ele = ele->NextSibling() )
924 {
925 ++count;
926 }
927
928 XMLTest( "Comments iterate correctly.", 3, count );
929 }
930
931 {
932 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
933 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
934 buf[60] = 239;
935 buf[61] = 0;
936
937 XMLDocument doc;
938 doc.Parse( (const char*)buf);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700939 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800940
941
942 {
943 // bug 1827248 Error while parsing a little bit malformed file
944 // Actually not malformed - should work.
945 XMLDocument xml;
946 xml.Parse( "<attributelist> </attributelist >" );
947 XMLTest( "Handle end tag whitespace", false, xml.Error() );
948 }
949
950 {
951 // This one must not result in an infinite loop
952 XMLDocument xml;
953 xml.Parse( "<infinite>loop" );
954 XMLTest( "Infinite loop test.", true, true );
955 }
956#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800957 {
958 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
959 XMLDocument doc;
960 doc.Parse( pub );
961
962 XMLDocument clone;
963 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
964 XMLNode* copy = node->ShallowClone( &clone );
965 clone.InsertEndChild( copy );
966 }
967
968 clone.Print();
969
970 int count=0;
971 const XMLNode* a=clone.FirstChild();
972 const XMLNode* b=doc.FirstChild();
973 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
974 ++count;
975 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
976 }
977 XMLTest( "Clone and Equal", 4, count );
978 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800979
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700980 {
981 // This shouldn't crash.
982 XMLDocument doc;
983 if(XML_NO_ERROR != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
984 {
985 doc.PrintError();
986 }
987 XMLTest( "Error in snprinf handling.", true, doc.Error() );
988 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700989
Lee Thomason5e3803c2012-04-16 08:57:05 -0700990 {
991 // Attribute ordering.
992 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
993 XMLDocument doc;
994 doc.Parse( xml );
995 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700996
Lee Thomason5e3803c2012-04-16 08:57:05 -0700997 const XMLAttribute* a = ele->FirstAttribute();
998 XMLTest( "Attribute order", "1", a->Value() );
999 a = a->Next();
1000 XMLTest( "Attribute order", "2", a->Value() );
1001 a = a->Next();
1002 XMLTest( "Attribute order", "3", a->Value() );
1003 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001004
Lee Thomason5e3803c2012-04-16 08:57:05 -07001005 ele->DeleteAttribute( "attrib2" );
1006 a = ele->FirstAttribute();
1007 XMLTest( "Attribute order", "1", a->Value() );
1008 a = a->Next();
1009 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001010
Lee Thomason5e3803c2012-04-16 08:57:05 -07001011 ele->DeleteAttribute( "attrib1" );
1012 ele->DeleteAttribute( "attrib3" );
1013 XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
1014 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001015
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001016 {
1017 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -07001018 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
1019 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
1020 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
1021 XMLDocument doc0;
1022 doc0.Parse( xml0 );
1023 XMLDocument doc1;
1024 doc1.Parse( xml1 );
1025 XMLDocument doc2;
1026 doc2.Parse( xml2 );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001027
Lee Thomason78a773d2012-07-02 10:10:19 -07001028 XMLElement* ele = 0;
1029 ele = doc0.FirstChildElement();
1030 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
1031 ele = doc1.FirstChildElement();
1032 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
1033 ele = doc2.FirstChildElement();
1034 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001035 }
1036
1037 {
1038 // Make sure we don't go into an infinite loop.
1039 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
1040 XMLDocument doc;
1041 doc.Parse( xml );
1042 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
1043 XMLElement* ele1 = ele0->NextSiblingElement();
1044 bool equal = ele0->ShallowEqual( ele1 );
1045
1046 XMLTest( "Infinite loop in shallow equal.", true, equal );
1047 }
1048
Lee Thomason5708f812012-03-28 17:46:41 -07001049 // -------- Handles ------------
1050 {
1051 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1052 XMLDocument doc;
1053 doc.Parse( xml );
Lee Thomason5708f812012-03-28 17:46:41 -07001054
1055 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
1056 XMLTest( "Handle, success, mutable", ele->Value(), "sub" );
1057
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001058 XMLHandle docH( doc );
1059 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001060 XMLTest( "Handle, dne, mutable", false, ele != 0 );
Lee Thomason5708f812012-03-28 17:46:41 -07001061 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001062
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001063 {
1064 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1065 XMLDocument doc;
1066 doc.Parse( xml );
1067 XMLConstHandle docH( doc );
1068
1069 const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
1070 XMLTest( "Handle, success, const", ele->Value(), "sub" );
1071
1072 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001073 XMLTest( "Handle, dne, const", false, ele != 0 );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001074 }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001075 {
1076 // Default Declaration & BOM
1077 XMLDocument doc;
1078 doc.InsertEndChild( doc.NewDeclaration() );
1079 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001080
Lee Thomasonf68c4382012-04-28 14:37:11 -07001081 XMLPrinter printer;
1082 doc.Print( &printer );
1083
1084 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1085 XMLTest( "BOM and default declaration", printer.CStr(), result, false );
Lee Thomason (grinliz)48ea0bc2012-05-26 14:41:14 -07001086 XMLTest( "CStrSize", printer.CStrSize(), 42, false );
Lee Thomasonf68c4382012-04-28 14:37:11 -07001087 }
Lee Thomason21be8822012-07-15 17:27:22 -07001088 {
1089 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1090 XMLDocument doc;
1091 doc.Parse( xml );
1092 XMLTest( "Ill formed XML", true, doc.Error() );
1093 }
1094
1095 // QueryXYZText
1096 {
1097 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1098 XMLDocument doc;
1099 doc.Parse( xml );
1100
1101 const XMLElement* pointElement = doc.RootElement();
1102
1103 int intValue = 0;
1104 unsigned unsignedValue = 0;
1105 float floatValue = 0;
1106 double doubleValue = 0;
1107 bool boolValue = false;
1108
1109 pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1110 pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1111 pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1112 pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1113 pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1114
1115
1116 XMLTest( "QueryIntText", intValue, 1, false );
1117 XMLTest( "QueryUnsignedText", unsignedValue, (unsigned)1, false );
1118 XMLTest( "QueryFloatText", floatValue, 1.2f, false );
1119 XMLTest( "QueryDoubleText", doubleValue, 1.2, false );
1120 XMLTest( "QueryBoolText", boolValue, true, false );
1121 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001122
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001123 {
1124 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1125 XMLDocument doc;
1126 doc.Parse( xml );
1127 XMLTest( "Non-alpha element lead letter parses.", doc.Error(), false );
1128 }
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001129
1130 {
1131 const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1132 XMLDocument doc;
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001133 doc.Parse( xml );
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001134 XMLTest("Non-alpha attribute lead character parses.", doc.Error(), false);
1135 }
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001136
1137 {
1138 const char* xml = "<3lement></3lement>";
1139 XMLDocument doc;
1140 doc.Parse( xml );
1141 XMLTest("Element names with lead digit fail to parse.", doc.Error(), true);
1142 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -07001143
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001144 {
1145 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1146 XMLDocument doc;
1147 doc.Parse( xml, 10 );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001148 XMLTest( "Set length of incoming data", doc.Error(), false );
1149 }
1150
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001151 {
1152 XMLDocument doc;
1153 doc.LoadFile( "resources/dream.xml" );
1154 doc.Clear();
1155 XMLTest( "Document Clear()'s", doc.NoChildren(), true );
1156 }
1157
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001158 // ----------- Whitespace ------------
1159 {
1160 const char* xml = "<element>"
1161 "<a> This \nis &apos; text &apos; </a>"
1162 "<b> This is &apos; text &apos; \n</b>"
1163 "<c>This is &apos; \n\n text &apos;</c>"
1164 "</element>";
1165 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1166 doc.Parse( xml );
1167
1168 const XMLElement* element = doc.FirstChildElement();
1169 for( const XMLElement* parent = element->FirstChildElement();
1170 parent;
1171 parent = parent->NextSiblingElement() )
1172 {
1173 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1174 }
1175 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001176
Lee Thomasonae9ab072012-10-24 10:17:53 -07001177#if 0
1178 {
1179 // Passes if assert doesn't fire.
1180 XMLDocument xmlDoc;
1181
1182 xmlDoc.NewDeclaration();
1183 xmlDoc.NewComment("Configuration file");
1184
1185 XMLElement *root = xmlDoc.NewElement("settings");
1186 root->SetAttribute("version", 2);
1187 }
1188#endif
1189
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001190 {
1191 const char* xml = "<element> </element>";
1192 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1193 doc.Parse( xml );
1194 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1195 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001196
Lee Thomason5b0a6772012-11-19 13:54:42 -08001197 {
1198 // An assert should not fire.
1199 const char* xml = "<element/>";
1200 XMLDocument doc;
1201 doc.Parse( xml );
1202 XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope.
1203 XMLTest( "Tracking unused elements", true, ele != 0, false );
1204 }
1205
Lee Thomasona6412ac2012-12-13 15:39:11 -08001206
1207 {
1208 const char* xml = "<parent><child>abc</child></parent>";
1209 XMLDocument doc;
1210 doc.Parse( xml );
1211 XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
1212
1213 XMLPrinter printer;
1214 ele->Accept( &printer );
1215 XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1216 }
1217
1218
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001219 {
1220 XMLDocument doc;
1221 XMLError error = doc.LoadFile( "resources/empty.xml" );
1222 XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
1223 }
1224
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001225 {
1226 // BOM preservation
1227 static const char* xml_bom_preservation = "\xef\xbb\xbf<element/>\n";
1228 {
1229 XMLDocument doc;
1230 XMLTest( "BOM preservation (parse)", XML_NO_ERROR, doc.Parse( xml_bom_preservation ), false );
1231 XMLPrinter printer;
1232 doc.Print( &printer );
1233
1234 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1235 doc.SaveFile( "resources/bomtest.xml" );
1236 }
1237 {
1238 XMLDocument doc;
1239 doc.LoadFile( "resources/bomtest.xml" );
1240 XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
1241
1242 XMLPrinter printer;
1243 doc.Print( &printer );
1244 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1245 }
1246 }
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001247
Michael Daumlinged523282013-10-23 07:47:29 +02001248 {
1249 // Insertion with Removal
1250 const char* xml = "<?xml version=\"1.0\" ?>"
1251 "<root>"
1252 "<one>"
1253 "<subtree>"
1254 "<elem>element 1</elem>text<!-- comment -->"
1255 "</subtree>"
1256 "</one>"
1257 "<two/>"
1258 "</root>";
1259 const char* xmlInsideTwo = "<?xml version=\"1.0\" ?>"
1260 "<root>"
1261 "<one/>"
1262 "<two>"
1263 "<subtree>"
1264 "<elem>element 1</elem>text<!-- comment -->"
1265 "</subtree>"
1266 "</two>"
1267 "</root>";
1268 const char* xmlAfterOne = "<?xml version=\"1.0\" ?>"
1269 "<root>"
1270 "<one/>"
1271 "<subtree>"
1272 "<elem>element 1</elem>text<!-- comment -->"
1273 "</subtree>"
1274 "<two/>"
1275 "</root>";
1276 const char* xmlAfterTwo = "<?xml version=\"1.0\" ?>"
1277 "<root>"
1278 "<one/>"
1279 "<two/>"
1280 "<subtree>"
1281 "<elem>element 1</elem>text<!-- comment -->"
1282 "</subtree>"
1283 "</root>";
1284
1285 XMLDocument doc;
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001286 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001287 XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1288 XMLElement* two = doc.RootElement()->FirstChildElement("two");
1289 two->InsertFirstChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001290 XMLPrinter printer1(0, true);
1291 doc.Accept(&printer1);
1292 XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
Michael Daumlinged523282013-10-23 07:47:29 +02001293
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001294 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001295 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1296 two = doc.RootElement()->FirstChildElement("two");
1297 doc.RootElement()->InsertAfterChild(two, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001298 XMLPrinter printer2(0, true);
1299 doc.Accept(&printer2);
1300 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001301
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001302 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001303 XMLNode* one = doc.RootElement()->FirstChildElement("one");
1304 subtree = one->FirstChildElement("subtree");
1305 doc.RootElement()->InsertAfterChild(one, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001306 XMLPrinter printer3(0, true);
1307 doc.Accept(&printer3);
1308 XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001309
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001310 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001311 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1312 two = doc.RootElement()->FirstChildElement("two");
1313 doc.RootElement()->InsertEndChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001314 XMLPrinter printer4(0, true);
1315 doc.Accept(&printer4);
1316 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001317 }
1318
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001319 {
1320 const char* xml = "<svg width = \"128\" height = \"128\">"
1321 " <text> </text>"
1322 "</svg>";
1323 XMLDocument doc;
1324 doc.Parse(xml);
1325 doc.Print();
1326 }
1327
1328#if 1
1329 // the question being explored is what kind of print to use:
1330 // https://github.com/leethomason/tinyxml2/issues/63
1331 {
1332 //const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
1333 const char* xml = "<element/>";
1334 XMLDocument doc;
1335 doc.Parse( xml );
1336 doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
1337 doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
1338 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
1339 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
1340 doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
1341 doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
1342
1343 doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
1344 doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
1345 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
1346 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
1347 doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
1348 doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
1349
1350 doc.Print();
1351
1352 /* The result of this test is platform, compiler, and library version dependent. :("
1353 XMLPrinter printer;
1354 doc.Print( &printer );
1355 XMLTest( "Float and double formatting.",
1356 "<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",
1357 printer.CStr(),
1358 true );
1359 */
1360 }
1361#endif
1362
1363
1364
Lee Thomason6f381b72012-03-02 12:59:39 -08001365 // ----------- Performance tracking --------------
1366 {
1367#if defined( _MSC_VER )
1368 __int64 start, end, freq;
1369 QueryPerformanceFrequency( (LARGE_INTEGER*) &freq );
1370#endif
1371
Bruno Diasa2d4e6e2012-05-07 04:58:11 -03001372 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason6f381b72012-03-02 12:59:39 -08001373 fseek( fp, 0, SEEK_END );
1374 long size = ftell( fp );
1375 fseek( fp, 0, SEEK_SET );
1376
1377 char* mem = new char[size+1];
1378 fread( mem, size, 1, fp );
1379 fclose( fp );
1380 mem[size] = 0;
1381
1382#if defined( _MSC_VER )
1383 QueryPerformanceCounter( (LARGE_INTEGER*) &start );
1384#else
1385 clock_t cstart = clock();
1386#endif
1387 static const int COUNT = 10;
1388 for( int i=0; i<COUNT; ++i ) {
1389 XMLDocument doc;
1390 doc.Parse( mem );
1391 }
1392#if defined( _MSC_VER )
1393 QueryPerformanceCounter( (LARGE_INTEGER*) &end );
1394#else
1395 clock_t cend = clock();
1396#endif
1397
1398 delete [] mem;
1399
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001400 static const char* note =
Lee Thomason6f381b72012-03-02 12:59:39 -08001401#ifdef DEBUG
1402 "DEBUG";
1403#else
1404 "Release";
1405#endif
1406
1407#if defined( _MSC_VER )
1408 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, 1000.0 * (double)(end-start) / ( (double)freq * (double)COUNT) );
1409#else
1410 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart)/(double)COUNT );
1411#endif
1412 }
1413
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -08001414 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001415 _CrtMemCheckpoint( &endMemState );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001416 //_CrtMemDumpStatistics( &endMemState );
1417
1418 _CrtMemState diffMemState;
1419 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
1420 _CrtMemDumpStatistics( &diffMemState );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001421 //printf( "new total=%d\n", gNewTotal );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001422 #endif
1423
1424 printf ("\nPass %d, Fail %d\n", gPass, gFail);
Lee Thomason (grinliz)db304252013-07-31 12:24:52 -07001425
1426 return gFail;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08001427}