blob: 3564afb04eb4b8fa1f7249d0abace639f83b87f0 [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 );
Dmitry-Me99916592014-10-23 11:37:03 +0400282 // Enable MS Visual C++ debug heap memory leaks dump on exit
283 _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700284 #endif
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800285
Martinsh Shaiters39ddc262013-01-15 21:53:08 +0200286 #if defined(_MSC_VER) || defined(MINGW32) || defined(__MINGW32__)
ddiproiettoa8ae1f62013-05-05 18:42:52 +0300287 #if defined __MINGW64_VERSION_MAJOR && defined __MINGW64_VERSION_MINOR
288 //MINGW64: both 32 and 64-bit
289 mkdir( "resources/out/" );
290 #else
291 _mkdir( "resources/out/" );
292 #endif
Lee Thomasone9699e62012-07-25 12:24:23 -0700293 #else
294 mkdir( "resources/out/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
295 #endif
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400296
Lee Thomason178e4cc2013-01-25 16:19:05 -0800297 if ( argc > 1 ) {
298 XMLDocument* doc = new XMLDocument();
299 clock_t startTime = clock();
300 doc->LoadFile( argv[1] );
301 clock_t loadTime = clock();
302 int errorID = doc->ErrorID();
303 delete doc; doc = 0;
304 clock_t deleteTime = clock();
305
306 printf( "Test file '%s' loaded. ErrorID=%d\n", argv[1], errorID );
307 if ( !errorID ) {
Lee Thomason (grinliz)d6bd7362013-05-11 20:23:13 -0700308 printf( "Load time=%u\n", (unsigned)(loadTime - startTime) );
309 printf( "Delete time=%u\n", (unsigned)(deleteTime - loadTime) );
310 printf( "Total time=%u\n", (unsigned)(deleteTime - startTime) );
Lee Thomason178e4cc2013-01-25 16:19:05 -0800311 }
312 exit(0);
313 }
314
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300315 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason7f7b1622012-03-24 12:49:03 -0700316 if ( !fp ) {
317 printf( "Error opening test file 'dream.xml'.\n"
318 "Is your working directory the same as where \n"
319 "the xmltest.cpp and dream.xml file are?\n\n"
320 #if defined( _MSC_VER )
321 "In windows Visual Studio you may need to set\n"
322 "Properties->Debugging->Working Directory to '..'\n"
323 #endif
324 );
325 exit( 1 );
326 }
327 fclose( fp );
328
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700329 XMLTest( "Example-1", 0, example_1() );
330 XMLTest( "Example-2", 0, example_2() );
331 XMLTest( "Example-3", 0, example_3() );
Lee Thomason21be8822012-07-15 17:27:22 -0700332 XMLTest( "Example-4", true, example_4() );
Lee Thomason87e475a2012-03-20 11:55:29 -0700333
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700334 /* ------ Example 2: Lookup information. ---- */
Lee Thomason87e475a2012-03-20 11:55:29 -0700335
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800336 {
Lee Thomason43f59302012-02-06 18:18:11 -0800337 static const char* test[] = { "<element />",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400338 "<element></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800339 "<element><subelement/></element>",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400340 "<element><subelement></subelement></element>",
341 "<element><subelement><subsub/></subelement></element>",
342 "<!--comment beside elements--><element><subelement></subelement></element>",
343 "<!--comment beside elements, this time with spaces--> \n <element> <subelement> \n </subelement> </element>",
344 "<element attrib1='foo' attrib2=\"bar\" ></element>",
345 "<element attrib1='foo' attrib2=\"bar\" ><subelement attrib3='yeehaa' /></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800346 "<element>Text inside element.</element>",
347 "<element><b></b></element>",
348 "<element>Text inside and <b>bolded</b> in the element.</element>",
349 "<outer><element>Text inside and <b>bolded</b> in the element.</element></outer>",
Lee Thomason8ee79892012-01-25 17:44:30 -0800350 "<element>This &amp; That.</element>",
Lee Thomason18d68bd2012-01-26 18:17:26 -0800351 "<element attrib='This&lt;That' />",
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800352 0
353 };
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800354 for( int i=0; test[i]; ++i ) {
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800355 XMLDocument doc;
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800356 doc.Parse( test[i] );
Lee Thomason5cae8972012-01-24 18:03:07 -0800357 doc.Print();
Lee Thomasonec975ce2012-01-23 11:42:06 -0800358 printf( "----------------------------------------------\n" );
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800359 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800360 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800361#if 1
Lee Thomasond6277762012-02-22 16:00:12 -0800362 {
363 static const char* test = "<!--hello world\n"
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400364 " line 2\r"
365 " line 3\r\n"
366 " line 4\n\r"
367 " line 5\r-->";
Lee Thomasond6277762012-02-22 16:00:12 -0800368
369 XMLDocument doc;
370 doc.Parse( test );
371 doc.Print();
372 }
373
Lee Thomason2c85a712012-01-31 08:24:24 -0800374 {
375 static const char* test = "<element>Text before.</element>";
376 XMLDocument doc;
377 doc.Parse( test );
378 XMLElement* root = doc.FirstChildElement();
379 XMLElement* newElement = doc.NewElement( "Subelement" );
380 root->InsertEndChild( newElement );
381 doc.Print();
382 }
Lee Thomasond1983222012-02-06 08:41:24 -0800383 {
384 XMLDocument* doc = new XMLDocument();
385 static const char* test = "<element><sub/></element>";
386 doc->Parse( test );
387 delete doc;
388 }
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800389 {
Lee Thomason1ff38e02012-02-14 18:18:16 -0800390 // Test: Programmatic DOM
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800391 // Build:
392 // <element>
393 // <!--comment-->
394 // <sub attrib="1" />
395 // <sub attrib="2" />
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800396 // <sub attrib="3" >& Text!</sub>
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800397 // <element>
398
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800399 XMLDocument* doc = new XMLDocument();
Lee Thomason1ff38e02012-02-14 18:18:16 -0800400 XMLNode* element = doc->InsertEndChild( doc->NewElement( "element" ) );
401
402 XMLElement* sub[3] = { doc->NewElement( "sub" ), doc->NewElement( "sub" ), doc->NewElement( "sub" ) };
403 for( int i=0; i<3; ++i ) {
404 sub[i]->SetAttribute( "attrib", i );
405 }
406 element->InsertEndChild( sub[2] );
407 XMLNode* comment = element->InsertFirstChild( doc->NewComment( "comment" ) );
408 element->InsertAfterChild( comment, sub[0] );
409 element->InsertAfterChild( sub[0], sub[1] );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800410 sub[2]->InsertFirstChild( doc->NewText( "& Text!" ));
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800411 doc->Print();
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800412 XMLTest( "Programmatic DOM", "comment", doc->FirstChildElement( "element" )->FirstChild()->Value() );
413 XMLTest( "Programmatic DOM", "0", doc->FirstChildElement( "element" )->FirstChildElement()->Attribute( "attrib" ) );
414 XMLTest( "Programmatic DOM", 2, doc->FirstChildElement()->LastChildElement( "sub" )->IntAttribute( "attrib" ) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700415 XMLTest( "Programmatic DOM", "& Text!",
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800416 doc->FirstChildElement()->LastChildElement( "sub" )->FirstChild()->ToText()->Value() );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800417
418 // And now deletion:
419 element->DeleteChild( sub[2] );
420 doc->DeleteNode( comment );
421
422 element->FirstChildElement()->SetAttribute( "attrib", true );
423 element->LastChildElement()->DeleteAttribute( "attrib" );
424
425 XMLTest( "Programmatic DOM", true, doc->FirstChildElement()->FirstChildElement()->BoolAttribute( "attrib" ) );
426 int value = 10;
427 int result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value );
Lee Thomason21be8822012-07-15 17:27:22 -0700428 XMLTest( "Programmatic DOM", result, (int)XML_NO_ATTRIBUTE );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800429 XMLTest( "Programmatic DOM", value, 10 );
430
431 doc->Print();
432
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700433 {
434 XMLPrinter streamer;
435 doc->Print( &streamer );
436 printf( "%s", streamer.CStr() );
437 }
438 {
439 XMLPrinter streamer( 0, true );
440 doc->Print( &streamer );
441 XMLTest( "Compact mode", "<element><sub attrib=\"1\"/><sub/></element>", streamer.CStr(), false );
442 }
Lee Thomason (grinliz)6b8b0122012-09-08 21:21:00 -0700443 doc->SaveFile( "./resources/out/pretty.xml" );
444 doc->SaveFile( "./resources/out/compact.xml", true );
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800445 delete doc;
446 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800447 {
448 // Test: Dream
449 // XML1 : 1,187,569 bytes in 31,209 allocations
450 // XML2 : 469,073 bytes in 323 allocations
451 //int newStart = gNew;
452 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300453 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800454
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400455 doc.SaveFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800456 doc.PrintError();
457
458 XMLTest( "Dream", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400459 doc.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800460 XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false );
461 XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
462 doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
463 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 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400466 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800467
468 XMLDocument doc2;
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400469 doc2.LoadFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800470 XMLTest( "Dream-out", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400471 doc2.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800472 XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false );
473 XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
474 doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
475 XMLTest( "Dream-out", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400476 doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800477
478 //gNewTotal = gNew - newStart;
479 }
Lee Thomason6f381b72012-03-02 12:59:39 -0800480
481
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800482 {
483 const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
484 "<passages count=\"006\" formatversion=\"20020620\">\n"
485 " <wrong error>\n"
486 "</passages>";
487
488 XMLDocument doc;
489 doc.Parse( error );
Lee Thomason2fa81722012-11-09 12:37:46 -0800490 XMLTest( "Bad XML", doc.ErrorID(), XML_ERROR_PARSING_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800491 }
492
493 {
494 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
495
496 XMLDocument doc;
497 doc.Parse( str );
498
499 XMLElement* ele = doc.FirstChildElement();
500
501 int iVal, result;
502 double dVal;
503
504 result = ele->QueryDoubleAttribute( "attr0", &dVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700505 XMLTest( "Query attribute: int as double", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800506 XMLTest( "Query attribute: int as double", (int)dVal, 1 );
507 result = ele->QueryDoubleAttribute( "attr1", &dVal );
Thomas Roßa5221862013-05-11 10:22:12 +0200508 XMLTest( "Query attribute: double as double", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800509 XMLTest( "Query attribute: double as double", (int)dVal, 2 );
510 result = ele->QueryIntAttribute( "attr1", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700511 XMLTest( "Query attribute: double as int", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800512 XMLTest( "Query attribute: double as int", iVal, 2 );
513 result = ele->QueryIntAttribute( "attr2", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700514 XMLTest( "Query attribute: not a number", result, (int)XML_WRONG_ATTRIBUTE_TYPE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800515 result = ele->QueryIntAttribute( "bar", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700516 XMLTest( "Query attribute: does not exist", result, (int)XML_NO_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800517 }
518
519 {
520 const char* str = "<doc/>";
521
522 XMLDocument doc;
523 doc.Parse( str );
524
525 XMLElement* ele = doc.FirstChildElement();
526
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800527 int iVal, iVal2;
528 double dVal, dVal2;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800529
530 ele->SetAttribute( "str", "strValue" );
531 ele->SetAttribute( "int", 1 );
532 ele->SetAttribute( "double", -1.0 );
533
534 const char* cStr = ele->Attribute( "str" );
535 ele->QueryIntAttribute( "int", &iVal );
536 ele->QueryDoubleAttribute( "double", &dVal );
537
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800538 ele->QueryAttribute( "int", &iVal2 );
539 ele->QueryAttribute( "double", &dVal2 );
540
Lee Thomason8ba7f7d2012-03-24 13:04:04 -0700541 XMLTest( "Attribute match test", ele->Attribute( "str", "strValue" ), "strValue" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800542 XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
543 XMLTest( "Attribute round trip. int.", 1, iVal );
544 XMLTest( "Attribute round trip. double.", -1, (int)dVal );
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800545 XMLTest( "Alternate query", true, iVal == iVal2 );
546 XMLTest( "Alternate query", true, dVal == dVal2 );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800547 }
548
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800549 {
550 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300551 doc.LoadFile( "resources/utf8test.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800552
553 // Get the attribute "value" from the "Russian" element and check it.
554 XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700555 const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800556 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
557
558 XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
559
560 const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U,
561 0xd1U, 0x81U, 0xd1U, 0x81U,
562 0xd0U, 0xbaU, 0xd0U, 0xb8U,
563 0xd0U, 0xb9U, 0 };
564 const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
565
566 XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
567 XMLTest( "UTF-8: Browsing russian element name.",
568 russianText,
569 text->Value() );
570
571 // Now try for a round trip.
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400572 doc.SaveFile( "resources/out/utf8testout.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800573
574 // Check the round trip.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800575 int okay = 0;
576
Thomas Roßa6dd8c62012-07-26 20:42:18 +0200577 FILE* saved = fopen( "resources/out/utf8testout.xml", "r" );
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300578 FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800579
580 if ( saved && verify )
581 {
582 okay = 1;
PKEuSc28ba3a2012-07-16 03:08:47 -0700583 char verifyBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800584 while ( fgets( verifyBuf, 256, verify ) )
585 {
PKEuSc28ba3a2012-07-16 03:08:47 -0700586 char savedBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800587 fgets( savedBuf, 256, saved );
588 NullLineEndings( verifyBuf );
589 NullLineEndings( savedBuf );
590
591 if ( strcmp( verifyBuf, savedBuf ) )
592 {
593 printf( "verify:%s<\n", verifyBuf );
594 printf( "saved :%s<\n", savedBuf );
595 okay = 0;
596 break;
597 }
598 }
599 }
600 if ( saved )
601 fclose( saved );
602 if ( verify )
603 fclose( verify );
604 XMLTest( "UTF-8: Verified multi-language round trip.", 1, okay );
605 }
606
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800607 // --------GetText()-----------
608 {
609 const char* str = "<foo>This is text</foo>";
610 XMLDocument doc;
611 doc.Parse( str );
612 const XMLElement* element = doc.RootElement();
613
614 XMLTest( "GetText() normal use.", "This is text", element->GetText() );
615
616 str = "<foo><b>This is text</b></foo>";
617 doc.Parse( str );
618 element = doc.RootElement();
619
620 XMLTest( "GetText() contained element.", element->GetText() == 0, true );
621 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800622
Lee Thomasond6277762012-02-22 16:00:12 -0800623
Uli Kusterer321072e2014-01-21 01:57:38 +0100624 // --------SetText()-----------
625 {
626 const char* str = "<foo></foo>";
627 XMLDocument doc;
628 doc.Parse( str );
629 XMLElement* element = doc.RootElement();
630
Lee Thomason9c0678a2014-01-24 10:18:27 -0800631 element->SetText("darkness.");
632 XMLTest( "SetText() normal use (open/close).", "darkness.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100633
Lee Thomason9c0678a2014-01-24 10:18:27 -0800634 element->SetText("blue flame.");
635 XMLTest( "SetText() replace.", "blue flame.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100636
637 str = "<foo/>";
638 doc.Parse( str );
639 element = doc.RootElement();
640
Lee Thomason9c0678a2014-01-24 10:18:27 -0800641 element->SetText("The driver");
642 XMLTest( "SetText() normal use. (self-closing)", "The driver", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100643
Lee Thomason9c0678a2014-01-24 10:18:27 -0800644 element->SetText("<b>horses</b>");
645 XMLTest( "SetText() replace with tag-like text.", "<b>horses</b>", element->GetText() );
646 //doc.Print();
Uli Kusterer321072e2014-01-21 01:57:38 +0100647
648 str = "<foo><bar>Text in nested element</bar></foo>";
649 doc.Parse( str );
650 element = doc.RootElement();
651
Lee Thomason9c0678a2014-01-24 10:18:27 -0800652 element->SetText("wolves");
653 XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800654
655 str = "<foo/>";
656 doc.Parse( str );
657 element = doc.RootElement();
658
659 element->SetText( "str" );
660 XMLTest( "SetText types", "str", element->GetText() );
661
662 element->SetText( 1 );
663 XMLTest( "SetText types", "1", element->GetText() );
664
665 element->SetText( 1U );
666 XMLTest( "SetText types", "1", element->GetText() );
667
668 element->SetText( true );
669 XMLTest( "SetText types", "1", element->GetText() ); // TODO: should be 'true'?
670
671 element->SetText( 1.5f );
672 XMLTest( "SetText types", "1.5", element->GetText() );
673
674 element->SetText( 1.5 );
675 XMLTest( "SetText types", "1.5", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100676 }
677
678
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800679 // ---------- CDATA ---------------
680 {
681 const char* str = "<xmlElement>"
682 "<![CDATA["
683 "I am > the rules!\n"
684 "...since I make symbolic puns"
685 "]]>"
686 "</xmlElement>";
687 XMLDocument doc;
688 doc.Parse( str );
689 doc.Print();
Lee Thomasond6277762012-02-22 16:00:12 -0800690
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700691 XMLTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800692 "I am > the rules!\n...since I make symbolic puns",
Lee Thomasond6277762012-02-22 16:00:12 -0800693 false );
694 }
695
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800696 // ----------- CDATA -------------
697 {
698 const char* str = "<xmlElement>"
699 "<![CDATA["
700 "<b>I am > the rules!</b>\n"
701 "...since I make symbolic puns"
702 "]]>"
703 "</xmlElement>";
704 XMLDocument doc;
705 doc.Parse( str );
706 doc.Print();
707
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700708 XMLTest( "CDATA parse. [ tixml1:1480107 ]", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800709 "<b>I am > the rules!</b>\n...since I make symbolic puns",
710 false );
711 }
712
713 // InsertAfterChild causes crash.
714 {
715 // InsertBeforeChild and InsertAfterChild causes crash.
716 XMLDocument doc;
717 XMLElement* parent = doc.NewElement( "Parent" );
718 doc.InsertFirstChild( parent );
719
720 XMLElement* childText0 = doc.NewElement( "childText0" );
721 XMLElement* childText1 = doc.NewElement( "childText1" );
722
723 XMLNode* childNode0 = parent->InsertEndChild( childText0 );
724 XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
725
726 XMLTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent->LastChild() ), true );
727 }
Lee Thomasond6277762012-02-22 16:00:12 -0800728
729 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800730 // Entities not being written correctly.
731 // From Lynn Allen
Lee Thomasond6277762012-02-22 16:00:12 -0800732
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800733 const char* passages =
734 "<?xml version=\"1.0\" standalone=\"no\" ?>"
735 "<passages count=\"006\" formatversion=\"20020620\">"
736 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
737 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
738 "</passages>";
Lee Thomasond6277762012-02-22 16:00:12 -0800739
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800740 XMLDocument doc;
741 doc.Parse( passages );
742 XMLElement* psg = doc.RootElement()->FirstChildElement();
743 const char* context = psg->Attribute( "context" );
744 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 -0800745
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800746 XMLTest( "Entity transformation: read. ", expected, context, true );
Lee Thomasond6277762012-02-22 16:00:12 -0800747
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400748 FILE* textfile = fopen( "resources/out/textfile.txt", "w" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800749 if ( textfile )
750 {
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800751 XMLPrinter streamer( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800752 psg->Accept( &streamer );
753 fclose( textfile );
754 }
Thomas Roß0922b732012-09-23 16:31:22 +0200755
756 textfile = fopen( "resources/out/textfile.txt", "r" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800757 TIXMLASSERT( textfile );
758 if ( textfile )
759 {
760 char buf[ 1024 ];
761 fgets( buf, 1024, textfile );
762 XMLTest( "Entity transformation: write. ",
763 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
764 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
765 buf, false );
PKEuSc28ba3a2012-07-16 03:08:47 -0700766 fclose( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800767 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800768 }
769
770 {
Lee Thomason6f381b72012-03-02 12:59:39 -0800771 // Suppress entities.
772 const char* passages =
773 "<?xml version=\"1.0\" standalone=\"no\" ?>"
774 "<passages count=\"006\" formatversion=\"20020620\">"
775 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
776 "</passages>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700777
Lee Thomason6f381b72012-03-02 12:59:39 -0800778 XMLDocument doc( false );
779 doc.Parse( passages );
780
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700781 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ),
Lee Thomason6f381b72012-03-02 12:59:39 -0800782 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;." );
783 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value(),
784 "Crazy &ttk;" );
785 doc.Print();
786 }
787
788 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400789 const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800790
791 XMLDocument doc;
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400792 doc.Parse( test );
793 XMLTest( "dot in names", doc.Error(), false );
794 XMLTest( "dot in names", doc.FirstChildElement()->Name(), "a.elem" );
795 XMLTest( "dot in names", doc.FirstChildElement()->Attribute( "xmi.version" ), "2.0" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800796 }
797
798 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400799 const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800800
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400801 XMLDocument doc;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800802 doc.Parse( test );
803
804 XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
805 XMLTest( "Entity with one digit.",
806 text->Value(), "1.1 Start easy ignore fin thickness\n",
807 false );
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400808 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800809
810 {
811 // DOCTYPE not preserved (950171)
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700812 //
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800813 const char* doctype =
814 "<?xml version=\"1.0\" ?>"
815 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
816 "<!ELEMENT title (#PCDATA)>"
817 "<!ELEMENT books (title,authors)>"
818 "<element />";
819
820 XMLDocument doc;
821 doc.Parse( doctype );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400822 doc.SaveFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800823 doc.DeleteChild( doc.RootElement() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400824 doc.LoadFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800825 doc.Print();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700826
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800827 const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
828 XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
829
830 }
831
832 {
833 // Comments do not stream out correctly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700834 const char* doctype =
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800835 "<!-- Somewhat<evil> -->";
836 XMLDocument doc;
837 doc.Parse( doctype );
838
839 XMLComment* comment = doc.FirstChild()->ToComment();
840
841 XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
842 }
843 {
844 // Double attributes
845 const char* doctype = "<element attr='red' attr='blue' />";
846
847 XMLDocument doc;
848 doc.Parse( doctype );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700849
Lee Thomason2fa81722012-11-09 12:37:46 -0800850 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 -0800851 doc.PrintError();
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800852 }
853
854 {
855 // Embedded null in stream.
856 const char* doctype = "<element att\0r='red' attr='blue' />";
857
858 XMLDocument doc;
859 doc.Parse( doctype );
860 XMLTest( "Embedded null throws error.", true, doc.Error() );
861 }
862
863 {
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700864 // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800865 const char* str = " ";
866 XMLDocument doc;
867 doc.Parse( str );
Lee Thomason2fa81722012-11-09 12:37:46 -0800868 XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800869 }
870
871 {
872 // Low entities
873 XMLDocument doc;
874 doc.Parse( "<test>&#x0e;</test>" );
875 const char result[] = { 0x0e, 0 };
876 XMLTest( "Low entities.", doc.FirstChildElement()->GetText(), result );
877 doc.Print();
878 }
879
880 {
881 // Attribute values with trailing quotes not handled correctly
882 XMLDocument doc;
883 doc.Parse( "<foo attribute=bar\" />" );
884 XMLTest( "Throw error with bad end quotes.", doc.Error(), true );
885 }
886
887 {
888 // [ 1663758 ] Failure to report error on bad XML
889 XMLDocument xml;
890 xml.Parse("<x>");
891 XMLTest("Missing end tag at end of input", xml.Error(), true);
892 xml.Parse("<x> ");
893 XMLTest("Missing end tag with trailing whitespace", xml.Error(), true);
894 xml.Parse("<x></y>");
Lee Thomason2fa81722012-11-09 12:37:46 -0800895 XMLTest("Mismatched tags", xml.ErrorID(), XML_ERROR_MISMATCHED_ELEMENT);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700896 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800897
898
899 {
900 // [ 1475201 ] TinyXML parses entities in comments
901 XMLDocument xml;
902 xml.Parse("<!-- declarations for <head> & <body> -->"
903 "<!-- far &amp; away -->" );
904
905 XMLNode* e0 = xml.FirstChild();
906 XMLNode* e1 = e0->NextSibling();
907 XMLComment* c0 = e0->ToComment();
908 XMLComment* c1 = e1->ToComment();
909
910 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
911 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
912 }
913
914 {
915 XMLDocument xml;
916 xml.Parse( "<Parent>"
917 "<child1 att=''/>"
918 "<!-- With this comment, child2 will not be parsed! -->"
919 "<child2 att=''/>"
920 "</Parent>" );
921 xml.Print();
922
923 int count = 0;
924
925 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
926 ele;
927 ele = ele->NextSibling() )
928 {
929 ++count;
930 }
931
932 XMLTest( "Comments iterate correctly.", 3, count );
933 }
934
935 {
936 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
937 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
938 buf[60] = 239;
939 buf[61] = 0;
940
941 XMLDocument doc;
942 doc.Parse( (const char*)buf);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700943 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800944
945
946 {
947 // bug 1827248 Error while parsing a little bit malformed file
948 // Actually not malformed - should work.
949 XMLDocument xml;
950 xml.Parse( "<attributelist> </attributelist >" );
951 XMLTest( "Handle end tag whitespace", false, xml.Error() );
952 }
953
954 {
955 // This one must not result in an infinite loop
956 XMLDocument xml;
957 xml.Parse( "<infinite>loop" );
958 XMLTest( "Infinite loop test.", true, true );
959 }
960#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800961 {
962 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
963 XMLDocument doc;
964 doc.Parse( pub );
965
966 XMLDocument clone;
967 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
968 XMLNode* copy = node->ShallowClone( &clone );
969 clone.InsertEndChild( copy );
970 }
971
972 clone.Print();
973
974 int count=0;
975 const XMLNode* a=clone.FirstChild();
976 const XMLNode* b=doc.FirstChild();
977 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
978 ++count;
979 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
980 }
981 XMLTest( "Clone and Equal", 4, count );
982 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800983
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700984 {
985 // This shouldn't crash.
986 XMLDocument doc;
987 if(XML_NO_ERROR != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
988 {
989 doc.PrintError();
990 }
991 XMLTest( "Error in snprinf handling.", true, doc.Error() );
992 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700993
Lee Thomason5e3803c2012-04-16 08:57:05 -0700994 {
995 // Attribute ordering.
996 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
997 XMLDocument doc;
998 doc.Parse( xml );
999 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001000
Lee Thomason5e3803c2012-04-16 08:57:05 -07001001 const XMLAttribute* a = ele->FirstAttribute();
1002 XMLTest( "Attribute order", "1", a->Value() );
1003 a = a->Next();
1004 XMLTest( "Attribute order", "2", a->Value() );
1005 a = a->Next();
1006 XMLTest( "Attribute order", "3", a->Value() );
1007 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001008
Lee Thomason5e3803c2012-04-16 08:57:05 -07001009 ele->DeleteAttribute( "attrib2" );
1010 a = ele->FirstAttribute();
1011 XMLTest( "Attribute order", "1", a->Value() );
1012 a = a->Next();
1013 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001014
Lee Thomason5e3803c2012-04-16 08:57:05 -07001015 ele->DeleteAttribute( "attrib1" );
1016 ele->DeleteAttribute( "attrib3" );
1017 XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
1018 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001019
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001020 {
1021 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -07001022 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
1023 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
1024 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
1025 XMLDocument doc0;
1026 doc0.Parse( xml0 );
1027 XMLDocument doc1;
1028 doc1.Parse( xml1 );
1029 XMLDocument doc2;
1030 doc2.Parse( xml2 );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001031
Lee Thomason78a773d2012-07-02 10:10:19 -07001032 XMLElement* ele = 0;
1033 ele = doc0.FirstChildElement();
1034 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
1035 ele = doc1.FirstChildElement();
1036 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
1037 ele = doc2.FirstChildElement();
1038 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001039 }
1040
1041 {
1042 // Make sure we don't go into an infinite loop.
1043 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
1044 XMLDocument doc;
1045 doc.Parse( xml );
1046 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
1047 XMLElement* ele1 = ele0->NextSiblingElement();
1048 bool equal = ele0->ShallowEqual( ele1 );
1049
1050 XMLTest( "Infinite loop in shallow equal.", true, equal );
1051 }
1052
Lee Thomason5708f812012-03-28 17:46:41 -07001053 // -------- Handles ------------
1054 {
1055 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1056 XMLDocument doc;
1057 doc.Parse( xml );
Lee Thomason5708f812012-03-28 17:46:41 -07001058
1059 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
1060 XMLTest( "Handle, success, mutable", ele->Value(), "sub" );
1061
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001062 XMLHandle docH( doc );
1063 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001064 XMLTest( "Handle, dne, mutable", false, ele != 0 );
Lee Thomason5708f812012-03-28 17:46:41 -07001065 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001066
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001067 {
1068 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1069 XMLDocument doc;
1070 doc.Parse( xml );
1071 XMLConstHandle docH( doc );
1072
1073 const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
1074 XMLTest( "Handle, success, const", ele->Value(), "sub" );
1075
1076 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001077 XMLTest( "Handle, dne, const", false, ele != 0 );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001078 }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001079 {
1080 // Default Declaration & BOM
1081 XMLDocument doc;
1082 doc.InsertEndChild( doc.NewDeclaration() );
1083 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001084
Lee Thomasonf68c4382012-04-28 14:37:11 -07001085 XMLPrinter printer;
1086 doc.Print( &printer );
1087
1088 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1089 XMLTest( "BOM and default declaration", printer.CStr(), result, false );
Lee Thomason (grinliz)48ea0bc2012-05-26 14:41:14 -07001090 XMLTest( "CStrSize", printer.CStrSize(), 42, false );
Lee Thomasonf68c4382012-04-28 14:37:11 -07001091 }
Lee Thomason21be8822012-07-15 17:27:22 -07001092 {
1093 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1094 XMLDocument doc;
1095 doc.Parse( xml );
1096 XMLTest( "Ill formed XML", true, doc.Error() );
1097 }
1098
1099 // QueryXYZText
1100 {
1101 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1102 XMLDocument doc;
1103 doc.Parse( xml );
1104
1105 const XMLElement* pointElement = doc.RootElement();
1106
1107 int intValue = 0;
1108 unsigned unsignedValue = 0;
1109 float floatValue = 0;
1110 double doubleValue = 0;
1111 bool boolValue = false;
1112
1113 pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1114 pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1115 pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1116 pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1117 pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1118
1119
1120 XMLTest( "QueryIntText", intValue, 1, false );
1121 XMLTest( "QueryUnsignedText", unsignedValue, (unsigned)1, false );
1122 XMLTest( "QueryFloatText", floatValue, 1.2f, false );
1123 XMLTest( "QueryDoubleText", doubleValue, 1.2, false );
1124 XMLTest( "QueryBoolText", boolValue, true, false );
1125 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001126
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001127 {
1128 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1129 XMLDocument doc;
1130 doc.Parse( xml );
1131 XMLTest( "Non-alpha element lead letter parses.", doc.Error(), false );
1132 }
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001133
1134 {
1135 const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1136 XMLDocument doc;
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001137 doc.Parse( xml );
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001138 XMLTest("Non-alpha attribute lead character parses.", doc.Error(), false);
1139 }
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001140
1141 {
1142 const char* xml = "<3lement></3lement>";
1143 XMLDocument doc;
1144 doc.Parse( xml );
1145 XMLTest("Element names with lead digit fail to parse.", doc.Error(), true);
1146 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -07001147
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001148 {
1149 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1150 XMLDocument doc;
1151 doc.Parse( xml, 10 );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001152 XMLTest( "Set length of incoming data", doc.Error(), false );
1153 }
1154
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001155 {
1156 XMLDocument doc;
1157 doc.LoadFile( "resources/dream.xml" );
1158 doc.Clear();
1159 XMLTest( "Document Clear()'s", doc.NoChildren(), true );
1160 }
1161
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001162 // ----------- Whitespace ------------
1163 {
1164 const char* xml = "<element>"
1165 "<a> This \nis &apos; text &apos; </a>"
1166 "<b> This is &apos; text &apos; \n</b>"
1167 "<c>This is &apos; \n\n text &apos;</c>"
1168 "</element>";
1169 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1170 doc.Parse( xml );
1171
1172 const XMLElement* element = doc.FirstChildElement();
1173 for( const XMLElement* parent = element->FirstChildElement();
1174 parent;
1175 parent = parent->NextSiblingElement() )
1176 {
1177 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1178 }
1179 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001180
Lee Thomasonae9ab072012-10-24 10:17:53 -07001181#if 0
1182 {
1183 // Passes if assert doesn't fire.
1184 XMLDocument xmlDoc;
1185
1186 xmlDoc.NewDeclaration();
1187 xmlDoc.NewComment("Configuration file");
1188
1189 XMLElement *root = xmlDoc.NewElement("settings");
1190 root->SetAttribute("version", 2);
1191 }
1192#endif
1193
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001194 {
1195 const char* xml = "<element> </element>";
1196 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1197 doc.Parse( xml );
1198 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1199 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001200
Lee Thomason5b0a6772012-11-19 13:54:42 -08001201 {
1202 // An assert should not fire.
1203 const char* xml = "<element/>";
1204 XMLDocument doc;
1205 doc.Parse( xml );
1206 XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope.
1207 XMLTest( "Tracking unused elements", true, ele != 0, false );
1208 }
1209
Lee Thomasona6412ac2012-12-13 15:39:11 -08001210
1211 {
1212 const char* xml = "<parent><child>abc</child></parent>";
1213 XMLDocument doc;
1214 doc.Parse( xml );
1215 XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
1216
1217 XMLPrinter printer;
1218 ele->Accept( &printer );
1219 XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1220 }
1221
1222
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001223 {
1224 XMLDocument doc;
1225 XMLError error = doc.LoadFile( "resources/empty.xml" );
1226 XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
Lee Thomason331596e2014-09-11 14:56:43 -07001227 XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() );
Lee Thomasonc7556672014-09-14 12:39:42 -07001228 doc.PrintError();
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001229 }
1230
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001231 {
1232 // BOM preservation
1233 static const char* xml_bom_preservation = "\xef\xbb\xbf<element/>\n";
1234 {
1235 XMLDocument doc;
1236 XMLTest( "BOM preservation (parse)", XML_NO_ERROR, doc.Parse( xml_bom_preservation ), false );
1237 XMLPrinter printer;
1238 doc.Print( &printer );
1239
1240 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1241 doc.SaveFile( "resources/bomtest.xml" );
1242 }
1243 {
1244 XMLDocument doc;
1245 doc.LoadFile( "resources/bomtest.xml" );
1246 XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
1247
1248 XMLPrinter printer;
1249 doc.Print( &printer );
1250 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1251 }
1252 }
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001253
Michael Daumlinged523282013-10-23 07:47:29 +02001254 {
1255 // Insertion with Removal
1256 const char* xml = "<?xml version=\"1.0\" ?>"
1257 "<root>"
1258 "<one>"
1259 "<subtree>"
1260 "<elem>element 1</elem>text<!-- comment -->"
1261 "</subtree>"
1262 "</one>"
1263 "<two/>"
1264 "</root>";
1265 const char* xmlInsideTwo = "<?xml version=\"1.0\" ?>"
1266 "<root>"
1267 "<one/>"
1268 "<two>"
1269 "<subtree>"
1270 "<elem>element 1</elem>text<!-- comment -->"
1271 "</subtree>"
1272 "</two>"
1273 "</root>";
1274 const char* xmlAfterOne = "<?xml version=\"1.0\" ?>"
1275 "<root>"
1276 "<one/>"
1277 "<subtree>"
1278 "<elem>element 1</elem>text<!-- comment -->"
1279 "</subtree>"
1280 "<two/>"
1281 "</root>";
1282 const char* xmlAfterTwo = "<?xml version=\"1.0\" ?>"
1283 "<root>"
1284 "<one/>"
1285 "<two/>"
1286 "<subtree>"
1287 "<elem>element 1</elem>text<!-- comment -->"
1288 "</subtree>"
1289 "</root>";
1290
1291 XMLDocument doc;
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001292 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001293 XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1294 XMLElement* two = doc.RootElement()->FirstChildElement("two");
1295 two->InsertFirstChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001296 XMLPrinter printer1(0, true);
1297 doc.Accept(&printer1);
1298 XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
Michael Daumlinged523282013-10-23 07:47:29 +02001299
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001300 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001301 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1302 two = doc.RootElement()->FirstChildElement("two");
1303 doc.RootElement()->InsertAfterChild(two, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001304 XMLPrinter printer2(0, true);
1305 doc.Accept(&printer2);
1306 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001307
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001308 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001309 XMLNode* one = doc.RootElement()->FirstChildElement("one");
1310 subtree = one->FirstChildElement("subtree");
1311 doc.RootElement()->InsertAfterChild(one, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001312 XMLPrinter printer3(0, true);
1313 doc.Accept(&printer3);
1314 XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001315
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001316 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001317 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1318 two = doc.RootElement()->FirstChildElement("two");
1319 doc.RootElement()->InsertEndChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001320 XMLPrinter printer4(0, true);
1321 doc.Accept(&printer4);
1322 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001323 }
1324
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001325 {
1326 const char* xml = "<svg width = \"128\" height = \"128\">"
1327 " <text> </text>"
1328 "</svg>";
1329 XMLDocument doc;
1330 doc.Parse(xml);
1331 doc.Print();
1332 }
1333
1334#if 1
1335 // the question being explored is what kind of print to use:
1336 // https://github.com/leethomason/tinyxml2/issues/63
1337 {
1338 //const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
1339 const char* xml = "<element/>";
1340 XMLDocument doc;
1341 doc.Parse( xml );
1342 doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
1343 doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
1344 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
1345 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
1346 doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
1347 doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
1348
1349 doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
1350 doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
1351 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
1352 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
1353 doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
1354 doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
1355
1356 doc.Print();
1357
1358 /* The result of this test is platform, compiler, and library version dependent. :("
1359 XMLPrinter printer;
1360 doc.Print( &printer );
1361 XMLTest( "Float and double formatting.",
1362 "<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",
1363 printer.CStr(),
1364 true );
1365 */
1366 }
1367#endif
Lee Thomasonf07b9522014-10-30 13:25:12 -07001368
1369 {
1370 // Issue #184
1371 // If it doesn't assert, it passes. Caused by objects
1372 // getting created during parsing which are then
1373 // inaccessible in the memory pools.
1374 {
1375 XMLDocument doc;
1376 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1377 }
1378 {
1379 XMLDocument doc;
1380 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1381 doc.Clear();
1382 }
1383 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001384
1385
Lee Thomason6f381b72012-03-02 12:59:39 -08001386 // ----------- Performance tracking --------------
1387 {
1388#if defined( _MSC_VER )
1389 __int64 start, end, freq;
1390 QueryPerformanceFrequency( (LARGE_INTEGER*) &freq );
1391#endif
1392
Bruno Diasa2d4e6e2012-05-07 04:58:11 -03001393 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason6f381b72012-03-02 12:59:39 -08001394 fseek( fp, 0, SEEK_END );
1395 long size = ftell( fp );
1396 fseek( fp, 0, SEEK_SET );
1397
1398 char* mem = new char[size+1];
1399 fread( mem, size, 1, fp );
1400 fclose( fp );
1401 mem[size] = 0;
1402
1403#if defined( _MSC_VER )
1404 QueryPerformanceCounter( (LARGE_INTEGER*) &start );
1405#else
1406 clock_t cstart = clock();
1407#endif
1408 static const int COUNT = 10;
1409 for( int i=0; i<COUNT; ++i ) {
1410 XMLDocument doc;
1411 doc.Parse( mem );
1412 }
1413#if defined( _MSC_VER )
1414 QueryPerformanceCounter( (LARGE_INTEGER*) &end );
1415#else
1416 clock_t cend = clock();
1417#endif
1418
1419 delete [] mem;
1420
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001421 static const char* note =
Lee Thomason6f381b72012-03-02 12:59:39 -08001422#ifdef DEBUG
1423 "DEBUG";
1424#else
1425 "Release";
1426#endif
1427
1428#if defined( _MSC_VER )
1429 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, 1000.0 * (double)(end-start) / ( (double)freq * (double)COUNT) );
1430#else
1431 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart)/(double)COUNT );
1432#endif
1433 }
1434
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -08001435 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001436 _CrtMemCheckpoint( &endMemState );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001437 //_CrtMemDumpStatistics( &endMemState );
1438
1439 _CrtMemState diffMemState;
1440 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
1441 _CrtMemDumpStatistics( &diffMemState );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001442 //printf( "new total=%d\n", gNewTotal );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001443 #endif
1444
1445 printf ("\nPass %d, Fail %d\n", gPass, gFail);
Lee Thomason (grinliz)db304252013-07-31 12:24:52 -07001446
1447 return gFail;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08001448}