blob: 41709773099f9439a848e539e849c11b2dafbf5d [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;
Anton Indrawan8a0006c2014-11-20 18:27:07 +010026using namespace std;
Lee Thomasonec5a7b42012-02-13 18:16:52 -080027int gPass = 0;
28int gFail = 0;
29
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -080030
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070031bool XMLTest (const char* testString, const char* expected, const char* found, bool echo=true, bool extraNL=false )
Lee Thomason1ff38e02012-02-14 18:18:16 -080032{
33 bool pass = !strcmp( expected, found );
34 if ( pass )
35 printf ("[pass]");
36 else
37 printf ("[fail]");
38
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070039 if ( !echo ) {
Lee Thomason1ff38e02012-02-14 18:18:16 -080040 printf (" %s\n", testString);
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070041 }
42 else {
43 if ( extraNL ) {
44 printf( " %s\n", testString );
45 printf( "%s\n", expected );
46 printf( "%s\n", found );
47 }
48 else {
49 printf (" %s [%s][%s]\n", testString, expected, found);
50 }
51 }
Lee Thomason1ff38e02012-02-14 18:18:16 -080052
53 if ( pass )
54 ++gPass;
55 else
56 ++gFail;
57 return pass;
58}
59
60
Lee Thomason21be8822012-07-15 17:27:22 -070061template< class T > bool XMLTest( const char* testString, T expected, T found, bool echo=true )
Lee Thomason1ff38e02012-02-14 18:18:16 -080062{
63 bool pass = ( expected == found );
64 if ( pass )
65 printf ("[pass]");
66 else
67 printf ("[fail]");
68
U-Stream\Lee09a11c52012-02-17 08:31:16 -080069 if ( !echo )
Lee Thomason1ff38e02012-02-14 18:18:16 -080070 printf (" %s\n", testString);
71 else
Lee Thomasonc8312792012-07-16 12:44:41 -070072 printf (" %s [%d][%d]\n", testString, static_cast<int>(expected), static_cast<int>(found) );
Lee Thomason1ff38e02012-02-14 18:18:16 -080073
74 if ( pass )
75 ++gPass;
76 else
77 ++gFail;
78 return pass;
79}
Lee Thomasonec5a7b42012-02-13 18:16:52 -080080
U-Lama\Leee13c3e62011-12-28 14:36:55 -080081
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -080082void NullLineEndings( char* p )
83{
84 while( p && *p ) {
85 if ( *p == '\n' || *p == '\r' ) {
86 *p = 0;
87 return;
88 }
89 ++p;
90 }
91}
92
93
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070094int example_1()
95{
96 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -030097 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070098
99 return doc.ErrorID();
100}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200101/** @page Example-1 Load an XML File
102 * @dontinclude ./xmltest.cpp
103 * Basic XML file loading.
104 * The basic syntax to load an XML file from
105 * disk and check for an error. (ErrorID()
106 * will return 0 for no error.)
107 * @skip example_1()
108 * @until }
109 */
110
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700111
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700112int example_2()
113{
114 static const char* xml = "<element/>";
115 XMLDocument doc;
116 doc.Parse( xml );
117
118 return doc.ErrorID();
119}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200120/** @page Example-2 Parse an XML from char buffer
121 * @dontinclude ./xmltest.cpp
122 * Basic XML string parsing.
123 * The basic syntax to parse an XML for
124 * a char* and check for an error. (ErrorID()
125 * will return 0 for no error.)
126 * @skip example_2()
127 * @until }
128 */
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700129
130
131int example_3()
132{
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700133 static const char* xml =
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700134 "<?xml version=\"1.0\"?>"
135 "<!DOCTYPE PLAY SYSTEM \"play.dtd\">"
136 "<PLAY>"
137 "<TITLE>A Midsummer Night's Dream</TITLE>"
138 "</PLAY>";
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700139
140 XMLDocument doc;
141 doc.Parse( xml );
142
143 XMLElement* titleElement = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" );
144 const char* title = titleElement->GetText();
145 printf( "Name of play (1): %s\n", title );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700146
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700147 XMLText* textNode = titleElement->FirstChild()->ToText();
148 title = textNode->Value();
149 printf( "Name of play (2): %s\n", title );
150
151 return doc.ErrorID();
152}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200153/** @page Example-3 Get information out of XML
154 @dontinclude ./xmltest.cpp
155 In this example, we navigate a simple XML
156 file, and read some interesting text. Note
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700157 that this example doesn't use error
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200158 checking; working code should check for null
159 pointers when walking an XML tree, or use
160 XMLHandle.
161
162 (The XML is an excerpt from "dream.xml").
163
164 @skip example_3()
165 @until </PLAY>";
166
167 The structure of the XML file is:
168
169 <ul>
170 <li>(declaration)</li>
171 <li>(dtd stuff)</li>
172 <li>Element "PLAY"</li>
173 <ul>
174 <li>Element "TITLE"</li>
175 <ul>
176 <li>Text "A Midsummer Night's Dream"</li>
177 </ul>
178 </ul>
179 </ul>
180
181 For this example, we want to print out the
182 title of the play. The text of the title (what
183 we want) is child of the "TITLE" element which
184 is a child of the "PLAY" element.
185
186 We want to skip the declaration and dtd, so the
187 method FirstChildElement() is a good choice. The
188 FirstChildElement() of the Document is the "PLAY"
189 Element, the FirstChildElement() of the "PLAY" Element
190 is the "TITLE" Element.
191
192 @until ( "TITLE" );
193
194 We can then use the convenience function GetText()
195 to get the title of the play.
196
197 @until title );
198
199 Text is just another Node in the XML DOM. And in
200 fact you should be a little cautious with it, as
201 text nodes can contain elements.
202
203 @verbatim
204 Consider: A Midsummer Night's <b>Dream</b>
205 @endverbatim
206
207 It is more correct to actually query the Text Node
208 if in doubt:
209
210 @until title );
211
212 Noting that here we use FirstChild() since we are
213 looking for XMLText, not an element, and ToText()
214 is a cast from a Node to a XMLText.
215*/
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700216
217
Lee Thomason21be8822012-07-15 17:27:22 -0700218bool example_4()
219{
220 static const char* xml =
221 "<information>"
222 " <attributeApproach v='2' />"
223 " <textApproach>"
224 " <v>2</v>"
225 " </textApproach>"
226 "</information>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700227
Lee Thomason21be8822012-07-15 17:27:22 -0700228 XMLDocument doc;
229 doc.Parse( xml );
230
231 int v0 = 0;
232 int v1 = 0;
233
234 XMLElement* attributeApproachElement = doc.FirstChildElement()->FirstChildElement( "attributeApproach" );
235 attributeApproachElement->QueryIntAttribute( "v", &v0 );
236
237 XMLElement* textApproachElement = doc.FirstChildElement()->FirstChildElement( "textApproach" );
238 textApproachElement->FirstChildElement( "v" )->QueryIntText( &v1 );
239
240 printf( "Both values are the same: %d and %d\n", v0, v1 );
241
242 return !doc.Error() && ( v0 == v1 );
243}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200244/** @page Example-4 Read attributes and text information.
245 @dontinclude ./xmltest.cpp
246
247 There are fundamentally 2 ways of writing a key-value
248 pair into an XML file. (Something that's always annoyed
249 me about XML.) Either by using attributes, or by writing
250 the key name into an element and the value into
251 the text node wrapped by the element. Both approaches
252 are illustrated in this example, which shows two ways
253 to encode the value "2" into the key "v":
254
255 @skip example_4()
256 @until "</information>";
257
258 TinyXML-2 has accessors for both approaches.
259
260 When using an attribute, you navigate to the XMLElement
261 with that attribute and use the QueryIntAttribute()
262 group of methods. (Also QueryFloatAttribute(), etc.)
263
264 @skip XMLElement* attributeApproachElement
265 @until &v0 );
266
267 When using the text approach, you need to navigate
268 down one more step to the XMLElement that contains
269 the text. Note the extra FirstChildElement( "v" )
270 in the code below. The value of the text can then
271 be safely queried with the QueryIntText() group
272 of methods. (Also QueryFloatText(), etc.)
273
274 @skip XMLElement* textApproachElement
275 @until &v1 );
276*/
Lee Thomason21be8822012-07-15 17:27:22 -0700277
278
Lee Thomason178e4cc2013-01-25 16:19:05 -0800279int main( int argc, const char ** argv )
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800280{
Lee Thomason (grinliz)0a4df402012-02-27 20:50:52 -0800281 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason1ff38e02012-02-14 18:18:16 -0800282 _CrtMemCheckpoint( &startMemState );
Dmitry-Me99916592014-10-23 11:37:03 +0400283 // Enable MS Visual C++ debug heap memory leaks dump on exit
284 _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700285 #endif
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800286
Martinsh Shaiters39ddc262013-01-15 21:53:08 +0200287 #if defined(_MSC_VER) || defined(MINGW32) || defined(__MINGW32__)
ddiproiettoa8ae1f62013-05-05 18:42:52 +0300288 #if defined __MINGW64_VERSION_MAJOR && defined __MINGW64_VERSION_MINOR
289 //MINGW64: both 32 and 64-bit
290 mkdir( "resources/out/" );
291 #else
292 _mkdir( "resources/out/" );
293 #endif
Lee Thomasone9699e62012-07-25 12:24:23 -0700294 #else
295 mkdir( "resources/out/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
296 #endif
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400297
Dmitry-Me4bcbf142014-12-25 19:05:18 +0300298 {
299 TIXMLASSERT( true );
300 }
301
Lee Thomason178e4cc2013-01-25 16:19:05 -0800302 if ( argc > 1 ) {
303 XMLDocument* doc = new XMLDocument();
304 clock_t startTime = clock();
305 doc->LoadFile( argv[1] );
Anton Indrawan8a0006c2014-11-20 18:27:07 +0100306 clock_t loadTime = clock();
Lee Thomason178e4cc2013-01-25 16:19:05 -0800307 int errorID = doc->ErrorID();
308 delete doc; doc = 0;
Anton Indrawan8a0006c2014-11-20 18:27:07 +0100309 clock_t deleteTime = clock();
Lee Thomason178e4cc2013-01-25 16:19:05 -0800310
311 printf( "Test file '%s' loaded. ErrorID=%d\n", argv[1], errorID );
312 if ( !errorID ) {
Lee Thomason (grinliz)d6bd7362013-05-11 20:23:13 -0700313 printf( "Load time=%u\n", (unsigned)(loadTime - startTime) );
314 printf( "Delete time=%u\n", (unsigned)(deleteTime - loadTime) );
315 printf( "Total time=%u\n", (unsigned)(deleteTime - startTime) );
Lee Thomason178e4cc2013-01-25 16:19:05 -0800316 }
317 exit(0);
318 }
319
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300320 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason7f7b1622012-03-24 12:49:03 -0700321 if ( !fp ) {
322 printf( "Error opening test file 'dream.xml'.\n"
323 "Is your working directory the same as where \n"
324 "the xmltest.cpp and dream.xml file are?\n\n"
325 #if defined( _MSC_VER )
326 "In windows Visual Studio you may need to set\n"
327 "Properties->Debugging->Working Directory to '..'\n"
328 #endif
329 );
330 exit( 1 );
331 }
332 fclose( fp );
333
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700334 XMLTest( "Example-1", 0, example_1() );
335 XMLTest( "Example-2", 0, example_2() );
336 XMLTest( "Example-3", 0, example_3() );
Lee Thomason21be8822012-07-15 17:27:22 -0700337 XMLTest( "Example-4", true, example_4() );
Lee Thomason87e475a2012-03-20 11:55:29 -0700338
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700339 /* ------ Example 2: Lookup information. ---- */
Lee Thomason87e475a2012-03-20 11:55:29 -0700340
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800341 {
Lee Thomason43f59302012-02-06 18:18:11 -0800342 static const char* test[] = { "<element />",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400343 "<element></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800344 "<element><subelement/></element>",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400345 "<element><subelement></subelement></element>",
346 "<element><subelement><subsub/></subelement></element>",
347 "<!--comment beside elements--><element><subelement></subelement></element>",
348 "<!--comment beside elements, this time with spaces--> \n <element> <subelement> \n </subelement> </element>",
349 "<element attrib1='foo' attrib2=\"bar\" ></element>",
350 "<element attrib1='foo' attrib2=\"bar\" ><subelement attrib3='yeehaa' /></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800351 "<element>Text inside element.</element>",
352 "<element><b></b></element>",
353 "<element>Text inside and <b>bolded</b> in the element.</element>",
354 "<outer><element>Text inside and <b>bolded</b> in the element.</element></outer>",
Lee Thomason8ee79892012-01-25 17:44:30 -0800355 "<element>This &amp; That.</element>",
Lee Thomason18d68bd2012-01-26 18:17:26 -0800356 "<element attrib='This&lt;That' />",
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800357 0
358 };
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800359 for( int i=0; test[i]; ++i ) {
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800360 XMLDocument doc;
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800361 doc.Parse( test[i] );
Lee Thomason5cae8972012-01-24 18:03:07 -0800362 doc.Print();
Lee Thomasonec975ce2012-01-23 11:42:06 -0800363 printf( "----------------------------------------------\n" );
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800364 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800365 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800366#if 1
Lee Thomasond6277762012-02-22 16:00:12 -0800367 {
368 static const char* test = "<!--hello world\n"
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400369 " line 2\r"
370 " line 3\r\n"
371 " line 4\n\r"
372 " line 5\r-->";
Lee Thomasond6277762012-02-22 16:00:12 -0800373
374 XMLDocument doc;
375 doc.Parse( test );
376 doc.Print();
377 }
378
Lee Thomason2c85a712012-01-31 08:24:24 -0800379 {
380 static const char* test = "<element>Text before.</element>";
381 XMLDocument doc;
382 doc.Parse( test );
383 XMLElement* root = doc.FirstChildElement();
384 XMLElement* newElement = doc.NewElement( "Subelement" );
385 root->InsertEndChild( newElement );
386 doc.Print();
387 }
Lee Thomasond1983222012-02-06 08:41:24 -0800388 {
389 XMLDocument* doc = new XMLDocument();
390 static const char* test = "<element><sub/></element>";
391 doc->Parse( test );
392 delete doc;
393 }
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800394 {
Lee Thomason1ff38e02012-02-14 18:18:16 -0800395 // Test: Programmatic DOM
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800396 // Build:
397 // <element>
398 // <!--comment-->
399 // <sub attrib="1" />
400 // <sub attrib="2" />
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800401 // <sub attrib="3" >& Text!</sub>
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800402 // <element>
403
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800404 XMLDocument* doc = new XMLDocument();
Lee Thomason1ff38e02012-02-14 18:18:16 -0800405 XMLNode* element = doc->InsertEndChild( doc->NewElement( "element" ) );
406
407 XMLElement* sub[3] = { doc->NewElement( "sub" ), doc->NewElement( "sub" ), doc->NewElement( "sub" ) };
408 for( int i=0; i<3; ++i ) {
409 sub[i]->SetAttribute( "attrib", i );
410 }
411 element->InsertEndChild( sub[2] );
412 XMLNode* comment = element->InsertFirstChild( doc->NewComment( "comment" ) );
413 element->InsertAfterChild( comment, sub[0] );
414 element->InsertAfterChild( sub[0], sub[1] );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800415 sub[2]->InsertFirstChild( doc->NewText( "& Text!" ));
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800416 doc->Print();
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800417 XMLTest( "Programmatic DOM", "comment", doc->FirstChildElement( "element" )->FirstChild()->Value() );
418 XMLTest( "Programmatic DOM", "0", doc->FirstChildElement( "element" )->FirstChildElement()->Attribute( "attrib" ) );
419 XMLTest( "Programmatic DOM", 2, doc->FirstChildElement()->LastChildElement( "sub" )->IntAttribute( "attrib" ) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700420 XMLTest( "Programmatic DOM", "& Text!",
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800421 doc->FirstChildElement()->LastChildElement( "sub" )->FirstChild()->ToText()->Value() );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800422
423 // And now deletion:
424 element->DeleteChild( sub[2] );
425 doc->DeleteNode( comment );
426
427 element->FirstChildElement()->SetAttribute( "attrib", true );
428 element->LastChildElement()->DeleteAttribute( "attrib" );
429
430 XMLTest( "Programmatic DOM", true, doc->FirstChildElement()->FirstChildElement()->BoolAttribute( "attrib" ) );
431 int value = 10;
432 int result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value );
Lee Thomason21be8822012-07-15 17:27:22 -0700433 XMLTest( "Programmatic DOM", result, (int)XML_NO_ATTRIBUTE );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800434 XMLTest( "Programmatic DOM", value, 10 );
435
436 doc->Print();
437
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700438 {
439 XMLPrinter streamer;
440 doc->Print( &streamer );
441 printf( "%s", streamer.CStr() );
442 }
443 {
444 XMLPrinter streamer( 0, true );
445 doc->Print( &streamer );
446 XMLTest( "Compact mode", "<element><sub attrib=\"1\"/><sub/></element>", streamer.CStr(), false );
447 }
Lee Thomason (grinliz)6b8b0122012-09-08 21:21:00 -0700448 doc->SaveFile( "./resources/out/pretty.xml" );
449 doc->SaveFile( "./resources/out/compact.xml", true );
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800450 delete doc;
451 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800452 {
453 // Test: Dream
454 // XML1 : 1,187,569 bytes in 31,209 allocations
455 // XML2 : 469,073 bytes in 323 allocations
456 //int newStart = gNew;
457 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300458 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800459
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400460 doc.SaveFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800461 doc.PrintError();
462
463 XMLTest( "Dream", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400464 doc.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800465 XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false );
466 XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
467 doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
468 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400469 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800470 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400471 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800472
473 XMLDocument doc2;
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400474 doc2.LoadFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800475 XMLTest( "Dream-out", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400476 doc2.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800477 XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false );
478 XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
479 doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
480 XMLTest( "Dream-out", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400481 doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800482
483 //gNewTotal = gNew - newStart;
484 }
Lee Thomason6f381b72012-03-02 12:59:39 -0800485
486
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800487 {
488 const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
489 "<passages count=\"006\" formatversion=\"20020620\">\n"
490 " <wrong error>\n"
491 "</passages>";
492
493 XMLDocument doc;
494 doc.Parse( error );
Lee Thomason2fa81722012-11-09 12:37:46 -0800495 XMLTest( "Bad XML", doc.ErrorID(), XML_ERROR_PARSING_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800496 }
497
498 {
499 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
500
501 XMLDocument doc;
502 doc.Parse( str );
503
504 XMLElement* ele = doc.FirstChildElement();
505
506 int iVal, result;
507 double dVal;
508
509 result = ele->QueryDoubleAttribute( "attr0", &dVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700510 XMLTest( "Query attribute: int as double", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800511 XMLTest( "Query attribute: int as double", (int)dVal, 1 );
512 result = ele->QueryDoubleAttribute( "attr1", &dVal );
Thomas Roßa5221862013-05-11 10:22:12 +0200513 XMLTest( "Query attribute: double as double", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800514 XMLTest( "Query attribute: double as double", (int)dVal, 2 );
515 result = ele->QueryIntAttribute( "attr1", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700516 XMLTest( "Query attribute: double as int", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800517 XMLTest( "Query attribute: double as int", iVal, 2 );
518 result = ele->QueryIntAttribute( "attr2", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700519 XMLTest( "Query attribute: not a number", result, (int)XML_WRONG_ATTRIBUTE_TYPE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800520 result = ele->QueryIntAttribute( "bar", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700521 XMLTest( "Query attribute: does not exist", result, (int)XML_NO_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800522 }
523
524 {
525 const char* str = "<doc/>";
526
527 XMLDocument doc;
528 doc.Parse( str );
529
530 XMLElement* ele = doc.FirstChildElement();
531
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800532 int iVal, iVal2;
533 double dVal, dVal2;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800534
535 ele->SetAttribute( "str", "strValue" );
536 ele->SetAttribute( "int", 1 );
537 ele->SetAttribute( "double", -1.0 );
538
539 const char* cStr = ele->Attribute( "str" );
540 ele->QueryIntAttribute( "int", &iVal );
541 ele->QueryDoubleAttribute( "double", &dVal );
542
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800543 ele->QueryAttribute( "int", &iVal2 );
544 ele->QueryAttribute( "double", &dVal2 );
545
Lee Thomason8ba7f7d2012-03-24 13:04:04 -0700546 XMLTest( "Attribute match test", ele->Attribute( "str", "strValue" ), "strValue" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800547 XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
548 XMLTest( "Attribute round trip. int.", 1, iVal );
549 XMLTest( "Attribute round trip. double.", -1, (int)dVal );
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800550 XMLTest( "Alternate query", true, iVal == iVal2 );
551 XMLTest( "Alternate query", true, dVal == dVal2 );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800552 }
553
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800554 {
555 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300556 doc.LoadFile( "resources/utf8test.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800557
558 // Get the attribute "value" from the "Russian" element and check it.
559 XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700560 const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800561 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
562
563 XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
564
565 const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U,
566 0xd1U, 0x81U, 0xd1U, 0x81U,
567 0xd0U, 0xbaU, 0xd0U, 0xb8U,
568 0xd0U, 0xb9U, 0 };
569 const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
570
571 XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
572 XMLTest( "UTF-8: Browsing russian element name.",
573 russianText,
574 text->Value() );
575
576 // Now try for a round trip.
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400577 doc.SaveFile( "resources/out/utf8testout.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800578
579 // Check the round trip.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800580 int okay = 0;
581
Thomas Roßa6dd8c62012-07-26 20:42:18 +0200582 FILE* saved = fopen( "resources/out/utf8testout.xml", "r" );
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300583 FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800584
585 if ( saved && verify )
586 {
587 okay = 1;
PKEuSc28ba3a2012-07-16 03:08:47 -0700588 char verifyBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800589 while ( fgets( verifyBuf, 256, verify ) )
590 {
PKEuSc28ba3a2012-07-16 03:08:47 -0700591 char savedBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800592 fgets( savedBuf, 256, saved );
593 NullLineEndings( verifyBuf );
594 NullLineEndings( savedBuf );
595
596 if ( strcmp( verifyBuf, savedBuf ) )
597 {
598 printf( "verify:%s<\n", verifyBuf );
599 printf( "saved :%s<\n", savedBuf );
600 okay = 0;
601 break;
602 }
603 }
604 }
605 if ( saved )
606 fclose( saved );
607 if ( verify )
608 fclose( verify );
609 XMLTest( "UTF-8: Verified multi-language round trip.", 1, okay );
610 }
611
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800612 // --------GetText()-----------
613 {
614 const char* str = "<foo>This is text</foo>";
615 XMLDocument doc;
616 doc.Parse( str );
617 const XMLElement* element = doc.RootElement();
618
619 XMLTest( "GetText() normal use.", "This is text", element->GetText() );
620
621 str = "<foo><b>This is text</b></foo>";
622 doc.Parse( str );
623 element = doc.RootElement();
624
625 XMLTest( "GetText() contained element.", element->GetText() == 0, true );
626 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800627
Lee Thomasond6277762012-02-22 16:00:12 -0800628
Uli Kusterer321072e2014-01-21 01:57:38 +0100629 // --------SetText()-----------
630 {
631 const char* str = "<foo></foo>";
632 XMLDocument doc;
633 doc.Parse( str );
634 XMLElement* element = doc.RootElement();
635
Lee Thomason9c0678a2014-01-24 10:18:27 -0800636 element->SetText("darkness.");
637 XMLTest( "SetText() normal use (open/close).", "darkness.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100638
Lee Thomason9c0678a2014-01-24 10:18:27 -0800639 element->SetText("blue flame.");
640 XMLTest( "SetText() replace.", "blue flame.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100641
642 str = "<foo/>";
643 doc.Parse( str );
644 element = doc.RootElement();
645
Lee Thomason9c0678a2014-01-24 10:18:27 -0800646 element->SetText("The driver");
647 XMLTest( "SetText() normal use. (self-closing)", "The driver", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100648
Lee Thomason9c0678a2014-01-24 10:18:27 -0800649 element->SetText("<b>horses</b>");
650 XMLTest( "SetText() replace with tag-like text.", "<b>horses</b>", element->GetText() );
651 //doc.Print();
Uli Kusterer321072e2014-01-21 01:57:38 +0100652
653 str = "<foo><bar>Text in nested element</bar></foo>";
654 doc.Parse( str );
655 element = doc.RootElement();
656
Lee Thomason9c0678a2014-01-24 10:18:27 -0800657 element->SetText("wolves");
658 XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800659
660 str = "<foo/>";
661 doc.Parse( str );
662 element = doc.RootElement();
663
664 element->SetText( "str" );
665 XMLTest( "SetText types", "str", element->GetText() );
666
667 element->SetText( 1 );
668 XMLTest( "SetText types", "1", element->GetText() );
669
670 element->SetText( 1U );
671 XMLTest( "SetText types", "1", element->GetText() );
672
673 element->SetText( true );
674 XMLTest( "SetText types", "1", element->GetText() ); // TODO: should be 'true'?
675
676 element->SetText( 1.5f );
677 XMLTest( "SetText types", "1.5", element->GetText() );
678
679 element->SetText( 1.5 );
680 XMLTest( "SetText types", "1.5", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100681 }
682
683
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800684 // ---------- CDATA ---------------
685 {
686 const char* str = "<xmlElement>"
687 "<![CDATA["
688 "I am > the rules!\n"
689 "...since I make symbolic puns"
690 "]]>"
691 "</xmlElement>";
692 XMLDocument doc;
693 doc.Parse( str );
694 doc.Print();
Lee Thomasond6277762012-02-22 16:00:12 -0800695
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700696 XMLTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800697 "I am > the rules!\n...since I make symbolic puns",
Lee Thomasond6277762012-02-22 16:00:12 -0800698 false );
699 }
700
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800701 // ----------- CDATA -------------
702 {
703 const char* str = "<xmlElement>"
704 "<![CDATA["
705 "<b>I am > the rules!</b>\n"
706 "...since I make symbolic puns"
707 "]]>"
708 "</xmlElement>";
709 XMLDocument doc;
710 doc.Parse( str );
711 doc.Print();
712
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700713 XMLTest( "CDATA parse. [ tixml1:1480107 ]", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800714 "<b>I am > the rules!</b>\n...since I make symbolic puns",
715 false );
716 }
717
718 // InsertAfterChild causes crash.
719 {
720 // InsertBeforeChild and InsertAfterChild causes crash.
721 XMLDocument doc;
722 XMLElement* parent = doc.NewElement( "Parent" );
723 doc.InsertFirstChild( parent );
724
725 XMLElement* childText0 = doc.NewElement( "childText0" );
726 XMLElement* childText1 = doc.NewElement( "childText1" );
727
728 XMLNode* childNode0 = parent->InsertEndChild( childText0 );
729 XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
730
731 XMLTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent->LastChild() ), true );
732 }
Lee Thomasond6277762012-02-22 16:00:12 -0800733
734 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800735 // Entities not being written correctly.
736 // From Lynn Allen
Lee Thomasond6277762012-02-22 16:00:12 -0800737
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800738 const char* passages =
739 "<?xml version=\"1.0\" standalone=\"no\" ?>"
740 "<passages count=\"006\" formatversion=\"20020620\">"
741 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
742 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
743 "</passages>";
Lee Thomasond6277762012-02-22 16:00:12 -0800744
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800745 XMLDocument doc;
746 doc.Parse( passages );
747 XMLElement* psg = doc.RootElement()->FirstChildElement();
748 const char* context = psg->Attribute( "context" );
749 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 -0800750
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800751 XMLTest( "Entity transformation: read. ", expected, context, true );
Lee Thomasond6277762012-02-22 16:00:12 -0800752
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400753 FILE* textfile = fopen( "resources/out/textfile.txt", "w" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800754 if ( textfile )
755 {
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800756 XMLPrinter streamer( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800757 psg->Accept( &streamer );
758 fclose( textfile );
759 }
Thomas Roß0922b732012-09-23 16:31:22 +0200760
761 textfile = fopen( "resources/out/textfile.txt", "r" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800762 TIXMLASSERT( textfile );
763 if ( textfile )
764 {
765 char buf[ 1024 ];
766 fgets( buf, 1024, textfile );
767 XMLTest( "Entity transformation: write. ",
768 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
769 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
770 buf, false );
PKEuSc28ba3a2012-07-16 03:08:47 -0700771 fclose( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800772 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800773 }
774
775 {
Lee Thomason6f381b72012-03-02 12:59:39 -0800776 // Suppress entities.
777 const char* passages =
778 "<?xml version=\"1.0\" standalone=\"no\" ?>"
779 "<passages count=\"006\" formatversion=\"20020620\">"
780 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
781 "</passages>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700782
Lee Thomason6f381b72012-03-02 12:59:39 -0800783 XMLDocument doc( false );
784 doc.Parse( passages );
785
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700786 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ),
Lee Thomason6f381b72012-03-02 12:59:39 -0800787 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;." );
788 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value(),
789 "Crazy &ttk;" );
790 doc.Print();
791 }
792
793 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400794 const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800795
796 XMLDocument doc;
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400797 doc.Parse( test );
798 XMLTest( "dot in names", doc.Error(), false );
799 XMLTest( "dot in names", doc.FirstChildElement()->Name(), "a.elem" );
800 XMLTest( "dot in names", doc.FirstChildElement()->Attribute( "xmi.version" ), "2.0" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800801 }
802
803 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400804 const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800805
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400806 XMLDocument doc;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800807 doc.Parse( test );
808
809 XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
810 XMLTest( "Entity with one digit.",
811 text->Value(), "1.1 Start easy ignore fin thickness\n",
812 false );
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400813 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800814
815 {
816 // DOCTYPE not preserved (950171)
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700817 //
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800818 const char* doctype =
819 "<?xml version=\"1.0\" ?>"
820 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
821 "<!ELEMENT title (#PCDATA)>"
822 "<!ELEMENT books (title,authors)>"
823 "<element />";
824
825 XMLDocument doc;
826 doc.Parse( doctype );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400827 doc.SaveFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800828 doc.DeleteChild( doc.RootElement() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400829 doc.LoadFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800830 doc.Print();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700831
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800832 const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
833 XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
834
835 }
836
837 {
838 // Comments do not stream out correctly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700839 const char* doctype =
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800840 "<!-- Somewhat<evil> -->";
841 XMLDocument doc;
842 doc.Parse( doctype );
843
844 XMLComment* comment = doc.FirstChild()->ToComment();
845
846 XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
847 }
848 {
849 // Double attributes
850 const char* doctype = "<element attr='red' attr='blue' />";
851
852 XMLDocument doc;
853 doc.Parse( doctype );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700854
Lee Thomason2fa81722012-11-09 12:37:46 -0800855 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 -0800856 doc.PrintError();
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800857 }
858
859 {
860 // Embedded null in stream.
861 const char* doctype = "<element att\0r='red' attr='blue' />";
862
863 XMLDocument doc;
864 doc.Parse( doctype );
865 XMLTest( "Embedded null throws error.", true, doc.Error() );
866 }
867
868 {
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700869 // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800870 const char* str = " ";
871 XMLDocument doc;
872 doc.Parse( str );
Lee Thomason2fa81722012-11-09 12:37:46 -0800873 XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800874 }
875
876 {
877 // Low entities
878 XMLDocument doc;
879 doc.Parse( "<test>&#x0e;</test>" );
880 const char result[] = { 0x0e, 0 };
881 XMLTest( "Low entities.", doc.FirstChildElement()->GetText(), result );
882 doc.Print();
883 }
884
885 {
886 // Attribute values with trailing quotes not handled correctly
887 XMLDocument doc;
888 doc.Parse( "<foo attribute=bar\" />" );
889 XMLTest( "Throw error with bad end quotes.", doc.Error(), true );
890 }
891
892 {
893 // [ 1663758 ] Failure to report error on bad XML
894 XMLDocument xml;
895 xml.Parse("<x>");
896 XMLTest("Missing end tag at end of input", xml.Error(), true);
897 xml.Parse("<x> ");
898 XMLTest("Missing end tag with trailing whitespace", xml.Error(), true);
899 xml.Parse("<x></y>");
Lee Thomason2fa81722012-11-09 12:37:46 -0800900 XMLTest("Mismatched tags", xml.ErrorID(), XML_ERROR_MISMATCHED_ELEMENT);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700901 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800902
903
904 {
905 // [ 1475201 ] TinyXML parses entities in comments
906 XMLDocument xml;
907 xml.Parse("<!-- declarations for <head> & <body> -->"
908 "<!-- far &amp; away -->" );
909
910 XMLNode* e0 = xml.FirstChild();
911 XMLNode* e1 = e0->NextSibling();
912 XMLComment* c0 = e0->ToComment();
913 XMLComment* c1 = e1->ToComment();
914
915 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
916 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
917 }
918
919 {
920 XMLDocument xml;
921 xml.Parse( "<Parent>"
922 "<child1 att=''/>"
923 "<!-- With this comment, child2 will not be parsed! -->"
924 "<child2 att=''/>"
925 "</Parent>" );
926 xml.Print();
927
928 int count = 0;
929
930 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
931 ele;
932 ele = ele->NextSibling() )
933 {
934 ++count;
935 }
936
937 XMLTest( "Comments iterate correctly.", 3, count );
938 }
939
940 {
941 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
942 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
943 buf[60] = 239;
944 buf[61] = 0;
945
946 XMLDocument doc;
947 doc.Parse( (const char*)buf);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700948 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800949
950
951 {
952 // bug 1827248 Error while parsing a little bit malformed file
953 // Actually not malformed - should work.
954 XMLDocument xml;
955 xml.Parse( "<attributelist> </attributelist >" );
956 XMLTest( "Handle end tag whitespace", false, xml.Error() );
957 }
958
959 {
960 // This one must not result in an infinite loop
961 XMLDocument xml;
962 xml.Parse( "<infinite>loop" );
963 XMLTest( "Infinite loop test.", true, true );
964 }
965#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800966 {
967 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
968 XMLDocument doc;
969 doc.Parse( pub );
970
971 XMLDocument clone;
972 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
973 XMLNode* copy = node->ShallowClone( &clone );
974 clone.InsertEndChild( copy );
975 }
976
977 clone.Print();
978
979 int count=0;
980 const XMLNode* a=clone.FirstChild();
981 const XMLNode* b=doc.FirstChild();
982 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
983 ++count;
984 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
985 }
986 XMLTest( "Clone and Equal", 4, count );
987 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800988
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700989 {
990 // This shouldn't crash.
991 XMLDocument doc;
992 if(XML_NO_ERROR != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
993 {
994 doc.PrintError();
995 }
996 XMLTest( "Error in snprinf handling.", true, doc.Error() );
997 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700998
Lee Thomason5e3803c2012-04-16 08:57:05 -0700999 {
1000 // Attribute ordering.
1001 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
1002 XMLDocument doc;
1003 doc.Parse( xml );
1004 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001005
Lee Thomason5e3803c2012-04-16 08:57:05 -07001006 const XMLAttribute* a = ele->FirstAttribute();
1007 XMLTest( "Attribute order", "1", a->Value() );
1008 a = a->Next();
1009 XMLTest( "Attribute order", "2", a->Value() );
1010 a = a->Next();
1011 XMLTest( "Attribute order", "3", a->Value() );
1012 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001013
Lee Thomason5e3803c2012-04-16 08:57:05 -07001014 ele->DeleteAttribute( "attrib2" );
1015 a = ele->FirstAttribute();
1016 XMLTest( "Attribute order", "1", a->Value() );
1017 a = a->Next();
1018 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001019
Lee Thomason5e3803c2012-04-16 08:57:05 -07001020 ele->DeleteAttribute( "attrib1" );
1021 ele->DeleteAttribute( "attrib3" );
1022 XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
1023 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001024
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001025 {
1026 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -07001027 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
1028 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
1029 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
1030 XMLDocument doc0;
1031 doc0.Parse( xml0 );
1032 XMLDocument doc1;
1033 doc1.Parse( xml1 );
1034 XMLDocument doc2;
1035 doc2.Parse( xml2 );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001036
Lee Thomason78a773d2012-07-02 10:10:19 -07001037 XMLElement* ele = 0;
1038 ele = doc0.FirstChildElement();
1039 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
1040 ele = doc1.FirstChildElement();
1041 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
1042 ele = doc2.FirstChildElement();
1043 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001044 }
1045
1046 {
1047 // Make sure we don't go into an infinite loop.
1048 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
1049 XMLDocument doc;
1050 doc.Parse( xml );
1051 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
1052 XMLElement* ele1 = ele0->NextSiblingElement();
1053 bool equal = ele0->ShallowEqual( ele1 );
1054
1055 XMLTest( "Infinite loop in shallow equal.", true, equal );
1056 }
1057
Lee Thomason5708f812012-03-28 17:46:41 -07001058 // -------- Handles ------------
1059 {
1060 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1061 XMLDocument doc;
1062 doc.Parse( xml );
Lee Thomason5708f812012-03-28 17:46:41 -07001063
1064 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
1065 XMLTest( "Handle, success, mutable", ele->Value(), "sub" );
1066
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001067 XMLHandle docH( doc );
1068 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001069 XMLTest( "Handle, dne, mutable", false, ele != 0 );
Lee Thomason5708f812012-03-28 17:46:41 -07001070 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001071
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001072 {
1073 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1074 XMLDocument doc;
1075 doc.Parse( xml );
1076 XMLConstHandle docH( doc );
1077
1078 const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
1079 XMLTest( "Handle, success, const", ele->Value(), "sub" );
1080
1081 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001082 XMLTest( "Handle, dne, const", false, ele != 0 );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001083 }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001084 {
1085 // Default Declaration & BOM
1086 XMLDocument doc;
1087 doc.InsertEndChild( doc.NewDeclaration() );
1088 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001089
Lee Thomasonf68c4382012-04-28 14:37:11 -07001090 XMLPrinter printer;
1091 doc.Print( &printer );
1092
1093 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1094 XMLTest( "BOM and default declaration", printer.CStr(), result, false );
Lee Thomason (grinliz)48ea0bc2012-05-26 14:41:14 -07001095 XMLTest( "CStrSize", printer.CStrSize(), 42, false );
Lee Thomasonf68c4382012-04-28 14:37:11 -07001096 }
Lee Thomason21be8822012-07-15 17:27:22 -07001097 {
1098 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1099 XMLDocument doc;
1100 doc.Parse( xml );
1101 XMLTest( "Ill formed XML", true, doc.Error() );
1102 }
1103
1104 // QueryXYZText
1105 {
1106 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1107 XMLDocument doc;
1108 doc.Parse( xml );
1109
1110 const XMLElement* pointElement = doc.RootElement();
1111
1112 int intValue = 0;
1113 unsigned unsignedValue = 0;
1114 float floatValue = 0;
1115 double doubleValue = 0;
1116 bool boolValue = false;
1117
1118 pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1119 pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1120 pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1121 pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1122 pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1123
1124
1125 XMLTest( "QueryIntText", intValue, 1, false );
1126 XMLTest( "QueryUnsignedText", unsignedValue, (unsigned)1, false );
1127 XMLTest( "QueryFloatText", floatValue, 1.2f, false );
1128 XMLTest( "QueryDoubleText", doubleValue, 1.2, false );
1129 XMLTest( "QueryBoolText", boolValue, true, false );
1130 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001131
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001132 {
1133 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1134 XMLDocument doc;
1135 doc.Parse( xml );
1136 XMLTest( "Non-alpha element lead letter parses.", doc.Error(), false );
1137 }
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001138
1139 {
1140 const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1141 XMLDocument doc;
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001142 doc.Parse( xml );
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001143 XMLTest("Non-alpha attribute lead character parses.", doc.Error(), false);
1144 }
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001145
1146 {
1147 const char* xml = "<3lement></3lement>";
1148 XMLDocument doc;
1149 doc.Parse( xml );
1150 XMLTest("Element names with lead digit fail to parse.", doc.Error(), true);
1151 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -07001152
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001153 {
1154 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1155 XMLDocument doc;
1156 doc.Parse( xml, 10 );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001157 XMLTest( "Set length of incoming data", doc.Error(), false );
1158 }
1159
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001160 {
1161 XMLDocument doc;
1162 doc.LoadFile( "resources/dream.xml" );
1163 doc.Clear();
1164 XMLTest( "Document Clear()'s", doc.NoChildren(), true );
1165 }
1166
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001167 // ----------- Whitespace ------------
1168 {
1169 const char* xml = "<element>"
1170 "<a> This \nis &apos; text &apos; </a>"
1171 "<b> This is &apos; text &apos; \n</b>"
1172 "<c>This is &apos; \n\n text &apos;</c>"
1173 "</element>";
1174 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1175 doc.Parse( xml );
1176
1177 const XMLElement* element = doc.FirstChildElement();
1178 for( const XMLElement* parent = element->FirstChildElement();
1179 parent;
1180 parent = parent->NextSiblingElement() )
1181 {
1182 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1183 }
1184 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001185
Lee Thomasonae9ab072012-10-24 10:17:53 -07001186#if 0
1187 {
1188 // Passes if assert doesn't fire.
1189 XMLDocument xmlDoc;
1190
1191 xmlDoc.NewDeclaration();
1192 xmlDoc.NewComment("Configuration file");
1193
1194 XMLElement *root = xmlDoc.NewElement("settings");
1195 root->SetAttribute("version", 2);
1196 }
1197#endif
1198
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001199 {
1200 const char* xml = "<element> </element>";
1201 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1202 doc.Parse( xml );
1203 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1204 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001205
Lee Thomason5b0a6772012-11-19 13:54:42 -08001206 {
1207 // An assert should not fire.
1208 const char* xml = "<element/>";
1209 XMLDocument doc;
1210 doc.Parse( xml );
1211 XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope.
1212 XMLTest( "Tracking unused elements", true, ele != 0, false );
1213 }
1214
Lee Thomasona6412ac2012-12-13 15:39:11 -08001215
1216 {
1217 const char* xml = "<parent><child>abc</child></parent>";
1218 XMLDocument doc;
1219 doc.Parse( xml );
1220 XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
1221
1222 XMLPrinter printer;
1223 ele->Accept( &printer );
1224 XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1225 }
1226
1227
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001228 {
1229 XMLDocument doc;
1230 XMLError error = doc.LoadFile( "resources/empty.xml" );
1231 XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
Lee Thomason331596e2014-09-11 14:56:43 -07001232 XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() );
Lee Thomasonc7556672014-09-14 12:39:42 -07001233 doc.PrintError();
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001234 }
1235
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001236 {
1237 // BOM preservation
1238 static const char* xml_bom_preservation = "\xef\xbb\xbf<element/>\n";
1239 {
1240 XMLDocument doc;
1241 XMLTest( "BOM preservation (parse)", XML_NO_ERROR, doc.Parse( xml_bom_preservation ), false );
1242 XMLPrinter printer;
1243 doc.Print( &printer );
1244
1245 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1246 doc.SaveFile( "resources/bomtest.xml" );
1247 }
1248 {
1249 XMLDocument doc;
1250 doc.LoadFile( "resources/bomtest.xml" );
1251 XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
1252
1253 XMLPrinter printer;
1254 doc.Print( &printer );
1255 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1256 }
1257 }
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001258
Michael Daumlinged523282013-10-23 07:47:29 +02001259 {
1260 // Insertion with Removal
1261 const char* xml = "<?xml version=\"1.0\" ?>"
1262 "<root>"
1263 "<one>"
1264 "<subtree>"
1265 "<elem>element 1</elem>text<!-- comment -->"
1266 "</subtree>"
1267 "</one>"
1268 "<two/>"
1269 "</root>";
1270 const char* xmlInsideTwo = "<?xml version=\"1.0\" ?>"
1271 "<root>"
1272 "<one/>"
1273 "<two>"
1274 "<subtree>"
1275 "<elem>element 1</elem>text<!-- comment -->"
1276 "</subtree>"
1277 "</two>"
1278 "</root>";
1279 const char* xmlAfterOne = "<?xml version=\"1.0\" ?>"
1280 "<root>"
1281 "<one/>"
1282 "<subtree>"
1283 "<elem>element 1</elem>text<!-- comment -->"
1284 "</subtree>"
1285 "<two/>"
1286 "</root>";
1287 const char* xmlAfterTwo = "<?xml version=\"1.0\" ?>"
1288 "<root>"
1289 "<one/>"
1290 "<two/>"
1291 "<subtree>"
1292 "<elem>element 1</elem>text<!-- comment -->"
1293 "</subtree>"
1294 "</root>";
1295
1296 XMLDocument doc;
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001297 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001298 XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1299 XMLElement* two = doc.RootElement()->FirstChildElement("two");
1300 two->InsertFirstChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001301 XMLPrinter printer1(0, true);
1302 doc.Accept(&printer1);
1303 XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
Michael Daumlinged523282013-10-23 07:47:29 +02001304
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001305 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001306 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1307 two = doc.RootElement()->FirstChildElement("two");
1308 doc.RootElement()->InsertAfterChild(two, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001309 XMLPrinter printer2(0, true);
1310 doc.Accept(&printer2);
1311 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001312
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001313 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001314 XMLNode* one = doc.RootElement()->FirstChildElement("one");
1315 subtree = one->FirstChildElement("subtree");
1316 doc.RootElement()->InsertAfterChild(one, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001317 XMLPrinter printer3(0, true);
1318 doc.Accept(&printer3);
1319 XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001320
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001321 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001322 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1323 two = doc.RootElement()->FirstChildElement("two");
1324 doc.RootElement()->InsertEndChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001325 XMLPrinter printer4(0, true);
1326 doc.Accept(&printer4);
1327 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001328 }
1329
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001330 {
1331 const char* xml = "<svg width = \"128\" height = \"128\">"
1332 " <text> </text>"
1333 "</svg>";
1334 XMLDocument doc;
1335 doc.Parse(xml);
1336 doc.Print();
1337 }
1338
Lee Thomason92e521b2014-11-15 17:45:51 -08001339 {
1340 // Test that it doesn't crash.
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001341 const char* xml = "<?xml version=\"1.0\"?><root><sample><field0><1</field0><field1>2</field1></sample></root>";
1342 XMLDocument doc;
1343 doc.Parse(xml);
1344 doc.PrintError();
Lee Thomason92e521b2014-11-15 17:45:51 -08001345 }
1346
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001347#if 1
1348 // the question being explored is what kind of print to use:
1349 // https://github.com/leethomason/tinyxml2/issues/63
1350 {
1351 //const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
1352 const char* xml = "<element/>";
1353 XMLDocument doc;
1354 doc.Parse( xml );
1355 doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
1356 doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
1357 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
1358 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
1359 doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
1360 doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
1361
1362 doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
1363 doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
1364 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
1365 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
1366 doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
1367 doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
1368
1369 doc.Print();
1370
1371 /* The result of this test is platform, compiler, and library version dependent. :("
1372 XMLPrinter printer;
1373 doc.Print( &printer );
1374 XMLTest( "Float and double formatting.",
1375 "<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",
1376 printer.CStr(),
1377 true );
1378 */
1379 }
1380#endif
Lee Thomasonf07b9522014-10-30 13:25:12 -07001381
1382 {
1383 // Issue #184
1384 // If it doesn't assert, it passes. Caused by objects
1385 // getting created during parsing which are then
1386 // inaccessible in the memory pools.
1387 {
1388 XMLDocument doc;
1389 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1390 }
1391 {
1392 XMLDocument doc;
1393 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1394 doc.Clear();
1395 }
1396 }
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001397
1398 {
1399 // If this doesn't assert in DEBUG, all is well.
1400 tinyxml2::XMLDocument doc;
1401 tinyxml2::XMLElement *pRoot = doc.NewElement("Root");
1402 doc.DeleteNode(pRoot);
1403 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001404
Dmitry-Me8b67d742014-12-22 11:35:12 +03001405 {
1406 // Should not assert in DEBUG
1407 XMLPrinter printer;
1408 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001409
Lee Thomason6f381b72012-03-02 12:59:39 -08001410 // ----------- Performance tracking --------------
1411 {
1412#if defined( _MSC_VER )
1413 __int64 start, end, freq;
1414 QueryPerformanceFrequency( (LARGE_INTEGER*) &freq );
1415#endif
1416
Bruno Diasa2d4e6e2012-05-07 04:58:11 -03001417 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason6f381b72012-03-02 12:59:39 -08001418 fseek( fp, 0, SEEK_END );
1419 long size = ftell( fp );
1420 fseek( fp, 0, SEEK_SET );
1421
1422 char* mem = new char[size+1];
1423 fread( mem, size, 1, fp );
1424 fclose( fp );
1425 mem[size] = 0;
1426
1427#if defined( _MSC_VER )
1428 QueryPerformanceCounter( (LARGE_INTEGER*) &start );
1429#else
1430 clock_t cstart = clock();
1431#endif
1432 static const int COUNT = 10;
1433 for( int i=0; i<COUNT; ++i ) {
1434 XMLDocument doc;
1435 doc.Parse( mem );
1436 }
1437#if defined( _MSC_VER )
1438 QueryPerformanceCounter( (LARGE_INTEGER*) &end );
1439#else
1440 clock_t cend = clock();
1441#endif
1442
1443 delete [] mem;
1444
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001445 static const char* note =
Lee Thomason6f381b72012-03-02 12:59:39 -08001446#ifdef DEBUG
1447 "DEBUG";
1448#else
1449 "Release";
1450#endif
1451
1452#if defined( _MSC_VER )
1453 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, 1000.0 * (double)(end-start) / ( (double)freq * (double)COUNT) );
1454#else
1455 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart)/(double)COUNT );
1456#endif
1457 }
1458
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -08001459 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001460 _CrtMemCheckpoint( &endMemState );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001461
1462 _CrtMemState diffMemState;
1463 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
1464 _CrtMemDumpStatistics( &diffMemState );
1465 #endif
1466
1467 printf ("\nPass %d, Fail %d\n", gPass, gFail);
Lee Thomason (grinliz)db304252013-07-31 12:24:52 -07001468
1469 return gFail;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08001470}