blob: 7a3c508bfbca76f2af1f935aba251bd057b88ed4 [file] [log] [blame]
Lee Thomason5b0a6772012-11-19 13:54:42 -08001#if defined( _MSC_VER )
2 #define _CRT_SECURE_NO_WARNINGS // This test file is not intended to be secure.
3#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08004
Lee Thomason5b0a6772012-11-19 13:54:42 -08005#include "tinyxml2.h"
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -07006#include <cstdlib>
7#include <cstring>
8#include <ctime>
U-Lama\Leee13c3e62011-12-28 14:36:55 -08009
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080010#if defined( _MSC_VER )
Lee Thomasone9699e62012-07-25 12:24:23 -070011 #include <direct.h> // _mkdir
Lee Thomason1ff38e02012-02-14 18:18:16 -080012 #include <crtdbg.h>
Lee Thomason6f381b72012-03-02 12:59:39 -080013 #define WIN32_LEAN_AND_MEAN
14 #include <windows.h>
Lee Thomason1ff38e02012-02-14 18:18:16 -080015 _CrtMemState startMemState;
16 _CrtMemState endMemState;
Martinsh Shaiters39ddc262013-01-15 21:53:08 +020017#elif defined(MINGW32) || defined(__MINGW32__)
18 #include <io.h> // mkdir
Lee Thomasone9699e62012-07-25 12:24:23 -070019#else
20 #include <sys/stat.h> // mkdir
Lee Thomason1ff38e02012-02-14 18:18:16 -080021#endif
Lee Thomasone9ecdab2012-02-13 18:11:20 -080022
U-Lama\Leee13c3e62011-12-28 14:36:55 -080023using namespace tinyxml2;
Lee Thomasonec5a7b42012-02-13 18:16:52 -080024int gPass = 0;
25int gFail = 0;
26
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -080027
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070028bool XMLTest (const char* testString, const char* expected, const char* found, bool echo=true, bool extraNL=false )
Lee Thomason1ff38e02012-02-14 18:18:16 -080029{
30 bool pass = !strcmp( expected, found );
31 if ( pass )
32 printf ("[pass]");
33 else
34 printf ("[fail]");
35
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070036 if ( !echo ) {
Lee Thomason1ff38e02012-02-14 18:18:16 -080037 printf (" %s\n", testString);
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070038 }
39 else {
40 if ( extraNL ) {
41 printf( " %s\n", testString );
42 printf( "%s\n", expected );
43 printf( "%s\n", found );
44 }
45 else {
46 printf (" %s [%s][%s]\n", testString, expected, found);
47 }
48 }
Lee Thomason1ff38e02012-02-14 18:18:16 -080049
50 if ( pass )
51 ++gPass;
52 else
53 ++gFail;
54 return pass;
55}
56
57
Lee Thomason21be8822012-07-15 17:27:22 -070058template< class T > bool XMLTest( const char* testString, T expected, T found, bool echo=true )
Lee Thomason1ff38e02012-02-14 18:18:16 -080059{
60 bool pass = ( expected == found );
61 if ( pass )
62 printf ("[pass]");
63 else
64 printf ("[fail]");
65
U-Stream\Lee09a11c52012-02-17 08:31:16 -080066 if ( !echo )
Lee Thomason1ff38e02012-02-14 18:18:16 -080067 printf (" %s\n", testString);
68 else
Lee Thomasonc8312792012-07-16 12:44:41 -070069 printf (" %s [%d][%d]\n", testString, static_cast<int>(expected), static_cast<int>(found) );
Lee Thomason1ff38e02012-02-14 18:18:16 -080070
71 if ( pass )
72 ++gPass;
73 else
74 ++gFail;
75 return pass;
76}
Lee Thomasonec5a7b42012-02-13 18:16:52 -080077
U-Lama\Leee13c3e62011-12-28 14:36:55 -080078
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -080079void NullLineEndings( char* p )
80{
81 while( p && *p ) {
82 if ( *p == '\n' || *p == '\r' ) {
83 *p = 0;
84 return;
85 }
86 ++p;
87 }
88}
89
90
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070091int example_1()
92{
93 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -030094 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070095
96 return doc.ErrorID();
97}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +020098/** @page Example-1 Load an XML File
99 * @dontinclude ./xmltest.cpp
100 * Basic XML file loading.
101 * The basic syntax to load an XML file from
102 * disk and check for an error. (ErrorID()
103 * will return 0 for no error.)
104 * @skip example_1()
105 * @until }
106 */
107
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700108
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700109int example_2()
110{
111 static const char* xml = "<element/>";
112 XMLDocument doc;
113 doc.Parse( xml );
114
115 return doc.ErrorID();
116}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200117/** @page Example-2 Parse an XML from char buffer
118 * @dontinclude ./xmltest.cpp
119 * Basic XML string parsing.
120 * The basic syntax to parse an XML for
121 * a char* and check for an error. (ErrorID()
122 * will return 0 for no error.)
123 * @skip example_2()
124 * @until }
125 */
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700126
127
128int example_3()
129{
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700130 static const char* xml =
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700131 "<?xml version=\"1.0\"?>"
132 "<!DOCTYPE PLAY SYSTEM \"play.dtd\">"
133 "<PLAY>"
134 "<TITLE>A Midsummer Night's Dream</TITLE>"
135 "</PLAY>";
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700136
137 XMLDocument doc;
138 doc.Parse( xml );
139
140 XMLElement* titleElement = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" );
141 const char* title = titleElement->GetText();
142 printf( "Name of play (1): %s\n", title );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700143
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700144 XMLText* textNode = titleElement->FirstChild()->ToText();
145 title = textNode->Value();
146 printf( "Name of play (2): %s\n", title );
147
148 return doc.ErrorID();
149}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200150/** @page Example-3 Get information out of XML
151 @dontinclude ./xmltest.cpp
152 In this example, we navigate a simple XML
153 file, and read some interesting text. Note
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700154 that this example doesn't use error
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200155 checking; working code should check for null
156 pointers when walking an XML tree, or use
157 XMLHandle.
158
159 (The XML is an excerpt from "dream.xml").
160
161 @skip example_3()
162 @until </PLAY>";
163
164 The structure of the XML file is:
165
166 <ul>
167 <li>(declaration)</li>
168 <li>(dtd stuff)</li>
169 <li>Element "PLAY"</li>
170 <ul>
171 <li>Element "TITLE"</li>
172 <ul>
173 <li>Text "A Midsummer Night's Dream"</li>
174 </ul>
175 </ul>
176 </ul>
177
178 For this example, we want to print out the
179 title of the play. The text of the title (what
180 we want) is child of the "TITLE" element which
181 is a child of the "PLAY" element.
182
183 We want to skip the declaration and dtd, so the
184 method FirstChildElement() is a good choice. The
185 FirstChildElement() of the Document is the "PLAY"
186 Element, the FirstChildElement() of the "PLAY" Element
187 is the "TITLE" Element.
188
189 @until ( "TITLE" );
190
191 We can then use the convenience function GetText()
192 to get the title of the play.
193
194 @until title );
195
196 Text is just another Node in the XML DOM. And in
197 fact you should be a little cautious with it, as
198 text nodes can contain elements.
199
200 @verbatim
201 Consider: A Midsummer Night's <b>Dream</b>
202 @endverbatim
203
204 It is more correct to actually query the Text Node
205 if in doubt:
206
207 @until title );
208
209 Noting that here we use FirstChild() since we are
210 looking for XMLText, not an element, and ToText()
211 is a cast from a Node to a XMLText.
212*/
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700213
214
Lee Thomason21be8822012-07-15 17:27:22 -0700215bool example_4()
216{
217 static const char* xml =
218 "<information>"
219 " <attributeApproach v='2' />"
220 " <textApproach>"
221 " <v>2</v>"
222 " </textApproach>"
223 "</information>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700224
Lee Thomason21be8822012-07-15 17:27:22 -0700225 XMLDocument doc;
226 doc.Parse( xml );
227
228 int v0 = 0;
229 int v1 = 0;
230
231 XMLElement* attributeApproachElement = doc.FirstChildElement()->FirstChildElement( "attributeApproach" );
232 attributeApproachElement->QueryIntAttribute( "v", &v0 );
233
234 XMLElement* textApproachElement = doc.FirstChildElement()->FirstChildElement( "textApproach" );
235 textApproachElement->FirstChildElement( "v" )->QueryIntText( &v1 );
236
237 printf( "Both values are the same: %d and %d\n", v0, v1 );
238
239 return !doc.Error() && ( v0 == v1 );
240}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200241/** @page Example-4 Read attributes and text information.
242 @dontinclude ./xmltest.cpp
243
244 There are fundamentally 2 ways of writing a key-value
245 pair into an XML file. (Something that's always annoyed
246 me about XML.) Either by using attributes, or by writing
247 the key name into an element and the value into
248 the text node wrapped by the element. Both approaches
249 are illustrated in this example, which shows two ways
250 to encode the value "2" into the key "v":
251
252 @skip example_4()
253 @until "</information>";
254
255 TinyXML-2 has accessors for both approaches.
256
257 When using an attribute, you navigate to the XMLElement
258 with that attribute and use the QueryIntAttribute()
259 group of methods. (Also QueryFloatAttribute(), etc.)
260
261 @skip XMLElement* attributeApproachElement
262 @until &v0 );
263
264 When using the text approach, you need to navigate
265 down one more step to the XMLElement that contains
266 the text. Note the extra FirstChildElement( "v" )
267 in the code below. The value of the text can then
268 be safely queried with the QueryIntText() group
269 of methods. (Also QueryFloatText(), etc.)
270
271 @skip XMLElement* textApproachElement
272 @until &v1 );
273*/
Lee Thomason21be8822012-07-15 17:27:22 -0700274
275
Lee Thomason178e4cc2013-01-25 16:19:05 -0800276int main( int argc, const char ** argv )
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800277{
Lee Thomason (grinliz)0a4df402012-02-27 20:50:52 -0800278 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason1ff38e02012-02-14 18:18:16 -0800279 _CrtMemCheckpoint( &startMemState );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700280 #endif
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800281
Martinsh Shaiters39ddc262013-01-15 21:53:08 +0200282 #if defined(_MSC_VER) || defined(MINGW32) || defined(__MINGW32__)
ddiproiettoa8ae1f62013-05-05 18:42:52 +0300283 #if defined __MINGW64_VERSION_MAJOR && defined __MINGW64_VERSION_MINOR
284 //MINGW64: both 32 and 64-bit
285 mkdir( "resources/out/" );
286 #else
287 _mkdir( "resources/out/" );
288 #endif
Lee Thomasone9699e62012-07-25 12:24:23 -0700289 #else
290 mkdir( "resources/out/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
291 #endif
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400292
Lee Thomason178e4cc2013-01-25 16:19:05 -0800293 if ( argc > 1 ) {
294 XMLDocument* doc = new XMLDocument();
295 clock_t startTime = clock();
296 doc->LoadFile( argv[1] );
297 clock_t loadTime = clock();
298 int errorID = doc->ErrorID();
299 delete doc; doc = 0;
300 clock_t deleteTime = clock();
301
302 printf( "Test file '%s' loaded. ErrorID=%d\n", argv[1], errorID );
303 if ( !errorID ) {
304 printf( "Load time=%d\n", loadTime - startTime );
305 printf( "Delete time=%d\n", deleteTime - loadTime );
Lee Thomason (grinliz)ac83b4e2013-02-01 09:02:34 -0800306 printf( "Total time=%d\n", deleteTime - startTime );
Lee Thomason178e4cc2013-01-25 16:19:05 -0800307 }
308 exit(0);
309 }
310
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300311 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason7f7b1622012-03-24 12:49:03 -0700312 if ( !fp ) {
313 printf( "Error opening test file 'dream.xml'.\n"
314 "Is your working directory the same as where \n"
315 "the xmltest.cpp and dream.xml file are?\n\n"
316 #if defined( _MSC_VER )
317 "In windows Visual Studio you may need to set\n"
318 "Properties->Debugging->Working Directory to '..'\n"
319 #endif
320 );
321 exit( 1 );
322 }
323 fclose( fp );
324
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700325 XMLTest( "Example-1", 0, example_1() );
326 XMLTest( "Example-2", 0, example_2() );
327 XMLTest( "Example-3", 0, example_3() );
Lee Thomason21be8822012-07-15 17:27:22 -0700328 XMLTest( "Example-4", true, example_4() );
Lee Thomason87e475a2012-03-20 11:55:29 -0700329
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700330 /* ------ Example 2: Lookup information. ---- */
Lee Thomason87e475a2012-03-20 11:55:29 -0700331
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800332 {
Lee Thomason43f59302012-02-06 18:18:11 -0800333 static const char* test[] = { "<element />",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400334 "<element></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800335 "<element><subelement/></element>",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400336 "<element><subelement></subelement></element>",
337 "<element><subelement><subsub/></subelement></element>",
338 "<!--comment beside elements--><element><subelement></subelement></element>",
339 "<!--comment beside elements, this time with spaces--> \n <element> <subelement> \n </subelement> </element>",
340 "<element attrib1='foo' attrib2=\"bar\" ></element>",
341 "<element attrib1='foo' attrib2=\"bar\" ><subelement attrib3='yeehaa' /></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800342 "<element>Text inside element.</element>",
343 "<element><b></b></element>",
344 "<element>Text inside and <b>bolded</b> in the element.</element>",
345 "<outer><element>Text inside and <b>bolded</b> in the element.</element></outer>",
Lee Thomason8ee79892012-01-25 17:44:30 -0800346 "<element>This &amp; That.</element>",
Lee Thomason18d68bd2012-01-26 18:17:26 -0800347 "<element attrib='This&lt;That' />",
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800348 0
349 };
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800350 for( int i=0; test[i]; ++i ) {
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800351 XMLDocument doc;
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800352 doc.Parse( test[i] );
Lee Thomason5cae8972012-01-24 18:03:07 -0800353 doc.Print();
Lee Thomasonec975ce2012-01-23 11:42:06 -0800354 printf( "----------------------------------------------\n" );
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800355 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800356 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800357#if 1
Lee Thomasond6277762012-02-22 16:00:12 -0800358 {
359 static const char* test = "<!--hello world\n"
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400360 " line 2\r"
361 " line 3\r\n"
362 " line 4\n\r"
363 " line 5\r-->";
Lee Thomasond6277762012-02-22 16:00:12 -0800364
365 XMLDocument doc;
366 doc.Parse( test );
367 doc.Print();
368 }
369
Lee Thomason2c85a712012-01-31 08:24:24 -0800370 {
371 static const char* test = "<element>Text before.</element>";
372 XMLDocument doc;
373 doc.Parse( test );
374 XMLElement* root = doc.FirstChildElement();
375 XMLElement* newElement = doc.NewElement( "Subelement" );
376 root->InsertEndChild( newElement );
377 doc.Print();
378 }
Lee Thomasond1983222012-02-06 08:41:24 -0800379 {
380 XMLDocument* doc = new XMLDocument();
381 static const char* test = "<element><sub/></element>";
382 doc->Parse( test );
383 delete doc;
384 }
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800385 {
Lee Thomason1ff38e02012-02-14 18:18:16 -0800386 // Test: Programmatic DOM
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800387 // Build:
388 // <element>
389 // <!--comment-->
390 // <sub attrib="1" />
391 // <sub attrib="2" />
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800392 // <sub attrib="3" >& Text!</sub>
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800393 // <element>
394
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800395 XMLDocument* doc = new XMLDocument();
Lee Thomason1ff38e02012-02-14 18:18:16 -0800396 XMLNode* element = doc->InsertEndChild( doc->NewElement( "element" ) );
397
398 XMLElement* sub[3] = { doc->NewElement( "sub" ), doc->NewElement( "sub" ), doc->NewElement( "sub" ) };
399 for( int i=0; i<3; ++i ) {
400 sub[i]->SetAttribute( "attrib", i );
401 }
402 element->InsertEndChild( sub[2] );
403 XMLNode* comment = element->InsertFirstChild( doc->NewComment( "comment" ) );
404 element->InsertAfterChild( comment, sub[0] );
405 element->InsertAfterChild( sub[0], sub[1] );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800406 sub[2]->InsertFirstChild( doc->NewText( "& Text!" ));
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800407 doc->Print();
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800408 XMLTest( "Programmatic DOM", "comment", doc->FirstChildElement( "element" )->FirstChild()->Value() );
409 XMLTest( "Programmatic DOM", "0", doc->FirstChildElement( "element" )->FirstChildElement()->Attribute( "attrib" ) );
410 XMLTest( "Programmatic DOM", 2, doc->FirstChildElement()->LastChildElement( "sub" )->IntAttribute( "attrib" ) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700411 XMLTest( "Programmatic DOM", "& Text!",
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800412 doc->FirstChildElement()->LastChildElement( "sub" )->FirstChild()->ToText()->Value() );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800413
414 // And now deletion:
415 element->DeleteChild( sub[2] );
416 doc->DeleteNode( comment );
417
418 element->FirstChildElement()->SetAttribute( "attrib", true );
419 element->LastChildElement()->DeleteAttribute( "attrib" );
420
421 XMLTest( "Programmatic DOM", true, doc->FirstChildElement()->FirstChildElement()->BoolAttribute( "attrib" ) );
422 int value = 10;
423 int result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value );
Lee Thomason21be8822012-07-15 17:27:22 -0700424 XMLTest( "Programmatic DOM", result, (int)XML_NO_ATTRIBUTE );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800425 XMLTest( "Programmatic DOM", value, 10 );
426
427 doc->Print();
428
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700429 {
430 XMLPrinter streamer;
431 doc->Print( &streamer );
432 printf( "%s", streamer.CStr() );
433 }
434 {
435 XMLPrinter streamer( 0, true );
436 doc->Print( &streamer );
437 XMLTest( "Compact mode", "<element><sub attrib=\"1\"/><sub/></element>", streamer.CStr(), false );
438 }
Lee Thomason (grinliz)6b8b0122012-09-08 21:21:00 -0700439 doc->SaveFile( "./resources/out/pretty.xml" );
440 doc->SaveFile( "./resources/out/compact.xml", true );
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800441 delete doc;
442 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800443 {
444 // Test: Dream
445 // XML1 : 1,187,569 bytes in 31,209 allocations
446 // XML2 : 469,073 bytes in 323 allocations
447 //int newStart = gNew;
448 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300449 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800450
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400451 doc.SaveFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800452 doc.PrintError();
453
454 XMLTest( "Dream", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400455 doc.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800456 XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false );
457 XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
458 doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
459 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400460 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800461 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400462 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800463
464 XMLDocument doc2;
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400465 doc2.LoadFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800466 XMLTest( "Dream-out", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400467 doc2.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800468 XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false );
469 XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
470 doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
471 XMLTest( "Dream-out", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400472 doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800473
474 //gNewTotal = gNew - newStart;
475 }
Lee Thomason6f381b72012-03-02 12:59:39 -0800476
477
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800478 {
479 const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
480 "<passages count=\"006\" formatversion=\"20020620\">\n"
481 " <wrong error>\n"
482 "</passages>";
483
484 XMLDocument doc;
485 doc.Parse( error );
Lee Thomason2fa81722012-11-09 12:37:46 -0800486 XMLTest( "Bad XML", doc.ErrorID(), XML_ERROR_PARSING_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800487 }
488
489 {
490 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
491
492 XMLDocument doc;
493 doc.Parse( str );
494
495 XMLElement* ele = doc.FirstChildElement();
496
497 int iVal, result;
498 double dVal;
499
500 result = ele->QueryDoubleAttribute( "attr0", &dVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700501 XMLTest( "Query attribute: int as double", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800502 XMLTest( "Query attribute: int as double", (int)dVal, 1 );
503 result = ele->QueryDoubleAttribute( "attr1", &dVal );
504 XMLTest( "Query attribute: double as double", (int)dVal, 2 );
505 result = ele->QueryIntAttribute( "attr1", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700506 XMLTest( "Query attribute: double as int", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800507 XMLTest( "Query attribute: double as int", iVal, 2 );
508 result = ele->QueryIntAttribute( "attr2", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700509 XMLTest( "Query attribute: not a number", result, (int)XML_WRONG_ATTRIBUTE_TYPE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800510 result = ele->QueryIntAttribute( "bar", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700511 XMLTest( "Query attribute: does not exist", result, (int)XML_NO_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800512 }
513
514 {
515 const char* str = "<doc/>";
516
517 XMLDocument doc;
518 doc.Parse( str );
519
520 XMLElement* ele = doc.FirstChildElement();
521
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800522 int iVal, iVal2;
523 double dVal, dVal2;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800524
525 ele->SetAttribute( "str", "strValue" );
526 ele->SetAttribute( "int", 1 );
527 ele->SetAttribute( "double", -1.0 );
528
529 const char* cStr = ele->Attribute( "str" );
530 ele->QueryIntAttribute( "int", &iVal );
531 ele->QueryDoubleAttribute( "double", &dVal );
532
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800533 ele->QueryAttribute( "int", &iVal2 );
534 ele->QueryAttribute( "double", &dVal2 );
535
Lee Thomason8ba7f7d2012-03-24 13:04:04 -0700536 XMLTest( "Attribute match test", ele->Attribute( "str", "strValue" ), "strValue" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800537 XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
538 XMLTest( "Attribute round trip. int.", 1, iVal );
539 XMLTest( "Attribute round trip. double.", -1, (int)dVal );
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800540 XMLTest( "Alternate query", true, iVal == iVal2 );
541 XMLTest( "Alternate query", true, dVal == dVal2 );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800542 }
543
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800544 {
545 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300546 doc.LoadFile( "resources/utf8test.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800547
548 // Get the attribute "value" from the "Russian" element and check it.
549 XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700550 const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800551 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
552
553 XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
554
555 const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U,
556 0xd1U, 0x81U, 0xd1U, 0x81U,
557 0xd0U, 0xbaU, 0xd0U, 0xb8U,
558 0xd0U, 0xb9U, 0 };
559 const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
560
561 XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
562 XMLTest( "UTF-8: Browsing russian element name.",
563 russianText,
564 text->Value() );
565
566 // Now try for a round trip.
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400567 doc.SaveFile( "resources/out/utf8testout.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800568
569 // Check the round trip.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800570 int okay = 0;
571
Thomas Roßa6dd8c62012-07-26 20:42:18 +0200572 FILE* saved = fopen( "resources/out/utf8testout.xml", "r" );
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300573 FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800574
575 if ( saved && verify )
576 {
577 okay = 1;
PKEuSc28ba3a2012-07-16 03:08:47 -0700578 char verifyBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800579 while ( fgets( verifyBuf, 256, verify ) )
580 {
PKEuSc28ba3a2012-07-16 03:08:47 -0700581 char savedBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800582 fgets( savedBuf, 256, saved );
583 NullLineEndings( verifyBuf );
584 NullLineEndings( savedBuf );
585
586 if ( strcmp( verifyBuf, savedBuf ) )
587 {
588 printf( "verify:%s<\n", verifyBuf );
589 printf( "saved :%s<\n", savedBuf );
590 okay = 0;
591 break;
592 }
593 }
594 }
595 if ( saved )
596 fclose( saved );
597 if ( verify )
598 fclose( verify );
599 XMLTest( "UTF-8: Verified multi-language round trip.", 1, okay );
600 }
601
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800602 // --------GetText()-----------
603 {
604 const char* str = "<foo>This is text</foo>";
605 XMLDocument doc;
606 doc.Parse( str );
607 const XMLElement* element = doc.RootElement();
608
609 XMLTest( "GetText() normal use.", "This is text", element->GetText() );
610
611 str = "<foo><b>This is text</b></foo>";
612 doc.Parse( str );
613 element = doc.RootElement();
614
615 XMLTest( "GetText() contained element.", element->GetText() == 0, true );
616 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800617
Lee Thomasond6277762012-02-22 16:00:12 -0800618
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800619 // ---------- CDATA ---------------
620 {
621 const char* str = "<xmlElement>"
622 "<![CDATA["
623 "I am > the rules!\n"
624 "...since I make symbolic puns"
625 "]]>"
626 "</xmlElement>";
627 XMLDocument doc;
628 doc.Parse( str );
629 doc.Print();
Lee Thomasond6277762012-02-22 16:00:12 -0800630
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700631 XMLTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800632 "I am > the rules!\n...since I make symbolic puns",
Lee Thomasond6277762012-02-22 16:00:12 -0800633 false );
634 }
635
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800636 // ----------- CDATA -------------
637 {
638 const char* str = "<xmlElement>"
639 "<![CDATA["
640 "<b>I am > the rules!</b>\n"
641 "...since I make symbolic puns"
642 "]]>"
643 "</xmlElement>";
644 XMLDocument doc;
645 doc.Parse( str );
646 doc.Print();
647
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700648 XMLTest( "CDATA parse. [ tixml1:1480107 ]", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800649 "<b>I am > the rules!</b>\n...since I make symbolic puns",
650 false );
651 }
652
653 // InsertAfterChild causes crash.
654 {
655 // InsertBeforeChild and InsertAfterChild causes crash.
656 XMLDocument doc;
657 XMLElement* parent = doc.NewElement( "Parent" );
658 doc.InsertFirstChild( parent );
659
660 XMLElement* childText0 = doc.NewElement( "childText0" );
661 XMLElement* childText1 = doc.NewElement( "childText1" );
662
663 XMLNode* childNode0 = parent->InsertEndChild( childText0 );
664 XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
665
666 XMLTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent->LastChild() ), true );
667 }
Lee Thomasond6277762012-02-22 16:00:12 -0800668
669 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800670 // Entities not being written correctly.
671 // From Lynn Allen
Lee Thomasond6277762012-02-22 16:00:12 -0800672
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800673 const char* passages =
674 "<?xml version=\"1.0\" standalone=\"no\" ?>"
675 "<passages count=\"006\" formatversion=\"20020620\">"
676 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
677 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
678 "</passages>";
Lee Thomasond6277762012-02-22 16:00:12 -0800679
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800680 XMLDocument doc;
681 doc.Parse( passages );
682 XMLElement* psg = doc.RootElement()->FirstChildElement();
683 const char* context = psg->Attribute( "context" );
684 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 -0800685
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800686 XMLTest( "Entity transformation: read. ", expected, context, true );
Lee Thomasond6277762012-02-22 16:00:12 -0800687
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400688 FILE* textfile = fopen( "resources/out/textfile.txt", "w" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800689 if ( textfile )
690 {
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800691 XMLPrinter streamer( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800692 psg->Accept( &streamer );
693 fclose( textfile );
694 }
Thomas Roß0922b732012-09-23 16:31:22 +0200695
696 textfile = fopen( "resources/out/textfile.txt", "r" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800697 TIXMLASSERT( textfile );
698 if ( textfile )
699 {
700 char buf[ 1024 ];
701 fgets( buf, 1024, textfile );
702 XMLTest( "Entity transformation: write. ",
703 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
704 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
705 buf, false );
PKEuSc28ba3a2012-07-16 03:08:47 -0700706 fclose( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800707 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800708 }
709
710 {
Lee Thomason6f381b72012-03-02 12:59:39 -0800711 // Suppress entities.
712 const char* passages =
713 "<?xml version=\"1.0\" standalone=\"no\" ?>"
714 "<passages count=\"006\" formatversion=\"20020620\">"
715 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
716 "</passages>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700717
Lee Thomason6f381b72012-03-02 12:59:39 -0800718 XMLDocument doc( false );
719 doc.Parse( passages );
720
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700721 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ),
Lee Thomason6f381b72012-03-02 12:59:39 -0800722 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;." );
723 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value(),
724 "Crazy &ttk;" );
725 doc.Print();
726 }
727
728 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400729 const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800730
731 XMLDocument doc;
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400732 doc.Parse( test );
733 XMLTest( "dot in names", doc.Error(), false );
734 XMLTest( "dot in names", doc.FirstChildElement()->Name(), "a.elem" );
735 XMLTest( "dot in names", doc.FirstChildElement()->Attribute( "xmi.version" ), "2.0" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800736 }
737
738 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400739 const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800740
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400741 XMLDocument doc;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800742 doc.Parse( test );
743
744 XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
745 XMLTest( "Entity with one digit.",
746 text->Value(), "1.1 Start easy ignore fin thickness\n",
747 false );
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400748 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800749
750 {
751 // DOCTYPE not preserved (950171)
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700752 //
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800753 const char* doctype =
754 "<?xml version=\"1.0\" ?>"
755 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
756 "<!ELEMENT title (#PCDATA)>"
757 "<!ELEMENT books (title,authors)>"
758 "<element />";
759
760 XMLDocument doc;
761 doc.Parse( doctype );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400762 doc.SaveFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800763 doc.DeleteChild( doc.RootElement() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400764 doc.LoadFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800765 doc.Print();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700766
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800767 const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
768 XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
769
770 }
771
772 {
773 // Comments do not stream out correctly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700774 const char* doctype =
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800775 "<!-- Somewhat<evil> -->";
776 XMLDocument doc;
777 doc.Parse( doctype );
778
779 XMLComment* comment = doc.FirstChild()->ToComment();
780
781 XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
782 }
783 {
784 // Double attributes
785 const char* doctype = "<element attr='red' attr='blue' />";
786
787 XMLDocument doc;
788 doc.Parse( doctype );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700789
Lee Thomason2fa81722012-11-09 12:37:46 -0800790 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 -0800791 doc.PrintError();
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800792 }
793
794 {
795 // Embedded null in stream.
796 const char* doctype = "<element att\0r='red' attr='blue' />";
797
798 XMLDocument doc;
799 doc.Parse( doctype );
800 XMLTest( "Embedded null throws error.", true, doc.Error() );
801 }
802
803 {
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700804 // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800805 const char* str = " ";
806 XMLDocument doc;
807 doc.Parse( str );
Lee Thomason2fa81722012-11-09 12:37:46 -0800808 XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800809 }
810
811 {
812 // Low entities
813 XMLDocument doc;
814 doc.Parse( "<test>&#x0e;</test>" );
815 const char result[] = { 0x0e, 0 };
816 XMLTest( "Low entities.", doc.FirstChildElement()->GetText(), result );
817 doc.Print();
818 }
819
820 {
821 // Attribute values with trailing quotes not handled correctly
822 XMLDocument doc;
823 doc.Parse( "<foo attribute=bar\" />" );
824 XMLTest( "Throw error with bad end quotes.", doc.Error(), true );
825 }
826
827 {
828 // [ 1663758 ] Failure to report error on bad XML
829 XMLDocument xml;
830 xml.Parse("<x>");
831 XMLTest("Missing end tag at end of input", xml.Error(), true);
832 xml.Parse("<x> ");
833 XMLTest("Missing end tag with trailing whitespace", xml.Error(), true);
834 xml.Parse("<x></y>");
Lee Thomason2fa81722012-11-09 12:37:46 -0800835 XMLTest("Mismatched tags", xml.ErrorID(), XML_ERROR_MISMATCHED_ELEMENT);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700836 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800837
838
839 {
840 // [ 1475201 ] TinyXML parses entities in comments
841 XMLDocument xml;
842 xml.Parse("<!-- declarations for <head> & <body> -->"
843 "<!-- far &amp; away -->" );
844
845 XMLNode* e0 = xml.FirstChild();
846 XMLNode* e1 = e0->NextSibling();
847 XMLComment* c0 = e0->ToComment();
848 XMLComment* c1 = e1->ToComment();
849
850 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
851 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
852 }
853
854 {
855 XMLDocument xml;
856 xml.Parse( "<Parent>"
857 "<child1 att=''/>"
858 "<!-- With this comment, child2 will not be parsed! -->"
859 "<child2 att=''/>"
860 "</Parent>" );
861 xml.Print();
862
863 int count = 0;
864
865 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
866 ele;
867 ele = ele->NextSibling() )
868 {
869 ++count;
870 }
871
872 XMLTest( "Comments iterate correctly.", 3, count );
873 }
874
875 {
876 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
877 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
878 buf[60] = 239;
879 buf[61] = 0;
880
881 XMLDocument doc;
882 doc.Parse( (const char*)buf);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700883 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800884
885
886 {
887 // bug 1827248 Error while parsing a little bit malformed file
888 // Actually not malformed - should work.
889 XMLDocument xml;
890 xml.Parse( "<attributelist> </attributelist >" );
891 XMLTest( "Handle end tag whitespace", false, xml.Error() );
892 }
893
894 {
895 // This one must not result in an infinite loop
896 XMLDocument xml;
897 xml.Parse( "<infinite>loop" );
898 XMLTest( "Infinite loop test.", true, true );
899 }
900#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800901 {
902 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
903 XMLDocument doc;
904 doc.Parse( pub );
905
906 XMLDocument clone;
907 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
908 XMLNode* copy = node->ShallowClone( &clone );
909 clone.InsertEndChild( copy );
910 }
911
912 clone.Print();
913
914 int count=0;
915 const XMLNode* a=clone.FirstChild();
916 const XMLNode* b=doc.FirstChild();
917 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
918 ++count;
919 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
920 }
921 XMLTest( "Clone and Equal", 4, count );
922 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800923
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700924 {
925 // This shouldn't crash.
926 XMLDocument doc;
927 if(XML_NO_ERROR != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
928 {
929 doc.PrintError();
930 }
931 XMLTest( "Error in snprinf handling.", true, doc.Error() );
932 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700933
Lee Thomason5e3803c2012-04-16 08:57:05 -0700934 {
935 // Attribute ordering.
936 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
937 XMLDocument doc;
938 doc.Parse( xml );
939 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700940
Lee Thomason5e3803c2012-04-16 08:57:05 -0700941 const XMLAttribute* a = ele->FirstAttribute();
942 XMLTest( "Attribute order", "1", a->Value() );
943 a = a->Next();
944 XMLTest( "Attribute order", "2", a->Value() );
945 a = a->Next();
946 XMLTest( "Attribute order", "3", a->Value() );
947 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700948
Lee Thomason5e3803c2012-04-16 08:57:05 -0700949 ele->DeleteAttribute( "attrib2" );
950 a = ele->FirstAttribute();
951 XMLTest( "Attribute order", "1", a->Value() );
952 a = a->Next();
953 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700954
Lee Thomason5e3803c2012-04-16 08:57:05 -0700955 ele->DeleteAttribute( "attrib1" );
956 ele->DeleteAttribute( "attrib3" );
957 XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
958 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700959
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -0700960 {
961 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -0700962 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
963 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
964 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
965 XMLDocument doc0;
966 doc0.Parse( xml0 );
967 XMLDocument doc1;
968 doc1.Parse( xml1 );
969 XMLDocument doc2;
970 doc2.Parse( xml2 );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -0700971
Lee Thomason78a773d2012-07-02 10:10:19 -0700972 XMLElement* ele = 0;
973 ele = doc0.FirstChildElement();
974 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
975 ele = doc1.FirstChildElement();
976 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
977 ele = doc2.FirstChildElement();
978 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -0700979 }
980
981 {
982 // Make sure we don't go into an infinite loop.
983 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
984 XMLDocument doc;
985 doc.Parse( xml );
986 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
987 XMLElement* ele1 = ele0->NextSiblingElement();
988 bool equal = ele0->ShallowEqual( ele1 );
989
990 XMLTest( "Infinite loop in shallow equal.", true, equal );
991 }
992
Lee Thomason5708f812012-03-28 17:46:41 -0700993 // -------- Handles ------------
994 {
995 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
996 XMLDocument doc;
997 doc.Parse( xml );
Lee Thomason5708f812012-03-28 17:46:41 -0700998
999 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
1000 XMLTest( "Handle, success, mutable", ele->Value(), "sub" );
1001
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001002 XMLHandle docH( doc );
1003 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001004 XMLTest( "Handle, dne, mutable", false, ele != 0 );
Lee Thomason5708f812012-03-28 17:46:41 -07001005 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001006
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001007 {
1008 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1009 XMLDocument doc;
1010 doc.Parse( xml );
1011 XMLConstHandle docH( doc );
1012
1013 const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
1014 XMLTest( "Handle, success, const", ele->Value(), "sub" );
1015
1016 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001017 XMLTest( "Handle, dne, const", false, ele != 0 );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001018 }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001019 {
1020 // Default Declaration & BOM
1021 XMLDocument doc;
1022 doc.InsertEndChild( doc.NewDeclaration() );
1023 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001024
Lee Thomasonf68c4382012-04-28 14:37:11 -07001025 XMLPrinter printer;
1026 doc.Print( &printer );
1027
1028 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1029 XMLTest( "BOM and default declaration", printer.CStr(), result, false );
Lee Thomason (grinliz)48ea0bc2012-05-26 14:41:14 -07001030 XMLTest( "CStrSize", printer.CStrSize(), 42, false );
Lee Thomasonf68c4382012-04-28 14:37:11 -07001031 }
Lee Thomason21be8822012-07-15 17:27:22 -07001032 {
1033 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1034 XMLDocument doc;
1035 doc.Parse( xml );
1036 XMLTest( "Ill formed XML", true, doc.Error() );
1037 }
1038
1039 // QueryXYZText
1040 {
1041 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1042 XMLDocument doc;
1043 doc.Parse( xml );
1044
1045 const XMLElement* pointElement = doc.RootElement();
1046
1047 int intValue = 0;
1048 unsigned unsignedValue = 0;
1049 float floatValue = 0;
1050 double doubleValue = 0;
1051 bool boolValue = false;
1052
1053 pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1054 pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1055 pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1056 pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1057 pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1058
1059
1060 XMLTest( "QueryIntText", intValue, 1, false );
1061 XMLTest( "QueryUnsignedText", unsignedValue, (unsigned)1, false );
1062 XMLTest( "QueryFloatText", floatValue, 1.2f, false );
1063 XMLTest( "QueryDoubleText", doubleValue, 1.2, false );
1064 XMLTest( "QueryBoolText", boolValue, true, false );
1065 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001066
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001067 {
1068 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1069 XMLDocument doc;
1070 doc.Parse( xml );
1071 XMLTest( "Non-alpha element lead letter parses.", doc.Error(), false );
1072 }
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001073
1074 {
1075 const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1076 XMLDocument doc;
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001077 doc.Parse( xml );
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001078 XMLTest("Non-alpha attribute lead character parses.", doc.Error(), false);
1079 }
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001080
1081 {
1082 const char* xml = "<3lement></3lement>";
1083 XMLDocument doc;
1084 doc.Parse( xml );
1085 XMLTest("Element names with lead digit fail to parse.", doc.Error(), true);
1086 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -07001087
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001088 {
1089 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1090 XMLDocument doc;
1091 doc.Parse( xml, 10 );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001092 XMLTest( "Set length of incoming data", doc.Error(), false );
1093 }
1094
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001095 {
1096 XMLDocument doc;
1097 doc.LoadFile( "resources/dream.xml" );
1098 doc.Clear();
1099 XMLTest( "Document Clear()'s", doc.NoChildren(), true );
1100 }
1101
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001102 // ----------- Whitespace ------------
1103 {
1104 const char* xml = "<element>"
1105 "<a> This \nis &apos; text &apos; </a>"
1106 "<b> This is &apos; text &apos; \n</b>"
1107 "<c>This is &apos; \n\n text &apos;</c>"
1108 "</element>";
1109 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1110 doc.Parse( xml );
1111
1112 const XMLElement* element = doc.FirstChildElement();
1113 for( const XMLElement* parent = element->FirstChildElement();
1114 parent;
1115 parent = parent->NextSiblingElement() )
1116 {
1117 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1118 }
1119 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001120
Lee Thomasonae9ab072012-10-24 10:17:53 -07001121#if 0
1122 {
1123 // Passes if assert doesn't fire.
1124 XMLDocument xmlDoc;
1125
1126 xmlDoc.NewDeclaration();
1127 xmlDoc.NewComment("Configuration file");
1128
1129 XMLElement *root = xmlDoc.NewElement("settings");
1130 root->SetAttribute("version", 2);
1131 }
1132#endif
1133
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001134 {
1135 const char* xml = "<element> </element>";
1136 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1137 doc.Parse( xml );
1138 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1139 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001140
Lee Thomason (grinliz)fc6320e2012-09-23 20:25:50 -07001141#if 0 // the question being explored is what kind of print to use:
1142 // https://github.com/leethomason/tinyxml2/issues/63
1143 {
1144 const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9'/>";
1145 XMLDocument doc;
1146 doc.Parse( xml );
1147 doc.FirstChildElement()->SetAttribute( "attrA", 123456789.123456789 );
1148 doc.FirstChildElement()->SetAttribute( "attrB", 1.001e9 );
1149 doc.Print();
1150 }
1151#endif
1152
Lee Thomason5b0a6772012-11-19 13:54:42 -08001153 {
1154 // An assert should not fire.
1155 const char* xml = "<element/>";
1156 XMLDocument doc;
1157 doc.Parse( xml );
1158 XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope.
1159 XMLTest( "Tracking unused elements", true, ele != 0, false );
1160 }
1161
Lee Thomasona6412ac2012-12-13 15:39:11 -08001162
1163 {
1164 const char* xml = "<parent><child>abc</child></parent>";
1165 XMLDocument doc;
1166 doc.Parse( xml );
1167 XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
1168
1169 XMLPrinter printer;
1170 ele->Accept( &printer );
1171 XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1172 }
1173
1174
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001175 {
1176 XMLDocument doc;
1177 XMLError error = doc.LoadFile( "resources/empty.xml" );
1178 XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
1179 }
1180
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001181 {
1182 // BOM preservation
1183 static const char* xml_bom_preservation = "\xef\xbb\xbf<element/>\n";
1184 {
1185 XMLDocument doc;
1186 XMLTest( "BOM preservation (parse)", XML_NO_ERROR, doc.Parse( xml_bom_preservation ), false );
1187 XMLPrinter printer;
1188 doc.Print( &printer );
1189
1190 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1191 doc.SaveFile( "resources/bomtest.xml" );
1192 }
1193 {
1194 XMLDocument doc;
1195 doc.LoadFile( "resources/bomtest.xml" );
1196 XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
1197
1198 XMLPrinter printer;
1199 doc.Print( &printer );
1200 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1201 }
1202 }
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001203
Lee Thomason6f381b72012-03-02 12:59:39 -08001204 // ----------- Performance tracking --------------
1205 {
1206#if defined( _MSC_VER )
1207 __int64 start, end, freq;
1208 QueryPerformanceFrequency( (LARGE_INTEGER*) &freq );
1209#endif
1210
Bruno Diasa2d4e6e2012-05-07 04:58:11 -03001211 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason6f381b72012-03-02 12:59:39 -08001212 fseek( fp, 0, SEEK_END );
1213 long size = ftell( fp );
1214 fseek( fp, 0, SEEK_SET );
1215
1216 char* mem = new char[size+1];
1217 fread( mem, size, 1, fp );
1218 fclose( fp );
1219 mem[size] = 0;
1220
1221#if defined( _MSC_VER )
1222 QueryPerformanceCounter( (LARGE_INTEGER*) &start );
1223#else
1224 clock_t cstart = clock();
1225#endif
1226 static const int COUNT = 10;
1227 for( int i=0; i<COUNT; ++i ) {
1228 XMLDocument doc;
1229 doc.Parse( mem );
1230 }
1231#if defined( _MSC_VER )
1232 QueryPerformanceCounter( (LARGE_INTEGER*) &end );
1233#else
1234 clock_t cend = clock();
1235#endif
1236
1237 delete [] mem;
1238
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001239 static const char* note =
Lee Thomason6f381b72012-03-02 12:59:39 -08001240#ifdef DEBUG
1241 "DEBUG";
1242#else
1243 "Release";
1244#endif
1245
1246#if defined( _MSC_VER )
1247 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, 1000.0 * (double)(end-start) / ( (double)freq * (double)COUNT) );
1248#else
1249 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart)/(double)COUNT );
1250#endif
1251 }
1252
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -08001253 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001254 _CrtMemCheckpoint( &endMemState );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001255 //_CrtMemDumpStatistics( &endMemState );
1256
1257 _CrtMemState diffMemState;
1258 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
1259 _CrtMemDumpStatistics( &diffMemState );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001260 //printf( "new total=%d\n", gNewTotal );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001261 #endif
1262
1263 printf ("\nPass %d, Fail %d\n", gPass, gFail);
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001264 return 0;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08001265}