blob: 597cebbecae2be7855307ea1bc79181de9a25f79 [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
Dmitry-Me588bb8d2014-12-25 18:59:18 +0300870 const char* str = "";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800871 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 {
Dmitry-Me588bb8d2014-12-25 18:59:18 +0300877 // Documents with all whitespaces should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
878 const char* str = " ";
879 XMLDocument doc;
880 doc.Parse( str );
881 XMLTest( "All whitespaces document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
882 }
883
884 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800885 // Low entities
886 XMLDocument doc;
887 doc.Parse( "<test>&#x0e;</test>" );
888 const char result[] = { 0x0e, 0 };
889 XMLTest( "Low entities.", doc.FirstChildElement()->GetText(), result );
890 doc.Print();
891 }
892
893 {
894 // Attribute values with trailing quotes not handled correctly
895 XMLDocument doc;
896 doc.Parse( "<foo attribute=bar\" />" );
897 XMLTest( "Throw error with bad end quotes.", doc.Error(), true );
898 }
899
900 {
901 // [ 1663758 ] Failure to report error on bad XML
902 XMLDocument xml;
903 xml.Parse("<x>");
904 XMLTest("Missing end tag at end of input", xml.Error(), true);
905 xml.Parse("<x> ");
906 XMLTest("Missing end tag with trailing whitespace", xml.Error(), true);
907 xml.Parse("<x></y>");
Lee Thomason2fa81722012-11-09 12:37:46 -0800908 XMLTest("Mismatched tags", xml.ErrorID(), XML_ERROR_MISMATCHED_ELEMENT);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700909 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800910
911
912 {
913 // [ 1475201 ] TinyXML parses entities in comments
914 XMLDocument xml;
915 xml.Parse("<!-- declarations for <head> & <body> -->"
916 "<!-- far &amp; away -->" );
917
918 XMLNode* e0 = xml.FirstChild();
919 XMLNode* e1 = e0->NextSibling();
920 XMLComment* c0 = e0->ToComment();
921 XMLComment* c1 = e1->ToComment();
922
923 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
924 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
925 }
926
927 {
928 XMLDocument xml;
929 xml.Parse( "<Parent>"
930 "<child1 att=''/>"
931 "<!-- With this comment, child2 will not be parsed! -->"
932 "<child2 att=''/>"
933 "</Parent>" );
934 xml.Print();
935
936 int count = 0;
937
938 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
939 ele;
940 ele = ele->NextSibling() )
941 {
942 ++count;
943 }
944
945 XMLTest( "Comments iterate correctly.", 3, count );
946 }
947
948 {
949 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
950 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
951 buf[60] = 239;
952 buf[61] = 0;
953
954 XMLDocument doc;
955 doc.Parse( (const char*)buf);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700956 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800957
958
959 {
960 // bug 1827248 Error while parsing a little bit malformed file
961 // Actually not malformed - should work.
962 XMLDocument xml;
963 xml.Parse( "<attributelist> </attributelist >" );
964 XMLTest( "Handle end tag whitespace", false, xml.Error() );
965 }
966
967 {
968 // This one must not result in an infinite loop
969 XMLDocument xml;
970 xml.Parse( "<infinite>loop" );
971 XMLTest( "Infinite loop test.", true, true );
972 }
973#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800974 {
975 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
976 XMLDocument doc;
977 doc.Parse( pub );
978
979 XMLDocument clone;
980 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
981 XMLNode* copy = node->ShallowClone( &clone );
982 clone.InsertEndChild( copy );
983 }
984
985 clone.Print();
986
987 int count=0;
988 const XMLNode* a=clone.FirstChild();
989 const XMLNode* b=doc.FirstChild();
990 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
991 ++count;
992 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
993 }
994 XMLTest( "Clone and Equal", 4, count );
995 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800996
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700997 {
998 // This shouldn't crash.
999 XMLDocument doc;
1000 if(XML_NO_ERROR != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
1001 {
1002 doc.PrintError();
1003 }
1004 XMLTest( "Error in snprinf handling.", true, doc.Error() );
1005 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001006
Lee Thomason5e3803c2012-04-16 08:57:05 -07001007 {
1008 // Attribute ordering.
1009 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
1010 XMLDocument doc;
1011 doc.Parse( xml );
1012 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001013
Lee Thomason5e3803c2012-04-16 08:57:05 -07001014 const XMLAttribute* a = ele->FirstAttribute();
1015 XMLTest( "Attribute order", "1", a->Value() );
1016 a = a->Next();
1017 XMLTest( "Attribute order", "2", a->Value() );
1018 a = a->Next();
1019 XMLTest( "Attribute order", "3", a->Value() );
1020 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001021
Lee Thomason5e3803c2012-04-16 08:57:05 -07001022 ele->DeleteAttribute( "attrib2" );
1023 a = ele->FirstAttribute();
1024 XMLTest( "Attribute order", "1", a->Value() );
1025 a = a->Next();
1026 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001027
Lee Thomason5e3803c2012-04-16 08:57:05 -07001028 ele->DeleteAttribute( "attrib1" );
1029 ele->DeleteAttribute( "attrib3" );
1030 XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
1031 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001032
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001033 {
1034 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -07001035 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
1036 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
1037 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
1038 XMLDocument doc0;
1039 doc0.Parse( xml0 );
1040 XMLDocument doc1;
1041 doc1.Parse( xml1 );
1042 XMLDocument doc2;
1043 doc2.Parse( xml2 );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001044
Lee Thomason78a773d2012-07-02 10:10:19 -07001045 XMLElement* ele = 0;
1046 ele = doc0.FirstChildElement();
1047 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
1048 ele = doc1.FirstChildElement();
1049 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
1050 ele = doc2.FirstChildElement();
1051 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001052 }
1053
1054 {
1055 // Make sure we don't go into an infinite loop.
1056 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
1057 XMLDocument doc;
1058 doc.Parse( xml );
1059 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
1060 XMLElement* ele1 = ele0->NextSiblingElement();
1061 bool equal = ele0->ShallowEqual( ele1 );
1062
1063 XMLTest( "Infinite loop in shallow equal.", true, equal );
1064 }
1065
Lee Thomason5708f812012-03-28 17:46:41 -07001066 // -------- Handles ------------
1067 {
1068 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1069 XMLDocument doc;
1070 doc.Parse( xml );
Lee Thomason5708f812012-03-28 17:46:41 -07001071
1072 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
1073 XMLTest( "Handle, success, mutable", ele->Value(), "sub" );
1074
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001075 XMLHandle docH( doc );
1076 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001077 XMLTest( "Handle, dne, mutable", false, ele != 0 );
Lee Thomason5708f812012-03-28 17:46:41 -07001078 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001079
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001080 {
1081 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1082 XMLDocument doc;
1083 doc.Parse( xml );
1084 XMLConstHandle docH( doc );
1085
1086 const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
1087 XMLTest( "Handle, success, const", ele->Value(), "sub" );
1088
1089 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001090 XMLTest( "Handle, dne, const", false, ele != 0 );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001091 }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001092 {
1093 // Default Declaration & BOM
1094 XMLDocument doc;
1095 doc.InsertEndChild( doc.NewDeclaration() );
1096 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001097
Lee Thomasonf68c4382012-04-28 14:37:11 -07001098 XMLPrinter printer;
1099 doc.Print( &printer );
1100
1101 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1102 XMLTest( "BOM and default declaration", printer.CStr(), result, false );
Lee Thomason (grinliz)48ea0bc2012-05-26 14:41:14 -07001103 XMLTest( "CStrSize", printer.CStrSize(), 42, false );
Lee Thomasonf68c4382012-04-28 14:37:11 -07001104 }
Lee Thomason21be8822012-07-15 17:27:22 -07001105 {
1106 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1107 XMLDocument doc;
1108 doc.Parse( xml );
1109 XMLTest( "Ill formed XML", true, doc.Error() );
1110 }
1111
1112 // QueryXYZText
1113 {
1114 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1115 XMLDocument doc;
1116 doc.Parse( xml );
1117
1118 const XMLElement* pointElement = doc.RootElement();
1119
1120 int intValue = 0;
1121 unsigned unsignedValue = 0;
1122 float floatValue = 0;
1123 double doubleValue = 0;
1124 bool boolValue = false;
1125
1126 pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1127 pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1128 pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1129 pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1130 pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1131
1132
1133 XMLTest( "QueryIntText", intValue, 1, false );
1134 XMLTest( "QueryUnsignedText", unsignedValue, (unsigned)1, false );
1135 XMLTest( "QueryFloatText", floatValue, 1.2f, false );
1136 XMLTest( "QueryDoubleText", doubleValue, 1.2, false );
1137 XMLTest( "QueryBoolText", boolValue, true, false );
1138 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001139
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001140 {
1141 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1142 XMLDocument doc;
1143 doc.Parse( xml );
1144 XMLTest( "Non-alpha element lead letter parses.", doc.Error(), false );
1145 }
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001146
1147 {
1148 const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1149 XMLDocument doc;
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001150 doc.Parse( xml );
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001151 XMLTest("Non-alpha attribute lead character parses.", doc.Error(), false);
1152 }
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001153
1154 {
1155 const char* xml = "<3lement></3lement>";
1156 XMLDocument doc;
1157 doc.Parse( xml );
1158 XMLTest("Element names with lead digit fail to parse.", doc.Error(), true);
1159 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -07001160
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001161 {
1162 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1163 XMLDocument doc;
1164 doc.Parse( xml, 10 );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001165 XMLTest( "Set length of incoming data", doc.Error(), false );
1166 }
1167
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001168 {
1169 XMLDocument doc;
Dmitry-Me48b5df02015-04-06 18:20:25 +03001170 XMLTest( "Document is initially empty", doc.NoChildren(), true );
1171 doc.Clear();
1172 XMLTest( "Empty is empty after Clear()", doc.NoChildren(), true );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001173 doc.LoadFile( "resources/dream.xml" );
Dmitry-Meaaa4cea2015-02-06 16:00:46 +03001174 XMLTest( "Document has something to Clear()", doc.NoChildren(), false );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001175 doc.Clear();
1176 XMLTest( "Document Clear()'s", doc.NoChildren(), true );
1177 }
1178
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001179 // ----------- Whitespace ------------
1180 {
1181 const char* xml = "<element>"
1182 "<a> This \nis &apos; text &apos; </a>"
1183 "<b> This is &apos; text &apos; \n</b>"
1184 "<c>This is &apos; \n\n text &apos;</c>"
1185 "</element>";
1186 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1187 doc.Parse( xml );
1188
1189 const XMLElement* element = doc.FirstChildElement();
1190 for( const XMLElement* parent = element->FirstChildElement();
1191 parent;
1192 parent = parent->NextSiblingElement() )
1193 {
1194 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1195 }
1196 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001197
Lee Thomasonae9ab072012-10-24 10:17:53 -07001198#if 0
1199 {
1200 // Passes if assert doesn't fire.
1201 XMLDocument xmlDoc;
1202
1203 xmlDoc.NewDeclaration();
1204 xmlDoc.NewComment("Configuration file");
1205
1206 XMLElement *root = xmlDoc.NewElement("settings");
1207 root->SetAttribute("version", 2);
1208 }
1209#endif
1210
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001211 {
1212 const char* xml = "<element> </element>";
1213 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1214 doc.Parse( xml );
1215 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1216 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001217
Lee Thomason5b0a6772012-11-19 13:54:42 -08001218 {
1219 // An assert should not fire.
1220 const char* xml = "<element/>";
1221 XMLDocument doc;
1222 doc.Parse( xml );
1223 XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope.
1224 XMLTest( "Tracking unused elements", true, ele != 0, false );
1225 }
1226
Lee Thomasona6412ac2012-12-13 15:39:11 -08001227
1228 {
1229 const char* xml = "<parent><child>abc</child></parent>";
1230 XMLDocument doc;
1231 doc.Parse( xml );
1232 XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
1233
1234 XMLPrinter printer;
1235 ele->Accept( &printer );
1236 XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1237 }
1238
1239
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001240 {
1241 XMLDocument doc;
1242 XMLError error = doc.LoadFile( "resources/empty.xml" );
1243 XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
Lee Thomason331596e2014-09-11 14:56:43 -07001244 XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() );
Lee Thomasonc7556672014-09-14 12:39:42 -07001245 doc.PrintError();
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001246 }
1247
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001248 {
1249 // BOM preservation
1250 static const char* xml_bom_preservation = "\xef\xbb\xbf<element/>\n";
1251 {
1252 XMLDocument doc;
1253 XMLTest( "BOM preservation (parse)", XML_NO_ERROR, doc.Parse( xml_bom_preservation ), false );
1254 XMLPrinter printer;
1255 doc.Print( &printer );
1256
1257 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1258 doc.SaveFile( "resources/bomtest.xml" );
1259 }
1260 {
1261 XMLDocument doc;
1262 doc.LoadFile( "resources/bomtest.xml" );
1263 XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
1264
1265 XMLPrinter printer;
1266 doc.Print( &printer );
1267 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1268 }
1269 }
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001270
Michael Daumlinged523282013-10-23 07:47:29 +02001271 {
1272 // Insertion with Removal
1273 const char* xml = "<?xml version=\"1.0\" ?>"
1274 "<root>"
1275 "<one>"
1276 "<subtree>"
1277 "<elem>element 1</elem>text<!-- comment -->"
1278 "</subtree>"
1279 "</one>"
1280 "<two/>"
1281 "</root>";
1282 const char* xmlInsideTwo = "<?xml version=\"1.0\" ?>"
1283 "<root>"
1284 "<one/>"
1285 "<two>"
1286 "<subtree>"
1287 "<elem>element 1</elem>text<!-- comment -->"
1288 "</subtree>"
1289 "</two>"
1290 "</root>";
1291 const char* xmlAfterOne = "<?xml version=\"1.0\" ?>"
1292 "<root>"
1293 "<one/>"
1294 "<subtree>"
1295 "<elem>element 1</elem>text<!-- comment -->"
1296 "</subtree>"
1297 "<two/>"
1298 "</root>";
1299 const char* xmlAfterTwo = "<?xml version=\"1.0\" ?>"
1300 "<root>"
1301 "<one/>"
1302 "<two/>"
1303 "<subtree>"
1304 "<elem>element 1</elem>text<!-- comment -->"
1305 "</subtree>"
1306 "</root>";
1307
1308 XMLDocument doc;
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001309 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001310 XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1311 XMLElement* two = doc.RootElement()->FirstChildElement("two");
1312 two->InsertFirstChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001313 XMLPrinter printer1(0, true);
1314 doc.Accept(&printer1);
1315 XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
Michael Daumlinged523282013-10-23 07:47:29 +02001316
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001317 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001318 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1319 two = doc.RootElement()->FirstChildElement("two");
1320 doc.RootElement()->InsertAfterChild(two, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001321 XMLPrinter printer2(0, true);
1322 doc.Accept(&printer2);
1323 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001324
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001325 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001326 XMLNode* one = doc.RootElement()->FirstChildElement("one");
1327 subtree = one->FirstChildElement("subtree");
1328 doc.RootElement()->InsertAfterChild(one, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001329 XMLPrinter printer3(0, true);
1330 doc.Accept(&printer3);
1331 XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001332
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001333 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001334 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1335 two = doc.RootElement()->FirstChildElement("two");
1336 doc.RootElement()->InsertEndChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001337 XMLPrinter printer4(0, true);
1338 doc.Accept(&printer4);
1339 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001340 }
1341
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001342 {
1343 const char* xml = "<svg width = \"128\" height = \"128\">"
1344 " <text> </text>"
1345 "</svg>";
1346 XMLDocument doc;
1347 doc.Parse(xml);
1348 doc.Print();
1349 }
1350
Lee Thomason92e521b2014-11-15 17:45:51 -08001351 {
1352 // Test that it doesn't crash.
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001353 const char* xml = "<?xml version=\"1.0\"?><root><sample><field0><1</field0><field1>2</field1></sample></root>";
1354 XMLDocument doc;
1355 doc.Parse(xml);
1356 doc.PrintError();
Lee Thomason92e521b2014-11-15 17:45:51 -08001357 }
1358
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001359#if 1
1360 // the question being explored is what kind of print to use:
1361 // https://github.com/leethomason/tinyxml2/issues/63
1362 {
1363 //const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
1364 const char* xml = "<element/>";
1365 XMLDocument doc;
1366 doc.Parse( xml );
1367 doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
1368 doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
1369 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
1370 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
1371 doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
1372 doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
1373
1374 doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
1375 doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
1376 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
1377 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
1378 doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
1379 doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
1380
1381 doc.Print();
1382
1383 /* The result of this test is platform, compiler, and library version dependent. :("
1384 XMLPrinter printer;
1385 doc.Print( &printer );
1386 XMLTest( "Float and double formatting.",
1387 "<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",
1388 printer.CStr(),
1389 true );
1390 */
1391 }
1392#endif
Lee Thomasonf07b9522014-10-30 13:25:12 -07001393
1394 {
1395 // Issue #184
1396 // If it doesn't assert, it passes. Caused by objects
1397 // getting created during parsing which are then
1398 // inaccessible in the memory pools.
1399 {
1400 XMLDocument doc;
1401 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1402 }
1403 {
1404 XMLDocument doc;
1405 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1406 doc.Clear();
1407 }
1408 }
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001409
1410 {
1411 // If this doesn't assert in DEBUG, all is well.
1412 tinyxml2::XMLDocument doc;
1413 tinyxml2::XMLElement *pRoot = doc.NewElement("Root");
1414 doc.DeleteNode(pRoot);
1415 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001416
Dmitry-Me8b67d742014-12-22 11:35:12 +03001417 {
1418 // Should not assert in DEBUG
1419 XMLPrinter printer;
1420 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001421
Dmitry-Me6f51c802015-03-14 13:25:03 +03001422 {
1423 // Issue 291. Should not crash
1424 const char* xml = "&#0</a>";
1425 XMLDocument doc;
1426 doc.Parse( xml );
1427
1428 XMLPrinter printer;
1429 doc.Print( &printer );
1430 }
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001431 {
1432 // Issue 299. Can print elements that are not linked in.
1433 // Will crash if issue not fixed.
1434 XMLDocument doc;
1435 XMLElement* newElement = doc.NewElement( "printme" );
1436 XMLPrinter printer;
1437 newElement->Accept( &printer );
Dmitry-Me5daa54c2015-04-08 17:45:07 +03001438 // Delete the node to avoid possible memory leak report in debug output
1439 doc.DeleteNode( newElement );
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001440 }
Lee Thomasonf6577832015-03-26 11:18:21 -07001441 {
Ant Mitchell189198f2015-03-24 16:20:36 +00001442 // Issue 302. Clear errors from LoadFile/SaveFile
1443 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001444 XMLTest( "Issue 302. Should be no error initially", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001445 doc.SaveFile( "./no/such/path/pretty.xml" );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001446 XMLTest( "Issue 302. Fail to save", "XML_ERROR_FILE_COULD_NOT_BE_OPENED", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001447 doc.SaveFile( "./resources/out/compact.xml", true );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001448 XMLTest( "Issue 302. Subsequent success in saving", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001449 }
Dmitry-Me6f51c802015-03-14 13:25:03 +03001450
Dmitry-Med9852a52015-03-25 10:17:49 +03001451 {
1452 // If a document fails to load then subsequent
1453 // successful loads should clear the error
1454 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001455 XMLTest( "Should be no error initially", false, doc.Error() );
Dmitry-Med9852a52015-03-25 10:17:49 +03001456 doc.LoadFile( "resources/no-such-file.xml" );
1457 XMLTest( "No such file - should fail", true, doc.Error() );
1458
1459 doc.LoadFile( "resources/dream.xml" );
1460 XMLTest( "Error should be cleared", false, doc.Error() );
1461 }
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301462
1463 {
1464 // Check that declarations are parsed only as the FirstChild
1465 const char* xml0 = "<?xml version=\"1.0\" ?>"
1466 " <!-- xml version=\"1.1\" -->"
1467 "<first />";
1468 const char* xml1 = "<?xml version=\"1.0\" ?>"
1469 " <?xml version=\"1.1\" ?>"
1470 "<first />";
1471 const char* xml2 = "<first />"
1472 "<?xml version=\"1.0\" ?>";
1473 XMLDocument doc;
1474 doc.Parse(xml0);
1475 XMLTest("Test that the code changes do not affect normal parsing", doc.Error(), false);
1476 doc.Parse(xml1);
1477 XMLTest("Test that the second declaration throws an error", doc.Error(), true);
1478 doc.Parse(xml2);
1479 XMLTest("Test that declaration after a child throws an error", doc.Error(), true);
1480 }
Dmitry-Med9852a52015-03-25 10:17:49 +03001481
Lee Thomason6f381b72012-03-02 12:59:39 -08001482 // ----------- Performance tracking --------------
1483 {
1484#if defined( _MSC_VER )
1485 __int64 start, end, freq;
1486 QueryPerformanceFrequency( (LARGE_INTEGER*) &freq );
1487#endif
1488
Bruno Diasa2d4e6e2012-05-07 04:58:11 -03001489 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason6f381b72012-03-02 12:59:39 -08001490 fseek( fp, 0, SEEK_END );
1491 long size = ftell( fp );
1492 fseek( fp, 0, SEEK_SET );
1493
1494 char* mem = new char[size+1];
1495 fread( mem, size, 1, fp );
1496 fclose( fp );
1497 mem[size] = 0;
1498
1499#if defined( _MSC_VER )
1500 QueryPerformanceCounter( (LARGE_INTEGER*) &start );
1501#else
1502 clock_t cstart = clock();
1503#endif
1504 static const int COUNT = 10;
1505 for( int i=0; i<COUNT; ++i ) {
1506 XMLDocument doc;
1507 doc.Parse( mem );
1508 }
1509#if defined( _MSC_VER )
1510 QueryPerformanceCounter( (LARGE_INTEGER*) &end );
1511#else
1512 clock_t cend = clock();
1513#endif
1514
1515 delete [] mem;
1516
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001517 static const char* note =
Lee Thomason6f381b72012-03-02 12:59:39 -08001518#ifdef DEBUG
1519 "DEBUG";
1520#else
1521 "Release";
1522#endif
1523
1524#if defined( _MSC_VER )
1525 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, 1000.0 * (double)(end-start) / ( (double)freq * (double)COUNT) );
1526#else
1527 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart)/(double)COUNT );
1528#endif
1529 }
1530
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -08001531 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001532 _CrtMemCheckpoint( &endMemState );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001533
1534 _CrtMemState diffMemState;
1535 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
1536 _CrtMemDumpStatistics( &diffMemState );
1537 #endif
1538
1539 printf ("\nPass %d, Fail %d\n", gPass, gFail);
Lee Thomason (grinliz)db304252013-07-31 12:24:52 -07001540
1541 return gFail;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08001542}