blob: edd2e701f42c66ddb80b700c290b6bf2efb483df [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{
Sarat Addepalli13b2d732015-05-19 12:44:57 +053033 bool pass;
34 if ( !expected && !found )
35 pass = true;
36 else if ( !expected || !found )
37 pass = false;
38 else pass = !strcmp( expected, found );
Lee Thomason1ff38e02012-02-14 18:18:16 -080039 if ( pass )
40 printf ("[pass]");
41 else
42 printf ("[fail]");
43
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070044 if ( !echo ) {
Lee Thomason1ff38e02012-02-14 18:18:16 -080045 printf (" %s\n", testString);
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070046 }
47 else {
48 if ( extraNL ) {
49 printf( " %s\n", testString );
50 printf( "%s\n", expected );
51 printf( "%s\n", found );
52 }
53 else {
54 printf (" %s [%s][%s]\n", testString, expected, found);
55 }
56 }
Lee Thomason1ff38e02012-02-14 18:18:16 -080057
58 if ( pass )
59 ++gPass;
60 else
61 ++gFail;
62 return pass;
63}
64
65
Lee Thomason21be8822012-07-15 17:27:22 -070066template< class T > bool XMLTest( const char* testString, T expected, T found, bool echo=true )
Lee Thomason1ff38e02012-02-14 18:18:16 -080067{
68 bool pass = ( expected == found );
69 if ( pass )
70 printf ("[pass]");
71 else
72 printf ("[fail]");
73
U-Stream\Lee09a11c52012-02-17 08:31:16 -080074 if ( !echo )
Lee Thomason1ff38e02012-02-14 18:18:16 -080075 printf (" %s\n", testString);
76 else
Lee Thomasonc8312792012-07-16 12:44:41 -070077 printf (" %s [%d][%d]\n", testString, static_cast<int>(expected), static_cast<int>(found) );
Lee Thomason1ff38e02012-02-14 18:18:16 -080078
79 if ( pass )
80 ++gPass;
81 else
82 ++gFail;
83 return pass;
84}
Lee Thomasonec5a7b42012-02-13 18:16:52 -080085
U-Lama\Leee13c3e62011-12-28 14:36:55 -080086
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -080087void NullLineEndings( char* p )
88{
89 while( p && *p ) {
90 if ( *p == '\n' || *p == '\r' ) {
91 *p = 0;
92 return;
93 }
94 ++p;
95 }
96}
97
98
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070099int example_1()
100{
101 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300102 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700103
104 return doc.ErrorID();
105}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200106/** @page Example-1 Load an XML File
107 * @dontinclude ./xmltest.cpp
108 * Basic XML file loading.
109 * The basic syntax to load an XML file from
110 * disk and check for an error. (ErrorID()
111 * will return 0 for no error.)
112 * @skip example_1()
113 * @until }
114 */
115
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700116
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700117int example_2()
118{
119 static const char* xml = "<element/>";
120 XMLDocument doc;
121 doc.Parse( xml );
122
123 return doc.ErrorID();
124}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200125/** @page Example-2 Parse an XML from char buffer
126 * @dontinclude ./xmltest.cpp
127 * Basic XML string parsing.
128 * The basic syntax to parse an XML for
129 * a char* and check for an error. (ErrorID()
130 * will return 0 for no error.)
131 * @skip example_2()
132 * @until }
133 */
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700134
135
136int example_3()
137{
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700138 static const char* xml =
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700139 "<?xml version=\"1.0\"?>"
140 "<!DOCTYPE PLAY SYSTEM \"play.dtd\">"
141 "<PLAY>"
142 "<TITLE>A Midsummer Night's Dream</TITLE>"
143 "</PLAY>";
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700144
145 XMLDocument doc;
146 doc.Parse( xml );
147
148 XMLElement* titleElement = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" );
149 const char* title = titleElement->GetText();
150 printf( "Name of play (1): %s\n", title );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700151
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700152 XMLText* textNode = titleElement->FirstChild()->ToText();
153 title = textNode->Value();
154 printf( "Name of play (2): %s\n", title );
155
156 return doc.ErrorID();
157}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200158/** @page Example-3 Get information out of XML
159 @dontinclude ./xmltest.cpp
160 In this example, we navigate a simple XML
161 file, and read some interesting text. Note
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700162 that this example doesn't use error
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200163 checking; working code should check for null
164 pointers when walking an XML tree, or use
165 XMLHandle.
166
167 (The XML is an excerpt from "dream.xml").
168
169 @skip example_3()
170 @until </PLAY>";
171
172 The structure of the XML file is:
173
174 <ul>
175 <li>(declaration)</li>
176 <li>(dtd stuff)</li>
177 <li>Element "PLAY"</li>
178 <ul>
179 <li>Element "TITLE"</li>
180 <ul>
181 <li>Text "A Midsummer Night's Dream"</li>
182 </ul>
183 </ul>
184 </ul>
185
186 For this example, we want to print out the
187 title of the play. The text of the title (what
188 we want) is child of the "TITLE" element which
189 is a child of the "PLAY" element.
190
191 We want to skip the declaration and dtd, so the
192 method FirstChildElement() is a good choice. The
193 FirstChildElement() of the Document is the "PLAY"
194 Element, the FirstChildElement() of the "PLAY" Element
195 is the "TITLE" Element.
196
197 @until ( "TITLE" );
198
199 We can then use the convenience function GetText()
200 to get the title of the play.
201
202 @until title );
203
204 Text is just another Node in the XML DOM. And in
205 fact you should be a little cautious with it, as
206 text nodes can contain elements.
207
208 @verbatim
209 Consider: A Midsummer Night's <b>Dream</b>
210 @endverbatim
211
212 It is more correct to actually query the Text Node
213 if in doubt:
214
215 @until title );
216
217 Noting that here we use FirstChild() since we are
218 looking for XMLText, not an element, and ToText()
219 is a cast from a Node to a XMLText.
220*/
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700221
222
Lee Thomason21be8822012-07-15 17:27:22 -0700223bool example_4()
224{
225 static const char* xml =
226 "<information>"
227 " <attributeApproach v='2' />"
228 " <textApproach>"
229 " <v>2</v>"
230 " </textApproach>"
231 "</information>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700232
Lee Thomason21be8822012-07-15 17:27:22 -0700233 XMLDocument doc;
234 doc.Parse( xml );
235
236 int v0 = 0;
237 int v1 = 0;
238
239 XMLElement* attributeApproachElement = doc.FirstChildElement()->FirstChildElement( "attributeApproach" );
240 attributeApproachElement->QueryIntAttribute( "v", &v0 );
241
242 XMLElement* textApproachElement = doc.FirstChildElement()->FirstChildElement( "textApproach" );
243 textApproachElement->FirstChildElement( "v" )->QueryIntText( &v1 );
244
245 printf( "Both values are the same: %d and %d\n", v0, v1 );
246
247 return !doc.Error() && ( v0 == v1 );
248}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200249/** @page Example-4 Read attributes and text information.
250 @dontinclude ./xmltest.cpp
251
252 There are fundamentally 2 ways of writing a key-value
253 pair into an XML file. (Something that's always annoyed
254 me about XML.) Either by using attributes, or by writing
255 the key name into an element and the value into
256 the text node wrapped by the element. Both approaches
257 are illustrated in this example, which shows two ways
258 to encode the value "2" into the key "v":
259
260 @skip example_4()
261 @until "</information>";
262
263 TinyXML-2 has accessors for both approaches.
264
265 When using an attribute, you navigate to the XMLElement
266 with that attribute and use the QueryIntAttribute()
267 group of methods. (Also QueryFloatAttribute(), etc.)
268
269 @skip XMLElement* attributeApproachElement
270 @until &v0 );
271
272 When using the text approach, you need to navigate
273 down one more step to the XMLElement that contains
274 the text. Note the extra FirstChildElement( "v" )
275 in the code below. The value of the text can then
276 be safely queried with the QueryIntText() group
277 of methods. (Also QueryFloatText(), etc.)
278
279 @skip XMLElement* textApproachElement
280 @until &v1 );
281*/
Lee Thomason21be8822012-07-15 17:27:22 -0700282
283
Lee Thomason178e4cc2013-01-25 16:19:05 -0800284int main( int argc, const char ** argv )
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800285{
Lee Thomason (grinliz)0a4df402012-02-27 20:50:52 -0800286 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason1ff38e02012-02-14 18:18:16 -0800287 _CrtMemCheckpoint( &startMemState );
Dmitry-Me99916592014-10-23 11:37:03 +0400288 // Enable MS Visual C++ debug heap memory leaks dump on exit
289 _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700290 #endif
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800291
Martinsh Shaiters39ddc262013-01-15 21:53:08 +0200292 #if defined(_MSC_VER) || defined(MINGW32) || defined(__MINGW32__)
ddiproiettoa8ae1f62013-05-05 18:42:52 +0300293 #if defined __MINGW64_VERSION_MAJOR && defined __MINGW64_VERSION_MINOR
294 //MINGW64: both 32 and 64-bit
295 mkdir( "resources/out/" );
296 #else
297 _mkdir( "resources/out/" );
298 #endif
Lee Thomasone9699e62012-07-25 12:24:23 -0700299 #else
300 mkdir( "resources/out/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
301 #endif
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400302
Dmitry-Me4bcbf142014-12-25 19:05:18 +0300303 {
304 TIXMLASSERT( true );
305 }
306
Lee Thomason178e4cc2013-01-25 16:19:05 -0800307 if ( argc > 1 ) {
308 XMLDocument* doc = new XMLDocument();
309 clock_t startTime = clock();
310 doc->LoadFile( argv[1] );
Anton Indrawan8a0006c2014-11-20 18:27:07 +0100311 clock_t loadTime = clock();
Lee Thomason178e4cc2013-01-25 16:19:05 -0800312 int errorID = doc->ErrorID();
313 delete doc; doc = 0;
Anton Indrawan8a0006c2014-11-20 18:27:07 +0100314 clock_t deleteTime = clock();
Lee Thomason178e4cc2013-01-25 16:19:05 -0800315
316 printf( "Test file '%s' loaded. ErrorID=%d\n", argv[1], errorID );
317 if ( !errorID ) {
Lee Thomason (grinliz)d6bd7362013-05-11 20:23:13 -0700318 printf( "Load time=%u\n", (unsigned)(loadTime - startTime) );
319 printf( "Delete time=%u\n", (unsigned)(deleteTime - loadTime) );
320 printf( "Total time=%u\n", (unsigned)(deleteTime - startTime) );
Lee Thomason178e4cc2013-01-25 16:19:05 -0800321 }
322 exit(0);
323 }
324
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300325 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason7f7b1622012-03-24 12:49:03 -0700326 if ( !fp ) {
327 printf( "Error opening test file 'dream.xml'.\n"
328 "Is your working directory the same as where \n"
329 "the xmltest.cpp and dream.xml file are?\n\n"
330 #if defined( _MSC_VER )
331 "In windows Visual Studio you may need to set\n"
332 "Properties->Debugging->Working Directory to '..'\n"
333 #endif
334 );
335 exit( 1 );
336 }
337 fclose( fp );
338
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700339 XMLTest( "Example-1", 0, example_1() );
340 XMLTest( "Example-2", 0, example_2() );
341 XMLTest( "Example-3", 0, example_3() );
Lee Thomason21be8822012-07-15 17:27:22 -0700342 XMLTest( "Example-4", true, example_4() );
Lee Thomason87e475a2012-03-20 11:55:29 -0700343
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700344 /* ------ Example 2: Lookup information. ---- */
Lee Thomason87e475a2012-03-20 11:55:29 -0700345
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800346 {
Lee Thomason43f59302012-02-06 18:18:11 -0800347 static const char* test[] = { "<element />",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400348 "<element></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800349 "<element><subelement/></element>",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400350 "<element><subelement></subelement></element>",
351 "<element><subelement><subsub/></subelement></element>",
352 "<!--comment beside elements--><element><subelement></subelement></element>",
353 "<!--comment beside elements, this time with spaces--> \n <element> <subelement> \n </subelement> </element>",
354 "<element attrib1='foo' attrib2=\"bar\" ></element>",
355 "<element attrib1='foo' attrib2=\"bar\" ><subelement attrib3='yeehaa' /></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800356 "<element>Text inside element.</element>",
357 "<element><b></b></element>",
358 "<element>Text inside and <b>bolded</b> in the element.</element>",
359 "<outer><element>Text inside and <b>bolded</b> in the element.</element></outer>",
Lee Thomason8ee79892012-01-25 17:44:30 -0800360 "<element>This &amp; That.</element>",
Lee Thomason18d68bd2012-01-26 18:17:26 -0800361 "<element attrib='This&lt;That' />",
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800362 0
363 };
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800364 for( int i=0; test[i]; ++i ) {
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800365 XMLDocument doc;
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800366 doc.Parse( test[i] );
Lee Thomason5cae8972012-01-24 18:03:07 -0800367 doc.Print();
Lee Thomasonec975ce2012-01-23 11:42:06 -0800368 printf( "----------------------------------------------\n" );
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800369 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800370 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800371#if 1
Lee Thomasond6277762012-02-22 16:00:12 -0800372 {
373 static const char* test = "<!--hello world\n"
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400374 " line 2\r"
375 " line 3\r\n"
376 " line 4\n\r"
377 " line 5\r-->";
Lee Thomasond6277762012-02-22 16:00:12 -0800378
379 XMLDocument doc;
380 doc.Parse( test );
381 doc.Print();
382 }
383
Lee Thomason2c85a712012-01-31 08:24:24 -0800384 {
385 static const char* test = "<element>Text before.</element>";
386 XMLDocument doc;
387 doc.Parse( test );
388 XMLElement* root = doc.FirstChildElement();
389 XMLElement* newElement = doc.NewElement( "Subelement" );
390 root->InsertEndChild( newElement );
391 doc.Print();
392 }
Lee Thomasond1983222012-02-06 08:41:24 -0800393 {
394 XMLDocument* doc = new XMLDocument();
395 static const char* test = "<element><sub/></element>";
396 doc->Parse( test );
397 delete doc;
398 }
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800399 {
Lee Thomason1ff38e02012-02-14 18:18:16 -0800400 // Test: Programmatic DOM
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800401 // Build:
402 // <element>
403 // <!--comment-->
404 // <sub attrib="1" />
405 // <sub attrib="2" />
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800406 // <sub attrib="3" >& Text!</sub>
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800407 // <element>
408
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800409 XMLDocument* doc = new XMLDocument();
Lee Thomason1ff38e02012-02-14 18:18:16 -0800410 XMLNode* element = doc->InsertEndChild( doc->NewElement( "element" ) );
411
412 XMLElement* sub[3] = { doc->NewElement( "sub" ), doc->NewElement( "sub" ), doc->NewElement( "sub" ) };
413 for( int i=0; i<3; ++i ) {
414 sub[i]->SetAttribute( "attrib", i );
415 }
416 element->InsertEndChild( sub[2] );
417 XMLNode* comment = element->InsertFirstChild( doc->NewComment( "comment" ) );
418 element->InsertAfterChild( comment, sub[0] );
419 element->InsertAfterChild( sub[0], sub[1] );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800420 sub[2]->InsertFirstChild( doc->NewText( "& Text!" ));
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800421 doc->Print();
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800422 XMLTest( "Programmatic DOM", "comment", doc->FirstChildElement( "element" )->FirstChild()->Value() );
423 XMLTest( "Programmatic DOM", "0", doc->FirstChildElement( "element" )->FirstChildElement()->Attribute( "attrib" ) );
424 XMLTest( "Programmatic DOM", 2, doc->FirstChildElement()->LastChildElement( "sub" )->IntAttribute( "attrib" ) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700425 XMLTest( "Programmatic DOM", "& Text!",
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800426 doc->FirstChildElement()->LastChildElement( "sub" )->FirstChild()->ToText()->Value() );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800427
428 // And now deletion:
429 element->DeleteChild( sub[2] );
430 doc->DeleteNode( comment );
431
432 element->FirstChildElement()->SetAttribute( "attrib", true );
433 element->LastChildElement()->DeleteAttribute( "attrib" );
434
435 XMLTest( "Programmatic DOM", true, doc->FirstChildElement()->FirstChildElement()->BoolAttribute( "attrib" ) );
436 int value = 10;
437 int result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value );
Lee Thomason21be8822012-07-15 17:27:22 -0700438 XMLTest( "Programmatic DOM", result, (int)XML_NO_ATTRIBUTE );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800439 XMLTest( "Programmatic DOM", value, 10 );
440
441 doc->Print();
442
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700443 {
444 XMLPrinter streamer;
445 doc->Print( &streamer );
446 printf( "%s", streamer.CStr() );
447 }
448 {
449 XMLPrinter streamer( 0, true );
450 doc->Print( &streamer );
451 XMLTest( "Compact mode", "<element><sub attrib=\"1\"/><sub/></element>", streamer.CStr(), false );
452 }
Lee Thomason (grinliz)6b8b0122012-09-08 21:21:00 -0700453 doc->SaveFile( "./resources/out/pretty.xml" );
454 doc->SaveFile( "./resources/out/compact.xml", true );
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800455 delete doc;
456 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800457 {
458 // Test: Dream
459 // XML1 : 1,187,569 bytes in 31,209 allocations
460 // XML2 : 469,073 bytes in 323 allocations
461 //int newStart = gNew;
462 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300463 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800464
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400465 doc.SaveFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800466 doc.PrintError();
467
468 XMLTest( "Dream", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400469 doc.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800470 XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false );
471 XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
472 doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
473 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400474 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800475 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400476 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800477
478 XMLDocument doc2;
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400479 doc2.LoadFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800480 XMLTest( "Dream-out", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400481 doc2.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800482 XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false );
483 XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
484 doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
485 XMLTest( "Dream-out", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400486 doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800487
488 //gNewTotal = gNew - newStart;
489 }
Lee Thomason6f381b72012-03-02 12:59:39 -0800490
491
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800492 {
493 const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
494 "<passages count=\"006\" formatversion=\"20020620\">\n"
495 " <wrong error>\n"
496 "</passages>";
497
498 XMLDocument doc;
499 doc.Parse( error );
Lee Thomason2fa81722012-11-09 12:37:46 -0800500 XMLTest( "Bad XML", doc.ErrorID(), XML_ERROR_PARSING_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800501 }
502
503 {
504 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
505
506 XMLDocument doc;
507 doc.Parse( str );
508
509 XMLElement* ele = doc.FirstChildElement();
510
511 int iVal, result;
512 double dVal;
513
514 result = ele->QueryDoubleAttribute( "attr0", &dVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700515 XMLTest( "Query attribute: int as double", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800516 XMLTest( "Query attribute: int as double", (int)dVal, 1 );
517 result = ele->QueryDoubleAttribute( "attr1", &dVal );
Thomas Roßa5221862013-05-11 10:22:12 +0200518 XMLTest( "Query attribute: double as double", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800519 XMLTest( "Query attribute: double as double", (int)dVal, 2 );
520 result = ele->QueryIntAttribute( "attr1", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700521 XMLTest( "Query attribute: double as int", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800522 XMLTest( "Query attribute: double as int", iVal, 2 );
523 result = ele->QueryIntAttribute( "attr2", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700524 XMLTest( "Query attribute: not a number", result, (int)XML_WRONG_ATTRIBUTE_TYPE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800525 result = ele->QueryIntAttribute( "bar", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700526 XMLTest( "Query attribute: does not exist", result, (int)XML_NO_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800527 }
528
529 {
530 const char* str = "<doc/>";
531
532 XMLDocument doc;
533 doc.Parse( str );
534
535 XMLElement* ele = doc.FirstChildElement();
536
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800537 int iVal, iVal2;
538 double dVal, dVal2;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800539
540 ele->SetAttribute( "str", "strValue" );
541 ele->SetAttribute( "int", 1 );
542 ele->SetAttribute( "double", -1.0 );
543
544 const char* cStr = ele->Attribute( "str" );
545 ele->QueryIntAttribute( "int", &iVal );
546 ele->QueryDoubleAttribute( "double", &dVal );
547
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800548 ele->QueryAttribute( "int", &iVal2 );
549 ele->QueryAttribute( "double", &dVal2 );
550
Lee Thomason8ba7f7d2012-03-24 13:04:04 -0700551 XMLTest( "Attribute match test", ele->Attribute( "str", "strValue" ), "strValue" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800552 XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
553 XMLTest( "Attribute round trip. int.", 1, iVal );
554 XMLTest( "Attribute round trip. double.", -1, (int)dVal );
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800555 XMLTest( "Alternate query", true, iVal == iVal2 );
556 XMLTest( "Alternate query", true, dVal == dVal2 );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800557 }
558
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800559 {
560 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300561 doc.LoadFile( "resources/utf8test.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800562
563 // Get the attribute "value" from the "Russian" element and check it.
564 XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700565 const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800566 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
567
568 XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
569
570 const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U,
571 0xd1U, 0x81U, 0xd1U, 0x81U,
572 0xd0U, 0xbaU, 0xd0U, 0xb8U,
573 0xd0U, 0xb9U, 0 };
574 const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
575
576 XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
577 XMLTest( "UTF-8: Browsing russian element name.",
578 russianText,
579 text->Value() );
580
581 // Now try for a round trip.
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400582 doc.SaveFile( "resources/out/utf8testout.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800583
584 // Check the round trip.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800585 int okay = 0;
586
Thomas Roßa6dd8c62012-07-26 20:42:18 +0200587 FILE* saved = fopen( "resources/out/utf8testout.xml", "r" );
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300588 FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800589
590 if ( saved && verify )
591 {
592 okay = 1;
PKEuSc28ba3a2012-07-16 03:08:47 -0700593 char verifyBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800594 while ( fgets( verifyBuf, 256, verify ) )
595 {
PKEuSc28ba3a2012-07-16 03:08:47 -0700596 char savedBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800597 fgets( savedBuf, 256, saved );
598 NullLineEndings( verifyBuf );
599 NullLineEndings( savedBuf );
600
601 if ( strcmp( verifyBuf, savedBuf ) )
602 {
603 printf( "verify:%s<\n", verifyBuf );
604 printf( "saved :%s<\n", savedBuf );
605 okay = 0;
606 break;
607 }
608 }
609 }
610 if ( saved )
611 fclose( saved );
612 if ( verify )
613 fclose( verify );
614 XMLTest( "UTF-8: Verified multi-language round trip.", 1, okay );
615 }
616
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800617 // --------GetText()-----------
618 {
619 const char* str = "<foo>This is text</foo>";
620 XMLDocument doc;
621 doc.Parse( str );
622 const XMLElement* element = doc.RootElement();
623
624 XMLTest( "GetText() normal use.", "This is text", element->GetText() );
625
626 str = "<foo><b>This is text</b></foo>";
627 doc.Parse( str );
628 element = doc.RootElement();
629
630 XMLTest( "GetText() contained element.", element->GetText() == 0, true );
631 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800632
Lee Thomasond6277762012-02-22 16:00:12 -0800633
Uli Kusterer321072e2014-01-21 01:57:38 +0100634 // --------SetText()-----------
635 {
636 const char* str = "<foo></foo>";
637 XMLDocument doc;
638 doc.Parse( str );
639 XMLElement* element = doc.RootElement();
640
Lee Thomason9c0678a2014-01-24 10:18:27 -0800641 element->SetText("darkness.");
642 XMLTest( "SetText() normal use (open/close).", "darkness.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100643
Lee Thomason9c0678a2014-01-24 10:18:27 -0800644 element->SetText("blue flame.");
645 XMLTest( "SetText() replace.", "blue flame.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100646
647 str = "<foo/>";
648 doc.Parse( str );
649 element = doc.RootElement();
650
Lee Thomason9c0678a2014-01-24 10:18:27 -0800651 element->SetText("The driver");
652 XMLTest( "SetText() normal use. (self-closing)", "The driver", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100653
Lee Thomason9c0678a2014-01-24 10:18:27 -0800654 element->SetText("<b>horses</b>");
655 XMLTest( "SetText() replace with tag-like text.", "<b>horses</b>", element->GetText() );
656 //doc.Print();
Uli Kusterer321072e2014-01-21 01:57:38 +0100657
658 str = "<foo><bar>Text in nested element</bar></foo>";
659 doc.Parse( str );
660 element = doc.RootElement();
661
Lee Thomason9c0678a2014-01-24 10:18:27 -0800662 element->SetText("wolves");
663 XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800664
665 str = "<foo/>";
666 doc.Parse( str );
667 element = doc.RootElement();
668
669 element->SetText( "str" );
670 XMLTest( "SetText types", "str", element->GetText() );
671
672 element->SetText( 1 );
673 XMLTest( "SetText types", "1", element->GetText() );
674
675 element->SetText( 1U );
676 XMLTest( "SetText types", "1", element->GetText() );
677
678 element->SetText( true );
679 XMLTest( "SetText types", "1", element->GetText() ); // TODO: should be 'true'?
680
681 element->SetText( 1.5f );
682 XMLTest( "SetText types", "1.5", element->GetText() );
683
684 element->SetText( 1.5 );
685 XMLTest( "SetText types", "1.5", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100686 }
687
688
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800689 // ---------- CDATA ---------------
690 {
691 const char* str = "<xmlElement>"
692 "<![CDATA["
693 "I am > the rules!\n"
694 "...since I make symbolic puns"
695 "]]>"
696 "</xmlElement>";
697 XMLDocument doc;
698 doc.Parse( str );
699 doc.Print();
Lee Thomasond6277762012-02-22 16:00:12 -0800700
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700701 XMLTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800702 "I am > the rules!\n...since I make symbolic puns",
Lee Thomasond6277762012-02-22 16:00:12 -0800703 false );
704 }
705
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800706 // ----------- CDATA -------------
707 {
708 const char* str = "<xmlElement>"
709 "<![CDATA["
710 "<b>I am > the rules!</b>\n"
711 "...since I make symbolic puns"
712 "]]>"
713 "</xmlElement>";
714 XMLDocument doc;
715 doc.Parse( str );
716 doc.Print();
717
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700718 XMLTest( "CDATA parse. [ tixml1:1480107 ]", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800719 "<b>I am > the rules!</b>\n...since I make symbolic puns",
720 false );
721 }
722
723 // InsertAfterChild causes crash.
724 {
725 // InsertBeforeChild and InsertAfterChild causes crash.
726 XMLDocument doc;
727 XMLElement* parent = doc.NewElement( "Parent" );
728 doc.InsertFirstChild( parent );
729
730 XMLElement* childText0 = doc.NewElement( "childText0" );
731 XMLElement* childText1 = doc.NewElement( "childText1" );
732
733 XMLNode* childNode0 = parent->InsertEndChild( childText0 );
734 XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
735
736 XMLTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent->LastChild() ), true );
737 }
Lee Thomasond6277762012-02-22 16:00:12 -0800738
739 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800740 // Entities not being written correctly.
741 // From Lynn Allen
Lee Thomasond6277762012-02-22 16:00:12 -0800742
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800743 const char* passages =
744 "<?xml version=\"1.0\" standalone=\"no\" ?>"
745 "<passages count=\"006\" formatversion=\"20020620\">"
746 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
747 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
748 "</passages>";
Lee Thomasond6277762012-02-22 16:00:12 -0800749
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800750 XMLDocument doc;
751 doc.Parse( passages );
752 XMLElement* psg = doc.RootElement()->FirstChildElement();
753 const char* context = psg->Attribute( "context" );
754 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 -0800755
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800756 XMLTest( "Entity transformation: read. ", expected, context, true );
Lee Thomasond6277762012-02-22 16:00:12 -0800757
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400758 FILE* textfile = fopen( "resources/out/textfile.txt", "w" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800759 if ( textfile )
760 {
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800761 XMLPrinter streamer( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800762 psg->Accept( &streamer );
763 fclose( textfile );
764 }
Thomas Roß0922b732012-09-23 16:31:22 +0200765
766 textfile = fopen( "resources/out/textfile.txt", "r" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800767 TIXMLASSERT( textfile );
768 if ( textfile )
769 {
770 char buf[ 1024 ];
771 fgets( buf, 1024, textfile );
772 XMLTest( "Entity transformation: write. ",
773 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
774 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
775 buf, false );
PKEuSc28ba3a2012-07-16 03:08:47 -0700776 fclose( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800777 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800778 }
779
780 {
Lee Thomason6f381b72012-03-02 12:59:39 -0800781 // Suppress entities.
782 const char* passages =
783 "<?xml version=\"1.0\" standalone=\"no\" ?>"
784 "<passages count=\"006\" formatversion=\"20020620\">"
785 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
786 "</passages>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700787
Lee Thomason6f381b72012-03-02 12:59:39 -0800788 XMLDocument doc( false );
789 doc.Parse( passages );
790
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700791 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ),
Lee Thomason6f381b72012-03-02 12:59:39 -0800792 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;." );
793 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value(),
794 "Crazy &ttk;" );
795 doc.Print();
796 }
797
798 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400799 const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800800
801 XMLDocument doc;
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400802 doc.Parse( test );
803 XMLTest( "dot in names", doc.Error(), false );
804 XMLTest( "dot in names", doc.FirstChildElement()->Name(), "a.elem" );
805 XMLTest( "dot in names", doc.FirstChildElement()->Attribute( "xmi.version" ), "2.0" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800806 }
807
808 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400809 const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800810
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400811 XMLDocument doc;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800812 doc.Parse( test );
813
814 XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
815 XMLTest( "Entity with one digit.",
816 text->Value(), "1.1 Start easy ignore fin thickness\n",
817 false );
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400818 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800819
820 {
821 // DOCTYPE not preserved (950171)
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700822 //
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800823 const char* doctype =
824 "<?xml version=\"1.0\" ?>"
825 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
826 "<!ELEMENT title (#PCDATA)>"
827 "<!ELEMENT books (title,authors)>"
828 "<element />";
829
830 XMLDocument doc;
831 doc.Parse( doctype );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400832 doc.SaveFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800833 doc.DeleteChild( doc.RootElement() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400834 doc.LoadFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800835 doc.Print();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700836
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800837 const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
838 XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
839
840 }
841
842 {
843 // Comments do not stream out correctly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700844 const char* doctype =
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800845 "<!-- Somewhat<evil> -->";
846 XMLDocument doc;
847 doc.Parse( doctype );
848
849 XMLComment* comment = doc.FirstChild()->ToComment();
850
851 XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
852 }
853 {
854 // Double attributes
855 const char* doctype = "<element attr='red' attr='blue' />";
856
857 XMLDocument doc;
858 doc.Parse( doctype );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700859
Lee Thomason2fa81722012-11-09 12:37:46 -0800860 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 -0800861 doc.PrintError();
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800862 }
863
864 {
865 // Embedded null in stream.
866 const char* doctype = "<element att\0r='red' attr='blue' />";
867
868 XMLDocument doc;
869 doc.Parse( doctype );
870 XMLTest( "Embedded null throws error.", true, doc.Error() );
871 }
872
873 {
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700874 // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
Dmitry-Me588bb8d2014-12-25 18:59:18 +0300875 const char* str = "";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800876 XMLDocument doc;
877 doc.Parse( str );
Lee Thomason2fa81722012-11-09 12:37:46 -0800878 XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800879 }
880
881 {
Dmitry-Me588bb8d2014-12-25 18:59:18 +0300882 // Documents with all whitespaces should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
883 const char* str = " ";
884 XMLDocument doc;
885 doc.Parse( str );
886 XMLTest( "All whitespaces document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
887 }
888
889 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800890 // Low entities
891 XMLDocument doc;
892 doc.Parse( "<test>&#x0e;</test>" );
893 const char result[] = { 0x0e, 0 };
894 XMLTest( "Low entities.", doc.FirstChildElement()->GetText(), result );
895 doc.Print();
896 }
897
898 {
899 // Attribute values with trailing quotes not handled correctly
900 XMLDocument doc;
901 doc.Parse( "<foo attribute=bar\" />" );
902 XMLTest( "Throw error with bad end quotes.", doc.Error(), true );
903 }
904
905 {
906 // [ 1663758 ] Failure to report error on bad XML
907 XMLDocument xml;
908 xml.Parse("<x>");
909 XMLTest("Missing end tag at end of input", xml.Error(), true);
910 xml.Parse("<x> ");
911 XMLTest("Missing end tag with trailing whitespace", xml.Error(), true);
912 xml.Parse("<x></y>");
Lee Thomason2fa81722012-11-09 12:37:46 -0800913 XMLTest("Mismatched tags", xml.ErrorID(), XML_ERROR_MISMATCHED_ELEMENT);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700914 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800915
916
917 {
918 // [ 1475201 ] TinyXML parses entities in comments
919 XMLDocument xml;
920 xml.Parse("<!-- declarations for <head> & <body> -->"
921 "<!-- far &amp; away -->" );
922
923 XMLNode* e0 = xml.FirstChild();
924 XMLNode* e1 = e0->NextSibling();
925 XMLComment* c0 = e0->ToComment();
926 XMLComment* c1 = e1->ToComment();
927
928 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
929 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
930 }
931
932 {
933 XMLDocument xml;
934 xml.Parse( "<Parent>"
935 "<child1 att=''/>"
936 "<!-- With this comment, child2 will not be parsed! -->"
937 "<child2 att=''/>"
938 "</Parent>" );
939 xml.Print();
940
941 int count = 0;
942
943 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
944 ele;
945 ele = ele->NextSibling() )
946 {
947 ++count;
948 }
949
950 XMLTest( "Comments iterate correctly.", 3, count );
951 }
952
953 {
954 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
955 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
956 buf[60] = 239;
957 buf[61] = 0;
958
959 XMLDocument doc;
960 doc.Parse( (const char*)buf);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700961 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800962
963
964 {
965 // bug 1827248 Error while parsing a little bit malformed file
966 // Actually not malformed - should work.
967 XMLDocument xml;
968 xml.Parse( "<attributelist> </attributelist >" );
969 XMLTest( "Handle end tag whitespace", false, xml.Error() );
970 }
971
972 {
973 // This one must not result in an infinite loop
974 XMLDocument xml;
975 xml.Parse( "<infinite>loop" );
976 XMLTest( "Infinite loop test.", true, true );
977 }
978#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800979 {
980 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
981 XMLDocument doc;
982 doc.Parse( pub );
983
984 XMLDocument clone;
985 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
986 XMLNode* copy = node->ShallowClone( &clone );
987 clone.InsertEndChild( copy );
988 }
989
990 clone.Print();
991
992 int count=0;
993 const XMLNode* a=clone.FirstChild();
994 const XMLNode* b=doc.FirstChild();
995 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
996 ++count;
997 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
998 }
999 XMLTest( "Clone and Equal", 4, count );
1000 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001001
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001002 {
1003 // This shouldn't crash.
1004 XMLDocument doc;
1005 if(XML_NO_ERROR != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
1006 {
1007 doc.PrintError();
1008 }
1009 XMLTest( "Error in snprinf handling.", true, doc.Error() );
1010 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001011
Lee Thomason5e3803c2012-04-16 08:57:05 -07001012 {
1013 // Attribute ordering.
1014 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
1015 XMLDocument doc;
1016 doc.Parse( xml );
1017 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001018
Lee Thomason5e3803c2012-04-16 08:57:05 -07001019 const XMLAttribute* a = ele->FirstAttribute();
1020 XMLTest( "Attribute order", "1", a->Value() );
1021 a = a->Next();
1022 XMLTest( "Attribute order", "2", a->Value() );
1023 a = a->Next();
1024 XMLTest( "Attribute order", "3", a->Value() );
1025 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001026
Lee Thomason5e3803c2012-04-16 08:57:05 -07001027 ele->DeleteAttribute( "attrib2" );
1028 a = ele->FirstAttribute();
1029 XMLTest( "Attribute order", "1", a->Value() );
1030 a = a->Next();
1031 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001032
Lee Thomason5e3803c2012-04-16 08:57:05 -07001033 ele->DeleteAttribute( "attrib1" );
1034 ele->DeleteAttribute( "attrib3" );
1035 XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
1036 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001037
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001038 {
1039 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -07001040 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
1041 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
1042 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
1043 XMLDocument doc0;
1044 doc0.Parse( xml0 );
1045 XMLDocument doc1;
1046 doc1.Parse( xml1 );
1047 XMLDocument doc2;
1048 doc2.Parse( xml2 );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001049
Lee Thomason78a773d2012-07-02 10:10:19 -07001050 XMLElement* ele = 0;
1051 ele = doc0.FirstChildElement();
1052 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
1053 ele = doc1.FirstChildElement();
1054 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
1055 ele = doc2.FirstChildElement();
1056 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001057 }
1058
1059 {
1060 // Make sure we don't go into an infinite loop.
1061 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
1062 XMLDocument doc;
1063 doc.Parse( xml );
1064 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
1065 XMLElement* ele1 = ele0->NextSiblingElement();
1066 bool equal = ele0->ShallowEqual( ele1 );
1067
1068 XMLTest( "Infinite loop in shallow equal.", true, equal );
1069 }
1070
Lee Thomason5708f812012-03-28 17:46:41 -07001071 // -------- Handles ------------
1072 {
1073 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1074 XMLDocument doc;
1075 doc.Parse( xml );
Lee Thomason5708f812012-03-28 17:46:41 -07001076
1077 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
1078 XMLTest( "Handle, success, mutable", ele->Value(), "sub" );
1079
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001080 XMLHandle docH( doc );
1081 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001082 XMLTest( "Handle, dne, mutable", false, ele != 0 );
Lee Thomason5708f812012-03-28 17:46:41 -07001083 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001084
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001085 {
1086 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1087 XMLDocument doc;
1088 doc.Parse( xml );
1089 XMLConstHandle docH( doc );
1090
1091 const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
1092 XMLTest( "Handle, success, const", ele->Value(), "sub" );
1093
1094 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001095 XMLTest( "Handle, dne, const", false, ele != 0 );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001096 }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001097 {
1098 // Default Declaration & BOM
1099 XMLDocument doc;
1100 doc.InsertEndChild( doc.NewDeclaration() );
1101 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001102
Lee Thomasonf68c4382012-04-28 14:37:11 -07001103 XMLPrinter printer;
1104 doc.Print( &printer );
1105
1106 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1107 XMLTest( "BOM and default declaration", printer.CStr(), result, false );
Lee Thomason (grinliz)48ea0bc2012-05-26 14:41:14 -07001108 XMLTest( "CStrSize", printer.CStrSize(), 42, false );
Lee Thomasonf68c4382012-04-28 14:37:11 -07001109 }
Lee Thomason21be8822012-07-15 17:27:22 -07001110 {
1111 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1112 XMLDocument doc;
1113 doc.Parse( xml );
1114 XMLTest( "Ill formed XML", true, doc.Error() );
1115 }
1116
1117 // QueryXYZText
1118 {
1119 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1120 XMLDocument doc;
1121 doc.Parse( xml );
1122
1123 const XMLElement* pointElement = doc.RootElement();
1124
1125 int intValue = 0;
1126 unsigned unsignedValue = 0;
1127 float floatValue = 0;
1128 double doubleValue = 0;
1129 bool boolValue = false;
1130
1131 pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1132 pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1133 pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1134 pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1135 pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1136
1137
1138 XMLTest( "QueryIntText", intValue, 1, false );
1139 XMLTest( "QueryUnsignedText", unsignedValue, (unsigned)1, false );
1140 XMLTest( "QueryFloatText", floatValue, 1.2f, false );
1141 XMLTest( "QueryDoubleText", doubleValue, 1.2, false );
1142 XMLTest( "QueryBoolText", boolValue, true, false );
1143 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001144
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001145 {
1146 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1147 XMLDocument doc;
1148 doc.Parse( xml );
1149 XMLTest( "Non-alpha element lead letter parses.", doc.Error(), false );
1150 }
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001151
1152 {
1153 const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1154 XMLDocument doc;
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001155 doc.Parse( xml );
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001156 XMLTest("Non-alpha attribute lead character parses.", doc.Error(), false);
1157 }
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001158
1159 {
1160 const char* xml = "<3lement></3lement>";
1161 XMLDocument doc;
1162 doc.Parse( xml );
1163 XMLTest("Element names with lead digit fail to parse.", doc.Error(), true);
1164 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -07001165
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001166 {
1167 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1168 XMLDocument doc;
1169 doc.Parse( xml, 10 );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001170 XMLTest( "Set length of incoming data", doc.Error(), false );
1171 }
1172
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001173 {
1174 XMLDocument doc;
Dmitry-Me48b5df02015-04-06 18:20:25 +03001175 XMLTest( "Document is initially empty", doc.NoChildren(), true );
1176 doc.Clear();
1177 XMLTest( "Empty is empty after Clear()", doc.NoChildren(), true );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001178 doc.LoadFile( "resources/dream.xml" );
Dmitry-Meaaa4cea2015-02-06 16:00:46 +03001179 XMLTest( "Document has something to Clear()", doc.NoChildren(), false );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001180 doc.Clear();
1181 XMLTest( "Document Clear()'s", doc.NoChildren(), true );
1182 }
1183
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001184 // ----------- Whitespace ------------
1185 {
1186 const char* xml = "<element>"
1187 "<a> This \nis &apos; text &apos; </a>"
1188 "<b> This is &apos; text &apos; \n</b>"
1189 "<c>This is &apos; \n\n text &apos;</c>"
1190 "</element>";
1191 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1192 doc.Parse( xml );
1193
1194 const XMLElement* element = doc.FirstChildElement();
1195 for( const XMLElement* parent = element->FirstChildElement();
1196 parent;
1197 parent = parent->NextSiblingElement() )
1198 {
1199 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1200 }
1201 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001202
Lee Thomasonae9ab072012-10-24 10:17:53 -07001203#if 0
1204 {
1205 // Passes if assert doesn't fire.
1206 XMLDocument xmlDoc;
1207
1208 xmlDoc.NewDeclaration();
1209 xmlDoc.NewComment("Configuration file");
1210
1211 XMLElement *root = xmlDoc.NewElement("settings");
1212 root->SetAttribute("version", 2);
1213 }
1214#endif
1215
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001216 {
1217 const char* xml = "<element> </element>";
1218 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1219 doc.Parse( xml );
1220 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1221 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001222
Lee Thomason5b0a6772012-11-19 13:54:42 -08001223 {
1224 // An assert should not fire.
1225 const char* xml = "<element/>";
1226 XMLDocument doc;
1227 doc.Parse( xml );
1228 XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope.
1229 XMLTest( "Tracking unused elements", true, ele != 0, false );
1230 }
1231
Lee Thomasona6412ac2012-12-13 15:39:11 -08001232
1233 {
1234 const char* xml = "<parent><child>abc</child></parent>";
1235 XMLDocument doc;
1236 doc.Parse( xml );
1237 XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
1238
1239 XMLPrinter printer;
1240 ele->Accept( &printer );
1241 XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1242 }
1243
1244
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001245 {
1246 XMLDocument doc;
1247 XMLError error = doc.LoadFile( "resources/empty.xml" );
1248 XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
Lee Thomason331596e2014-09-11 14:56:43 -07001249 XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() );
Lee Thomasonc7556672014-09-14 12:39:42 -07001250 doc.PrintError();
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001251 }
1252
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001253 {
1254 // BOM preservation
1255 static const char* xml_bom_preservation = "\xef\xbb\xbf<element/>\n";
1256 {
1257 XMLDocument doc;
1258 XMLTest( "BOM preservation (parse)", XML_NO_ERROR, doc.Parse( xml_bom_preservation ), false );
1259 XMLPrinter printer;
1260 doc.Print( &printer );
1261
1262 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1263 doc.SaveFile( "resources/bomtest.xml" );
1264 }
1265 {
1266 XMLDocument doc;
1267 doc.LoadFile( "resources/bomtest.xml" );
1268 XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
1269
1270 XMLPrinter printer;
1271 doc.Print( &printer );
1272 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1273 }
1274 }
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001275
Michael Daumlinged523282013-10-23 07:47:29 +02001276 {
1277 // Insertion with Removal
1278 const char* xml = "<?xml version=\"1.0\" ?>"
1279 "<root>"
1280 "<one>"
1281 "<subtree>"
1282 "<elem>element 1</elem>text<!-- comment -->"
1283 "</subtree>"
1284 "</one>"
1285 "<two/>"
1286 "</root>";
1287 const char* xmlInsideTwo = "<?xml version=\"1.0\" ?>"
1288 "<root>"
1289 "<one/>"
1290 "<two>"
1291 "<subtree>"
1292 "<elem>element 1</elem>text<!-- comment -->"
1293 "</subtree>"
1294 "</two>"
1295 "</root>";
1296 const char* xmlAfterOne = "<?xml version=\"1.0\" ?>"
1297 "<root>"
1298 "<one/>"
1299 "<subtree>"
1300 "<elem>element 1</elem>text<!-- comment -->"
1301 "</subtree>"
1302 "<two/>"
1303 "</root>";
1304 const char* xmlAfterTwo = "<?xml version=\"1.0\" ?>"
1305 "<root>"
1306 "<one/>"
1307 "<two/>"
1308 "<subtree>"
1309 "<elem>element 1</elem>text<!-- comment -->"
1310 "</subtree>"
1311 "</root>";
1312
1313 XMLDocument doc;
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001314 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001315 XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1316 XMLElement* two = doc.RootElement()->FirstChildElement("two");
1317 two->InsertFirstChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001318 XMLPrinter printer1(0, true);
1319 doc.Accept(&printer1);
1320 XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
Michael Daumlinged523282013-10-23 07:47:29 +02001321
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001322 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001323 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1324 two = doc.RootElement()->FirstChildElement("two");
1325 doc.RootElement()->InsertAfterChild(two, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001326 XMLPrinter printer2(0, true);
1327 doc.Accept(&printer2);
1328 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001329
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001330 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001331 XMLNode* one = doc.RootElement()->FirstChildElement("one");
1332 subtree = one->FirstChildElement("subtree");
1333 doc.RootElement()->InsertAfterChild(one, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001334 XMLPrinter printer3(0, true);
1335 doc.Accept(&printer3);
1336 XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001337
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001338 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001339 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1340 two = doc.RootElement()->FirstChildElement("two");
1341 doc.RootElement()->InsertEndChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001342 XMLPrinter printer4(0, true);
1343 doc.Accept(&printer4);
1344 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001345 }
1346
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001347 {
1348 const char* xml = "<svg width = \"128\" height = \"128\">"
1349 " <text> </text>"
1350 "</svg>";
1351 XMLDocument doc;
1352 doc.Parse(xml);
1353 doc.Print();
1354 }
1355
Lee Thomason92e521b2014-11-15 17:45:51 -08001356 {
1357 // Test that it doesn't crash.
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001358 const char* xml = "<?xml version=\"1.0\"?><root><sample><field0><1</field0><field1>2</field1></sample></root>";
1359 XMLDocument doc;
1360 doc.Parse(xml);
1361 doc.PrintError();
Lee Thomason92e521b2014-11-15 17:45:51 -08001362 }
1363
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001364#if 1
1365 // the question being explored is what kind of print to use:
1366 // https://github.com/leethomason/tinyxml2/issues/63
1367 {
1368 //const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
1369 const char* xml = "<element/>";
1370 XMLDocument doc;
1371 doc.Parse( xml );
1372 doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
1373 doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
1374 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
1375 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
1376 doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
1377 doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
1378
1379 doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
1380 doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
1381 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
1382 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
1383 doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
1384 doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
1385
1386 doc.Print();
1387
1388 /* The result of this test is platform, compiler, and library version dependent. :("
1389 XMLPrinter printer;
1390 doc.Print( &printer );
1391 XMLTest( "Float and double formatting.",
1392 "<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",
1393 printer.CStr(),
1394 true );
1395 */
1396 }
1397#endif
Lee Thomasonf07b9522014-10-30 13:25:12 -07001398
1399 {
1400 // Issue #184
1401 // If it doesn't assert, it passes. Caused by objects
1402 // getting created during parsing which are then
1403 // inaccessible in the memory pools.
1404 {
1405 XMLDocument doc;
1406 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1407 }
1408 {
1409 XMLDocument doc;
1410 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1411 doc.Clear();
1412 }
1413 }
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001414
1415 {
1416 // If this doesn't assert in DEBUG, all is well.
1417 tinyxml2::XMLDocument doc;
1418 tinyxml2::XMLElement *pRoot = doc.NewElement("Root");
1419 doc.DeleteNode(pRoot);
1420 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001421
Dmitry-Me8b67d742014-12-22 11:35:12 +03001422 {
1423 // Should not assert in DEBUG
1424 XMLPrinter printer;
1425 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001426
Dmitry-Me6f51c802015-03-14 13:25:03 +03001427 {
1428 // Issue 291. Should not crash
1429 const char* xml = "&#0</a>";
1430 XMLDocument doc;
1431 doc.Parse( xml );
1432
1433 XMLPrinter printer;
1434 doc.Print( &printer );
1435 }
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001436 {
1437 // Issue 299. Can print elements that are not linked in.
1438 // Will crash if issue not fixed.
1439 XMLDocument doc;
1440 XMLElement* newElement = doc.NewElement( "printme" );
1441 XMLPrinter printer;
1442 newElement->Accept( &printer );
Dmitry-Me5daa54c2015-04-08 17:45:07 +03001443 // Delete the node to avoid possible memory leak report in debug output
1444 doc.DeleteNode( newElement );
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001445 }
Lee Thomasonf6577832015-03-26 11:18:21 -07001446 {
Ant Mitchell189198f2015-03-24 16:20:36 +00001447 // Issue 302. Clear errors from LoadFile/SaveFile
1448 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001449 XMLTest( "Issue 302. Should be no error initially", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001450 doc.SaveFile( "./no/such/path/pretty.xml" );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001451 XMLTest( "Issue 302. Fail to save", "XML_ERROR_FILE_COULD_NOT_BE_OPENED", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001452 doc.SaveFile( "./resources/out/compact.xml", true );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001453 XMLTest( "Issue 302. Subsequent success in saving", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001454 }
Dmitry-Me6f51c802015-03-14 13:25:03 +03001455
Dmitry-Med9852a52015-03-25 10:17:49 +03001456 {
1457 // If a document fails to load then subsequent
1458 // successful loads should clear the error
1459 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001460 XMLTest( "Should be no error initially", false, doc.Error() );
Dmitry-Med9852a52015-03-25 10:17:49 +03001461 doc.LoadFile( "resources/no-such-file.xml" );
1462 XMLTest( "No such file - should fail", true, doc.Error() );
1463
1464 doc.LoadFile( "resources/dream.xml" );
1465 XMLTest( "Error should be cleared", false, doc.Error() );
1466 }
1467
Sarat Addepallia7edb882015-05-19 12:39:27 +05301468 {
1469 // No matter - before or after successfully parsing a text -
1470 // calling XMLDocument::Value() causes an assert in debug.
1471 const char* validXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
1472 "<first />"
1473 "<second />";
1474 XMLDocument* doc = new XMLDocument();
1475 const char* value;
1476 XMLTest( "XMLDocument::Value() fires assert?", NULL, doc->Value() );
1477 doc->Parse( validXml );
1478 XMLTest( "XMLDocument::Value() fires assert?", NULL, doc->Value() );
1479 delete doc;
1480 }
1481
1482 // ----------- Performance tracking --------------
Lee Thomason6f381b72012-03-02 12:59:39 -08001483 {
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}