blob: 0b8b9e54c61d9b74a153ea3f366fd1b74ba1ce64 [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;
Sarat Addepallid608c562015-05-20 10:19:00 +053038 else
39 pass = !strcmp( expected, found );
Lee Thomason1ff38e02012-02-14 18:18:16 -080040 if ( pass )
41 printf ("[pass]");
42 else
43 printf ("[fail]");
44
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070045 if ( !echo ) {
Lee Thomason1ff38e02012-02-14 18:18:16 -080046 printf (" %s\n", testString);
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070047 }
48 else {
49 if ( extraNL ) {
50 printf( " %s\n", testString );
51 printf( "%s\n", expected );
52 printf( "%s\n", found );
53 }
54 else {
55 printf (" %s [%s][%s]\n", testString, expected, found);
56 }
57 }
Lee Thomason1ff38e02012-02-14 18:18:16 -080058
59 if ( pass )
60 ++gPass;
61 else
62 ++gFail;
63 return pass;
64}
65
66
Lee Thomason21be8822012-07-15 17:27:22 -070067template< class T > bool XMLTest( const char* testString, T expected, T found, bool echo=true )
Lee Thomason1ff38e02012-02-14 18:18:16 -080068{
69 bool pass = ( expected == found );
70 if ( pass )
71 printf ("[pass]");
72 else
73 printf ("[fail]");
74
U-Stream\Lee09a11c52012-02-17 08:31:16 -080075 if ( !echo )
Lee Thomason1ff38e02012-02-14 18:18:16 -080076 printf (" %s\n", testString);
77 else
Lee Thomasonc8312792012-07-16 12:44:41 -070078 printf (" %s [%d][%d]\n", testString, static_cast<int>(expected), static_cast<int>(found) );
Lee Thomason1ff38e02012-02-14 18:18:16 -080079
80 if ( pass )
81 ++gPass;
82 else
83 ++gFail;
84 return pass;
85}
Lee Thomasonec5a7b42012-02-13 18:16:52 -080086
U-Lama\Leee13c3e62011-12-28 14:36:55 -080087
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -080088void NullLineEndings( char* p )
89{
90 while( p && *p ) {
91 if ( *p == '\n' || *p == '\r' ) {
92 *p = 0;
93 return;
94 }
95 ++p;
96 }
97}
98
99
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700100int example_1()
101{
102 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300103 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700104
105 return doc.ErrorID();
106}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200107/** @page Example-1 Load an XML File
108 * @dontinclude ./xmltest.cpp
109 * Basic XML file loading.
110 * The basic syntax to load an XML file from
111 * disk and check for an error. (ErrorID()
112 * will return 0 for no error.)
113 * @skip example_1()
114 * @until }
115 */
116
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700117
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700118int example_2()
119{
120 static const char* xml = "<element/>";
121 XMLDocument doc;
122 doc.Parse( xml );
123
124 return doc.ErrorID();
125}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200126/** @page Example-2 Parse an XML from char buffer
127 * @dontinclude ./xmltest.cpp
128 * Basic XML string parsing.
129 * The basic syntax to parse an XML for
130 * a char* and check for an error. (ErrorID()
131 * will return 0 for no error.)
132 * @skip example_2()
133 * @until }
134 */
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700135
136
137int example_3()
138{
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700139 static const char* xml =
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700140 "<?xml version=\"1.0\"?>"
141 "<!DOCTYPE PLAY SYSTEM \"play.dtd\">"
142 "<PLAY>"
143 "<TITLE>A Midsummer Night's Dream</TITLE>"
144 "</PLAY>";
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700145
146 XMLDocument doc;
147 doc.Parse( xml );
148
149 XMLElement* titleElement = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" );
150 const char* title = titleElement->GetText();
151 printf( "Name of play (1): %s\n", title );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700152
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700153 XMLText* textNode = titleElement->FirstChild()->ToText();
154 title = textNode->Value();
155 printf( "Name of play (2): %s\n", title );
156
157 return doc.ErrorID();
158}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200159/** @page Example-3 Get information out of XML
160 @dontinclude ./xmltest.cpp
161 In this example, we navigate a simple XML
162 file, and read some interesting text. Note
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700163 that this example doesn't use error
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200164 checking; working code should check for null
165 pointers when walking an XML tree, or use
166 XMLHandle.
167
168 (The XML is an excerpt from "dream.xml").
169
170 @skip example_3()
171 @until </PLAY>";
172
173 The structure of the XML file is:
174
175 <ul>
176 <li>(declaration)</li>
177 <li>(dtd stuff)</li>
178 <li>Element "PLAY"</li>
179 <ul>
180 <li>Element "TITLE"</li>
181 <ul>
182 <li>Text "A Midsummer Night's Dream"</li>
183 </ul>
184 </ul>
185 </ul>
186
187 For this example, we want to print out the
188 title of the play. The text of the title (what
189 we want) is child of the "TITLE" element which
190 is a child of the "PLAY" element.
191
192 We want to skip the declaration and dtd, so the
193 method FirstChildElement() is a good choice. The
194 FirstChildElement() of the Document is the "PLAY"
195 Element, the FirstChildElement() of the "PLAY" Element
196 is the "TITLE" Element.
197
198 @until ( "TITLE" );
199
200 We can then use the convenience function GetText()
201 to get the title of the play.
202
203 @until title );
204
205 Text is just another Node in the XML DOM. And in
206 fact you should be a little cautious with it, as
207 text nodes can contain elements.
208
209 @verbatim
210 Consider: A Midsummer Night's <b>Dream</b>
211 @endverbatim
212
213 It is more correct to actually query the Text Node
214 if in doubt:
215
216 @until title );
217
218 Noting that here we use FirstChild() since we are
219 looking for XMLText, not an element, and ToText()
220 is a cast from a Node to a XMLText.
221*/
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700222
223
Lee Thomason21be8822012-07-15 17:27:22 -0700224bool example_4()
225{
226 static const char* xml =
227 "<information>"
228 " <attributeApproach v='2' />"
229 " <textApproach>"
230 " <v>2</v>"
231 " </textApproach>"
232 "</information>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700233
Lee Thomason21be8822012-07-15 17:27:22 -0700234 XMLDocument doc;
235 doc.Parse( xml );
236
237 int v0 = 0;
238 int v1 = 0;
239
240 XMLElement* attributeApproachElement = doc.FirstChildElement()->FirstChildElement( "attributeApproach" );
241 attributeApproachElement->QueryIntAttribute( "v", &v0 );
242
243 XMLElement* textApproachElement = doc.FirstChildElement()->FirstChildElement( "textApproach" );
244 textApproachElement->FirstChildElement( "v" )->QueryIntText( &v1 );
245
246 printf( "Both values are the same: %d and %d\n", v0, v1 );
247
248 return !doc.Error() && ( v0 == v1 );
249}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200250/** @page Example-4 Read attributes and text information.
251 @dontinclude ./xmltest.cpp
252
253 There are fundamentally 2 ways of writing a key-value
254 pair into an XML file. (Something that's always annoyed
255 me about XML.) Either by using attributes, or by writing
256 the key name into an element and the value into
257 the text node wrapped by the element. Both approaches
258 are illustrated in this example, which shows two ways
259 to encode the value "2" into the key "v":
260
261 @skip example_4()
262 @until "</information>";
263
264 TinyXML-2 has accessors for both approaches.
265
266 When using an attribute, you navigate to the XMLElement
267 with that attribute and use the QueryIntAttribute()
268 group of methods. (Also QueryFloatAttribute(), etc.)
269
270 @skip XMLElement* attributeApproachElement
271 @until &v0 );
272
273 When using the text approach, you need to navigate
274 down one more step to the XMLElement that contains
275 the text. Note the extra FirstChildElement( "v" )
276 in the code below. The value of the text can then
277 be safely queried with the QueryIntText() group
278 of methods. (Also QueryFloatText(), etc.)
279
280 @skip XMLElement* textApproachElement
281 @until &v1 );
282*/
Lee Thomason21be8822012-07-15 17:27:22 -0700283
284
Lee Thomason178e4cc2013-01-25 16:19:05 -0800285int main( int argc, const char ** argv )
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800286{
Lee Thomason (grinliz)0a4df402012-02-27 20:50:52 -0800287 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason1ff38e02012-02-14 18:18:16 -0800288 _CrtMemCheckpoint( &startMemState );
Dmitry-Me99916592014-10-23 11:37:03 +0400289 // Enable MS Visual C++ debug heap memory leaks dump on exit
290 _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700291 #endif
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800292
Martinsh Shaiters39ddc262013-01-15 21:53:08 +0200293 #if defined(_MSC_VER) || defined(MINGW32) || defined(__MINGW32__)
ddiproiettoa8ae1f62013-05-05 18:42:52 +0300294 #if defined __MINGW64_VERSION_MAJOR && defined __MINGW64_VERSION_MINOR
295 //MINGW64: both 32 and 64-bit
296 mkdir( "resources/out/" );
297 #else
298 _mkdir( "resources/out/" );
299 #endif
Lee Thomasone9699e62012-07-25 12:24:23 -0700300 #else
301 mkdir( "resources/out/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
302 #endif
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400303
Dmitry-Me4bcbf142014-12-25 19:05:18 +0300304 {
305 TIXMLASSERT( true );
306 }
307
Lee Thomason178e4cc2013-01-25 16:19:05 -0800308 if ( argc > 1 ) {
309 XMLDocument* doc = new XMLDocument();
310 clock_t startTime = clock();
311 doc->LoadFile( argv[1] );
Anton Indrawan8a0006c2014-11-20 18:27:07 +0100312 clock_t loadTime = clock();
Lee Thomason178e4cc2013-01-25 16:19:05 -0800313 int errorID = doc->ErrorID();
314 delete doc; doc = 0;
Anton Indrawan8a0006c2014-11-20 18:27:07 +0100315 clock_t deleteTime = clock();
Lee Thomason178e4cc2013-01-25 16:19:05 -0800316
317 printf( "Test file '%s' loaded. ErrorID=%d\n", argv[1], errorID );
318 if ( !errorID ) {
Lee Thomason (grinliz)d6bd7362013-05-11 20:23:13 -0700319 printf( "Load time=%u\n", (unsigned)(loadTime - startTime) );
320 printf( "Delete time=%u\n", (unsigned)(deleteTime - loadTime) );
321 printf( "Total time=%u\n", (unsigned)(deleteTime - startTime) );
Lee Thomason178e4cc2013-01-25 16:19:05 -0800322 }
323 exit(0);
324 }
325
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300326 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason7f7b1622012-03-24 12:49:03 -0700327 if ( !fp ) {
328 printf( "Error opening test file 'dream.xml'.\n"
329 "Is your working directory the same as where \n"
330 "the xmltest.cpp and dream.xml file are?\n\n"
331 #if defined( _MSC_VER )
332 "In windows Visual Studio you may need to set\n"
333 "Properties->Debugging->Working Directory to '..'\n"
334 #endif
335 );
336 exit( 1 );
337 }
338 fclose( fp );
339
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700340 XMLTest( "Example-1", 0, example_1() );
341 XMLTest( "Example-2", 0, example_2() );
342 XMLTest( "Example-3", 0, example_3() );
Lee Thomason21be8822012-07-15 17:27:22 -0700343 XMLTest( "Example-4", true, example_4() );
Lee Thomason87e475a2012-03-20 11:55:29 -0700344
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700345 /* ------ Example 2: Lookup information. ---- */
Lee Thomason87e475a2012-03-20 11:55:29 -0700346
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800347 {
Lee Thomason43f59302012-02-06 18:18:11 -0800348 static const char* test[] = { "<element />",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400349 "<element></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800350 "<element><subelement/></element>",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400351 "<element><subelement></subelement></element>",
352 "<element><subelement><subsub/></subelement></element>",
353 "<!--comment beside elements--><element><subelement></subelement></element>",
354 "<!--comment beside elements, this time with spaces--> \n <element> <subelement> \n </subelement> </element>",
355 "<element attrib1='foo' attrib2=\"bar\" ></element>",
356 "<element attrib1='foo' attrib2=\"bar\" ><subelement attrib3='yeehaa' /></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800357 "<element>Text inside element.</element>",
358 "<element><b></b></element>",
359 "<element>Text inside and <b>bolded</b> in the element.</element>",
360 "<outer><element>Text inside and <b>bolded</b> in the element.</element></outer>",
Lee Thomason8ee79892012-01-25 17:44:30 -0800361 "<element>This &amp; That.</element>",
Lee Thomason18d68bd2012-01-26 18:17:26 -0800362 "<element attrib='This&lt;That' />",
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800363 0
364 };
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800365 for( int i=0; test[i]; ++i ) {
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800366 XMLDocument doc;
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800367 doc.Parse( test[i] );
Lee Thomason5cae8972012-01-24 18:03:07 -0800368 doc.Print();
Lee Thomasonec975ce2012-01-23 11:42:06 -0800369 printf( "----------------------------------------------\n" );
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800370 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800371 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800372#if 1
Lee Thomasond6277762012-02-22 16:00:12 -0800373 {
374 static const char* test = "<!--hello world\n"
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400375 " line 2\r"
376 " line 3\r\n"
377 " line 4\n\r"
378 " line 5\r-->";
Lee Thomasond6277762012-02-22 16:00:12 -0800379
380 XMLDocument doc;
381 doc.Parse( test );
382 doc.Print();
383 }
384
Lee Thomason2c85a712012-01-31 08:24:24 -0800385 {
386 static const char* test = "<element>Text before.</element>";
387 XMLDocument doc;
388 doc.Parse( test );
389 XMLElement* root = doc.FirstChildElement();
390 XMLElement* newElement = doc.NewElement( "Subelement" );
391 root->InsertEndChild( newElement );
392 doc.Print();
393 }
Lee Thomasond1983222012-02-06 08:41:24 -0800394 {
395 XMLDocument* doc = new XMLDocument();
396 static const char* test = "<element><sub/></element>";
397 doc->Parse( test );
398 delete doc;
399 }
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800400 {
Lee Thomason1ff38e02012-02-14 18:18:16 -0800401 // Test: Programmatic DOM
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800402 // Build:
403 // <element>
404 // <!--comment-->
405 // <sub attrib="1" />
406 // <sub attrib="2" />
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800407 // <sub attrib="3" >& Text!</sub>
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800408 // <element>
409
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800410 XMLDocument* doc = new XMLDocument();
Lee Thomason1ff38e02012-02-14 18:18:16 -0800411 XMLNode* element = doc->InsertEndChild( doc->NewElement( "element" ) );
412
413 XMLElement* sub[3] = { doc->NewElement( "sub" ), doc->NewElement( "sub" ), doc->NewElement( "sub" ) };
414 for( int i=0; i<3; ++i ) {
415 sub[i]->SetAttribute( "attrib", i );
416 }
417 element->InsertEndChild( sub[2] );
418 XMLNode* comment = element->InsertFirstChild( doc->NewComment( "comment" ) );
Lee Thomasonaf9bce12016-07-17 22:35:52 -0700419 comment->SetUserData((void*)2);
Lee Thomason1ff38e02012-02-14 18:18:16 -0800420 element->InsertAfterChild( comment, sub[0] );
421 element->InsertAfterChild( sub[0], sub[1] );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800422 sub[2]->InsertFirstChild( doc->NewText( "& Text!" ));
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800423 doc->Print();
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800424 XMLTest( "Programmatic DOM", "comment", doc->FirstChildElement( "element" )->FirstChild()->Value() );
425 XMLTest( "Programmatic DOM", "0", doc->FirstChildElement( "element" )->FirstChildElement()->Attribute( "attrib" ) );
426 XMLTest( "Programmatic DOM", 2, doc->FirstChildElement()->LastChildElement( "sub" )->IntAttribute( "attrib" ) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700427 XMLTest( "Programmatic DOM", "& Text!",
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800428 doc->FirstChildElement()->LastChildElement( "sub" )->FirstChild()->ToText()->Value() );
Lee Thomasonc9445462016-07-17 22:53:48 -0700429 XMLTest("User data", (void*)2 == comment->GetUserData(), true, false);
U-Stream\Leeae25a442012-02-17 17:48:16 -0800430
431 // And now deletion:
432 element->DeleteChild( sub[2] );
433 doc->DeleteNode( comment );
434
435 element->FirstChildElement()->SetAttribute( "attrib", true );
436 element->LastChildElement()->DeleteAttribute( "attrib" );
437
438 XMLTest( "Programmatic DOM", true, doc->FirstChildElement()->FirstChildElement()->BoolAttribute( "attrib" ) );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700439 int value1 = 10;
440 int value2 = doc->FirstChildElement()->LastChildElement()->IntAttribute( "attrib", 10 );
441 int result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value1 );
Lee Thomason21be8822012-07-15 17:27:22 -0700442 XMLTest( "Programmatic DOM", result, (int)XML_NO_ATTRIBUTE );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700443 XMLTest( "Programmatic DOM", value1, 10 );
444 XMLTest( "Programmatic DOM", value2, 10 );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800445
446 doc->Print();
447
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700448 {
449 XMLPrinter streamer;
450 doc->Print( &streamer );
451 printf( "%s", streamer.CStr() );
452 }
453 {
454 XMLPrinter streamer( 0, true );
455 doc->Print( &streamer );
Doruk Turak1f212f32016-08-28 20:54:17 +0200456 XMLTest( "Compact mode", "<element><sub attrib=\"true\"/><sub/></element>", streamer.CStr(), false );
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700457 }
Lee Thomason (grinliz)6b8b0122012-09-08 21:21:00 -0700458 doc->SaveFile( "./resources/out/pretty.xml" );
459 doc->SaveFile( "./resources/out/compact.xml", true );
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800460 delete doc;
461 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800462 {
463 // Test: Dream
464 // XML1 : 1,187,569 bytes in 31,209 allocations
465 // XML2 : 469,073 bytes in 323 allocations
466 //int newStart = gNew;
467 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300468 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800469
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400470 doc.SaveFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800471 doc.PrintError();
472
473 XMLTest( "Dream", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400474 doc.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800475 XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false );
476 XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
477 doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
478 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400479 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800480 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400481 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800482
483 XMLDocument doc2;
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400484 doc2.LoadFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800485 XMLTest( "Dream-out", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400486 doc2.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800487 XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false );
488 XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
489 doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
490 XMLTest( "Dream-out", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400491 doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800492
493 //gNewTotal = gNew - newStart;
494 }
Lee Thomason6f381b72012-03-02 12:59:39 -0800495
496
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800497 {
498 const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
499 "<passages count=\"006\" formatversion=\"20020620\">\n"
500 " <wrong error>\n"
501 "</passages>";
502
503 XMLDocument doc;
504 doc.Parse( error );
Lee Thomason2fa81722012-11-09 12:37:46 -0800505 XMLTest( "Bad XML", doc.ErrorID(), XML_ERROR_PARSING_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800506 }
507
508 {
509 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
510
511 XMLDocument doc;
512 doc.Parse( str );
513
514 XMLElement* ele = doc.FirstChildElement();
515
516 int iVal, result;
517 double dVal;
518
519 result = ele->QueryDoubleAttribute( "attr0", &dVal );
Lee Thomason85536252016-06-04 19:10:53 -0700520 XMLTest( "Query attribute: int as double", result, (int)XML_SUCCESS);
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800521 XMLTest( "Query attribute: int as double", (int)dVal, 1 );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700522 XMLTest( "Query attribute: int as double", (int)ele->DoubleAttribute("attr0"), 1);
523
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800524 result = ele->QueryDoubleAttribute( "attr1", &dVal );
Lee Thomason85536252016-06-04 19:10:53 -0700525 XMLTest( "Query attribute: double as double", result, (int)XML_SUCCESS);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700526 XMLTest( "Query attribute: double as double", dVal, 2.0 );
527 XMLTest( "Query attribute: double as double", ele->DoubleAttribute("attr1"), 2.0 );
528
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800529 result = ele->QueryIntAttribute( "attr1", &iVal );
Lee Thomason85536252016-06-04 19:10:53 -0700530 XMLTest( "Query attribute: double as int", result, (int)XML_SUCCESS);
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800531 XMLTest( "Query attribute: double as int", iVal, 2 );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700532
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800533 result = ele->QueryIntAttribute( "attr2", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700534 XMLTest( "Query attribute: not a number", result, (int)XML_WRONG_ATTRIBUTE_TYPE );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700535 XMLTest( "Query attribute: not a number", ele->DoubleAttribute("attr2", 4.0), 4.0 );
536
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800537 result = ele->QueryIntAttribute( "bar", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700538 XMLTest( "Query attribute: does not exist", result, (int)XML_NO_ATTRIBUTE );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700539 XMLTest( "Query attribute: does not exist", ele->BoolAttribute("bar", true), true );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800540 }
541
542 {
543 const char* str = "<doc/>";
544
545 XMLDocument doc;
546 doc.Parse( str );
547
548 XMLElement* ele = doc.FirstChildElement();
549
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800550 int iVal, iVal2;
551 double dVal, dVal2;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800552
553 ele->SetAttribute( "str", "strValue" );
554 ele->SetAttribute( "int", 1 );
555 ele->SetAttribute( "double", -1.0 );
556
557 const char* cStr = ele->Attribute( "str" );
558 ele->QueryIntAttribute( "int", &iVal );
559 ele->QueryDoubleAttribute( "double", &dVal );
560
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800561 ele->QueryAttribute( "int", &iVal2 );
562 ele->QueryAttribute( "double", &dVal2 );
563
Lee Thomason8ba7f7d2012-03-24 13:04:04 -0700564 XMLTest( "Attribute match test", ele->Attribute( "str", "strValue" ), "strValue" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800565 XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
566 XMLTest( "Attribute round trip. int.", 1, iVal );
567 XMLTest( "Attribute round trip. double.", -1, (int)dVal );
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800568 XMLTest( "Alternate query", true, iVal == iVal2 );
569 XMLTest( "Alternate query", true, dVal == dVal2 );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700570 XMLTest( "Alternate query", true, iVal == ele->IntAttribute("int") );
571 XMLTest( "Alternate query", true, dVal == ele->DoubleAttribute("double") );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800572 }
573
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800574 {
575 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300576 doc.LoadFile( "resources/utf8test.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800577
578 // Get the attribute "value" from the "Russian" element and check it.
579 XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700580 const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800581 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
582
583 XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
584
585 const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U,
586 0xd1U, 0x81U, 0xd1U, 0x81U,
587 0xd0U, 0xbaU, 0xd0U, 0xb8U,
588 0xd0U, 0xb9U, 0 };
589 const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
590
591 XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
592 XMLTest( "UTF-8: Browsing russian element name.",
593 russianText,
594 text->Value() );
595
596 // Now try for a round trip.
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400597 doc.SaveFile( "resources/out/utf8testout.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800598
599 // Check the round trip.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800600 int okay = 0;
601
Thomas Roßa6dd8c62012-07-26 20:42:18 +0200602 FILE* saved = fopen( "resources/out/utf8testout.xml", "r" );
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300603 FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800604
605 if ( saved && verify )
606 {
607 okay = 1;
PKEuSc28ba3a2012-07-16 03:08:47 -0700608 char verifyBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800609 while ( fgets( verifyBuf, 256, verify ) )
610 {
PKEuSc28ba3a2012-07-16 03:08:47 -0700611 char savedBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800612 fgets( savedBuf, 256, saved );
613 NullLineEndings( verifyBuf );
614 NullLineEndings( savedBuf );
615
616 if ( strcmp( verifyBuf, savedBuf ) )
617 {
618 printf( "verify:%s<\n", verifyBuf );
619 printf( "saved :%s<\n", savedBuf );
620 okay = 0;
621 break;
622 }
623 }
624 }
625 if ( saved )
626 fclose( saved );
627 if ( verify )
628 fclose( verify );
629 XMLTest( "UTF-8: Verified multi-language round trip.", 1, okay );
630 }
631
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800632 // --------GetText()-----------
633 {
634 const char* str = "<foo>This is text</foo>";
635 XMLDocument doc;
636 doc.Parse( str );
637 const XMLElement* element = doc.RootElement();
638
639 XMLTest( "GetText() normal use.", "This is text", element->GetText() );
640
641 str = "<foo><b>This is text</b></foo>";
642 doc.Parse( str );
643 element = doc.RootElement();
644
645 XMLTest( "GetText() contained element.", element->GetText() == 0, true );
646 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800647
Lee Thomasond6277762012-02-22 16:00:12 -0800648
Uli Kusterer321072e2014-01-21 01:57:38 +0100649 // --------SetText()-----------
650 {
651 const char* str = "<foo></foo>";
652 XMLDocument doc;
653 doc.Parse( str );
654 XMLElement* element = doc.RootElement();
655
Lee Thomason9c0678a2014-01-24 10:18:27 -0800656 element->SetText("darkness.");
657 XMLTest( "SetText() normal use (open/close).", "darkness.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100658
Lee Thomason9c0678a2014-01-24 10:18:27 -0800659 element->SetText("blue flame.");
660 XMLTest( "SetText() replace.", "blue flame.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100661
662 str = "<foo/>";
663 doc.Parse( str );
664 element = doc.RootElement();
665
Lee Thomason9c0678a2014-01-24 10:18:27 -0800666 element->SetText("The driver");
667 XMLTest( "SetText() normal use. (self-closing)", "The driver", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100668
Lee Thomason9c0678a2014-01-24 10:18:27 -0800669 element->SetText("<b>horses</b>");
670 XMLTest( "SetText() replace with tag-like text.", "<b>horses</b>", element->GetText() );
671 //doc.Print();
Uli Kusterer321072e2014-01-21 01:57:38 +0100672
673 str = "<foo><bar>Text in nested element</bar></foo>";
674 doc.Parse( str );
675 element = doc.RootElement();
676
Lee Thomason9c0678a2014-01-24 10:18:27 -0800677 element->SetText("wolves");
678 XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800679
680 str = "<foo/>";
681 doc.Parse( str );
682 element = doc.RootElement();
683
684 element->SetText( "str" );
685 XMLTest( "SetText types", "str", element->GetText() );
686
687 element->SetText( 1 );
688 XMLTest( "SetText types", "1", element->GetText() );
689
690 element->SetText( 1U );
691 XMLTest( "SetText types", "1", element->GetText() );
692
693 element->SetText( true );
Doruk Turak1f212f32016-08-28 20:54:17 +0200694 XMLTest( "SetText types", "true", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800695
696 element->SetText( 1.5f );
697 XMLTest( "SetText types", "1.5", element->GetText() );
698
699 element->SetText( 1.5 );
700 XMLTest( "SetText types", "1.5", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100701 }
702
Lee Thomason51c12712016-06-04 20:18:49 -0700703 // ---------- Attributes ---------
704 {
705 static const int64_t BIG = -123456789012345678;
706 XMLDocument doc;
707 XMLElement* element = doc.NewElement("element");
708 doc.InsertFirstChild(element);
709
710 {
711 element->SetAttribute("attrib", int(-100));
712 int v = 0;
713 element->QueryIntAttribute("attrib", &v);
714 XMLTest("Attribute: int", -100, v, true);
715 element->QueryAttribute("attrib", &v);
716 XMLTest("Attribute: int", -100, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700717 XMLTest("Attribute: int", -100, element->IntAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700718 }
719 {
720 element->SetAttribute("attrib", unsigned(100));
721 unsigned v = 0;
722 element->QueryUnsignedAttribute("attrib", &v);
723 XMLTest("Attribute: unsigned", unsigned(100), v, true);
724 element->QueryAttribute("attrib", &v);
725 XMLTest("Attribute: unsigned", unsigned(100), v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700726 XMLTest("Attribute: unsigned", unsigned(100), element->UnsignedAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700727 }
728 {
729 element->SetAttribute("attrib", BIG);
730 int64_t v = 0;
731 element->QueryInt64Attribute("attrib", &v);
732 XMLTest("Attribute: int64_t", BIG, v, true);
733 element->QueryAttribute("attrib", &v);
734 XMLTest("Attribute: int64_t", BIG, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700735 XMLTest("Attribute: int64_t", BIG, element->Int64Attribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700736 }
737 {
738 element->SetAttribute("attrib", true);
739 bool v = false;
740 element->QueryBoolAttribute("attrib", &v);
741 XMLTest("Attribute: bool", true, v, true);
742 element->QueryAttribute("attrib", &v);
743 XMLTest("Attribute: bool", true, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700744 XMLTest("Attribute: bool", true, element->BoolAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700745 }
746 {
747 element->SetAttribute("attrib", 100.0);
748 double v = 0;
749 element->QueryDoubleAttribute("attrib", &v);
750 XMLTest("Attribute: double", 100.0, v, true);
751 element->QueryAttribute("attrib", &v);
752 XMLTest("Attribute: double", 100.0, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700753 XMLTest("Attribute: double", 100.0, element->DoubleAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700754 }
755 {
756 element->SetAttribute("attrib", 100.0f);
757 float v = 0;
758 element->QueryFloatAttribute("attrib", &v);
759 XMLTest("Attribute: float", 100.0f, v, true);
760 element->QueryAttribute("attrib", &v);
761 XMLTest("Attribute: float", 100.0f, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700762 XMLTest("Attribute: float", 100.0f, element->FloatAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700763 }
764 {
765 element->SetText(BIG);
766 int64_t v = 0;
767 element->QueryInt64Text(&v);
768 XMLTest("Element: int64_t", BIG, v, true);
769 }
770 }
771
772 // ---------- XMLPrinter stream mode ------
773 {
774 {
775 FILE* printerfp = fopen("resources/printer.xml", "w");
776 XMLPrinter printer(printerfp);
777 printer.OpenElement("foo");
778 printer.PushAttribute("attrib-text", "text");
779 printer.PushAttribute("attrib-int", int(1));
780 printer.PushAttribute("attrib-unsigned", unsigned(2));
781 printer.PushAttribute("attrib-int64", int64_t(3));
782 printer.PushAttribute("attrib-bool", true);
783 printer.PushAttribute("attrib-double", 4.0);
784 printer.CloseElement();
785 fclose(printerfp);
786 }
787 {
788 XMLDocument doc;
789 doc.LoadFile("resources/printer.xml");
790 XMLTest("XMLPrinter Stream mode: load", doc.ErrorID(), XML_SUCCESS, true);
791
792 const XMLDocument& cdoc = doc;
793
794 const XMLAttribute* attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-text");
795 XMLTest("attrib-text", "text", attrib->Value(), true);
796 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int");
797 XMLTest("attrib-int", int(1), attrib->IntValue(), true);
798 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-unsigned");
799 XMLTest("attrib-unsigned", unsigned(2), attrib->UnsignedValue(), true);
800 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int64");
801 XMLTest("attrib-int64", int64_t(3), attrib->Int64Value(), true);
802 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-bool");
803 XMLTest("attrib-bool", true, attrib->BoolValue(), true);
804 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-double");
805 XMLTest("attrib-double", 4.0, attrib->DoubleValue(), true);
806 }
807
808 }
809
Uli Kusterer321072e2014-01-21 01:57:38 +0100810
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800811 // ---------- CDATA ---------------
812 {
813 const char* str = "<xmlElement>"
814 "<![CDATA["
815 "I am > the rules!\n"
816 "...since I make symbolic puns"
817 "]]>"
818 "</xmlElement>";
819 XMLDocument doc;
820 doc.Parse( str );
821 doc.Print();
Lee Thomasond6277762012-02-22 16:00:12 -0800822
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700823 XMLTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800824 "I am > the rules!\n...since I make symbolic puns",
Lee Thomasond6277762012-02-22 16:00:12 -0800825 false );
826 }
827
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800828 // ----------- CDATA -------------
829 {
830 const char* str = "<xmlElement>"
831 "<![CDATA["
832 "<b>I am > the rules!</b>\n"
833 "...since I make symbolic puns"
834 "]]>"
835 "</xmlElement>";
836 XMLDocument doc;
837 doc.Parse( str );
838 doc.Print();
839
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700840 XMLTest( "CDATA parse. [ tixml1:1480107 ]", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800841 "<b>I am > the rules!</b>\n...since I make symbolic puns",
842 false );
843 }
844
845 // InsertAfterChild causes crash.
846 {
847 // InsertBeforeChild and InsertAfterChild causes crash.
848 XMLDocument doc;
849 XMLElement* parent = doc.NewElement( "Parent" );
850 doc.InsertFirstChild( parent );
851
852 XMLElement* childText0 = doc.NewElement( "childText0" );
853 XMLElement* childText1 = doc.NewElement( "childText1" );
854
855 XMLNode* childNode0 = parent->InsertEndChild( childText0 );
856 XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
857
858 XMLTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent->LastChild() ), true );
859 }
Lee Thomasond6277762012-02-22 16:00:12 -0800860
861 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800862 // Entities not being written correctly.
863 // From Lynn Allen
Lee Thomasond6277762012-02-22 16:00:12 -0800864
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800865 const char* passages =
866 "<?xml version=\"1.0\" standalone=\"no\" ?>"
867 "<passages count=\"006\" formatversion=\"20020620\">"
868 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
869 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
870 "</passages>";
Lee Thomasond6277762012-02-22 16:00:12 -0800871
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800872 XMLDocument doc;
873 doc.Parse( passages );
874 XMLElement* psg = doc.RootElement()->FirstChildElement();
875 const char* context = psg->Attribute( "context" );
876 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 -0800877
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800878 XMLTest( "Entity transformation: read. ", expected, context, true );
Lee Thomasond6277762012-02-22 16:00:12 -0800879
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400880 FILE* textfile = fopen( "resources/out/textfile.txt", "w" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800881 if ( textfile )
882 {
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800883 XMLPrinter streamer( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800884 psg->Accept( &streamer );
885 fclose( textfile );
886 }
Thomas Roß0922b732012-09-23 16:31:22 +0200887
888 textfile = fopen( "resources/out/textfile.txt", "r" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800889 TIXMLASSERT( textfile );
890 if ( textfile )
891 {
892 char buf[ 1024 ];
893 fgets( buf, 1024, textfile );
894 XMLTest( "Entity transformation: write. ",
895 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
896 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
897 buf, false );
PKEuSc28ba3a2012-07-16 03:08:47 -0700898 fclose( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800899 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800900 }
901
902 {
Lee Thomason6f381b72012-03-02 12:59:39 -0800903 // Suppress entities.
904 const char* passages =
905 "<?xml version=\"1.0\" standalone=\"no\" ?>"
906 "<passages count=\"006\" formatversion=\"20020620\">"
907 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
908 "</passages>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700909
Lee Thomason6f381b72012-03-02 12:59:39 -0800910 XMLDocument doc( false );
911 doc.Parse( passages );
912
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700913 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ),
Lee Thomason6f381b72012-03-02 12:59:39 -0800914 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;." );
915 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value(),
916 "Crazy &ttk;" );
917 doc.Print();
918 }
919
920 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400921 const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800922
923 XMLDocument doc;
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400924 doc.Parse( test );
925 XMLTest( "dot in names", doc.Error(), false );
926 XMLTest( "dot in names", doc.FirstChildElement()->Name(), "a.elem" );
927 XMLTest( "dot in names", doc.FirstChildElement()->Attribute( "xmi.version" ), "2.0" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800928 }
929
930 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400931 const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800932
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400933 XMLDocument doc;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800934 doc.Parse( test );
935
936 XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
937 XMLTest( "Entity with one digit.",
938 text->Value(), "1.1 Start easy ignore fin thickness\n",
939 false );
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400940 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800941
942 {
943 // DOCTYPE not preserved (950171)
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700944 //
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800945 const char* doctype =
946 "<?xml version=\"1.0\" ?>"
947 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
948 "<!ELEMENT title (#PCDATA)>"
949 "<!ELEMENT books (title,authors)>"
950 "<element />";
951
952 XMLDocument doc;
953 doc.Parse( doctype );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400954 doc.SaveFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800955 doc.DeleteChild( doc.RootElement() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400956 doc.LoadFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800957 doc.Print();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700958
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800959 const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
960 XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
961
962 }
963
964 {
965 // Comments do not stream out correctly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700966 const char* doctype =
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800967 "<!-- Somewhat<evil> -->";
968 XMLDocument doc;
969 doc.Parse( doctype );
970
971 XMLComment* comment = doc.FirstChild()->ToComment();
972
973 XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
974 }
975 {
976 // Double attributes
977 const char* doctype = "<element attr='red' attr='blue' />";
978
979 XMLDocument doc;
980 doc.Parse( doctype );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700981
Lee Thomason2fa81722012-11-09 12:37:46 -0800982 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 -0800983 doc.PrintError();
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800984 }
985
986 {
987 // Embedded null in stream.
988 const char* doctype = "<element att\0r='red' attr='blue' />";
989
990 XMLDocument doc;
991 doc.Parse( doctype );
992 XMLTest( "Embedded null throws error.", true, doc.Error() );
993 }
994
995 {
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700996 // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
Dmitry-Me588bb8d2014-12-25 18:59:18 +0300997 const char* str = "";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800998 XMLDocument doc;
999 doc.Parse( str );
Lee Thomason2fa81722012-11-09 12:37:46 -08001000 XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001001 }
1002
1003 {
Dmitry-Me588bb8d2014-12-25 18:59:18 +03001004 // Documents with all whitespaces should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
1005 const char* str = " ";
1006 XMLDocument doc;
1007 doc.Parse( str );
1008 XMLTest( "All whitespaces document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
1009 }
1010
1011 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001012 // Low entities
1013 XMLDocument doc;
1014 doc.Parse( "<test>&#x0e;</test>" );
1015 const char result[] = { 0x0e, 0 };
1016 XMLTest( "Low entities.", doc.FirstChildElement()->GetText(), result );
1017 doc.Print();
1018 }
1019
1020 {
1021 // Attribute values with trailing quotes not handled correctly
1022 XMLDocument doc;
1023 doc.Parse( "<foo attribute=bar\" />" );
1024 XMLTest( "Throw error with bad end quotes.", doc.Error(), true );
1025 }
1026
1027 {
1028 // [ 1663758 ] Failure to report error on bad XML
1029 XMLDocument xml;
1030 xml.Parse("<x>");
1031 XMLTest("Missing end tag at end of input", xml.Error(), true);
1032 xml.Parse("<x> ");
1033 XMLTest("Missing end tag with trailing whitespace", xml.Error(), true);
1034 xml.Parse("<x></y>");
Lee Thomason2fa81722012-11-09 12:37:46 -08001035 XMLTest("Mismatched tags", xml.ErrorID(), XML_ERROR_MISMATCHED_ELEMENT);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001036 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001037
1038
1039 {
1040 // [ 1475201 ] TinyXML parses entities in comments
1041 XMLDocument xml;
1042 xml.Parse("<!-- declarations for <head> & <body> -->"
1043 "<!-- far &amp; away -->" );
1044
1045 XMLNode* e0 = xml.FirstChild();
1046 XMLNode* e1 = e0->NextSibling();
1047 XMLComment* c0 = e0->ToComment();
1048 XMLComment* c1 = e1->ToComment();
1049
1050 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
1051 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
1052 }
1053
1054 {
1055 XMLDocument xml;
1056 xml.Parse( "<Parent>"
1057 "<child1 att=''/>"
1058 "<!-- With this comment, child2 will not be parsed! -->"
1059 "<child2 att=''/>"
1060 "</Parent>" );
1061 xml.Print();
1062
1063 int count = 0;
1064
1065 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
1066 ele;
1067 ele = ele->NextSibling() )
1068 {
1069 ++count;
1070 }
1071
1072 XMLTest( "Comments iterate correctly.", 3, count );
1073 }
1074
1075 {
1076 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
1077 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
1078 buf[60] = 239;
1079 buf[61] = 0;
1080
1081 XMLDocument doc;
1082 doc.Parse( (const char*)buf);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001083 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001084
1085
1086 {
1087 // bug 1827248 Error while parsing a little bit malformed file
1088 // Actually not malformed - should work.
1089 XMLDocument xml;
1090 xml.Parse( "<attributelist> </attributelist >" );
1091 XMLTest( "Handle end tag whitespace", false, xml.Error() );
1092 }
1093
1094 {
1095 // This one must not result in an infinite loop
1096 XMLDocument xml;
1097 xml.Parse( "<infinite>loop" );
1098 XMLTest( "Infinite loop test.", true, true );
1099 }
1100#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001101 {
1102 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
1103 XMLDocument doc;
1104 doc.Parse( pub );
1105
1106 XMLDocument clone;
1107 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
1108 XMLNode* copy = node->ShallowClone( &clone );
1109 clone.InsertEndChild( copy );
1110 }
1111
1112 clone.Print();
1113
1114 int count=0;
1115 const XMLNode* a=clone.FirstChild();
1116 const XMLNode* b=doc.FirstChild();
1117 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
1118 ++count;
1119 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
1120 }
1121 XMLTest( "Clone and Equal", 4, count );
1122 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001123
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001124 {
1125 // This shouldn't crash.
1126 XMLDocument doc;
Lee Thomason85536252016-06-04 19:10:53 -07001127 if(XML_SUCCESS != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001128 {
1129 doc.PrintError();
1130 }
1131 XMLTest( "Error in snprinf handling.", true, doc.Error() );
1132 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001133
Lee Thomason5e3803c2012-04-16 08:57:05 -07001134 {
1135 // Attribute ordering.
1136 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
1137 XMLDocument doc;
1138 doc.Parse( xml );
1139 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001140
Lee Thomason5e3803c2012-04-16 08:57:05 -07001141 const XMLAttribute* a = ele->FirstAttribute();
1142 XMLTest( "Attribute order", "1", a->Value() );
1143 a = a->Next();
1144 XMLTest( "Attribute order", "2", a->Value() );
1145 a = a->Next();
1146 XMLTest( "Attribute order", "3", a->Value() );
1147 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001148
Lee Thomason5e3803c2012-04-16 08:57:05 -07001149 ele->DeleteAttribute( "attrib2" );
1150 a = ele->FirstAttribute();
1151 XMLTest( "Attribute order", "1", a->Value() );
1152 a = a->Next();
1153 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001154
Lee Thomason5e3803c2012-04-16 08:57:05 -07001155 ele->DeleteAttribute( "attrib1" );
1156 ele->DeleteAttribute( "attrib3" );
1157 XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
1158 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001159
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001160 {
1161 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -07001162 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
1163 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
1164 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
1165 XMLDocument doc0;
1166 doc0.Parse( xml0 );
1167 XMLDocument doc1;
1168 doc1.Parse( xml1 );
1169 XMLDocument doc2;
1170 doc2.Parse( xml2 );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001171
Lee Thomason78a773d2012-07-02 10:10:19 -07001172 XMLElement* ele = 0;
1173 ele = doc0.FirstChildElement();
1174 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
1175 ele = doc1.FirstChildElement();
1176 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
1177 ele = doc2.FirstChildElement();
1178 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001179 }
1180
1181 {
1182 // Make sure we don't go into an infinite loop.
1183 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
1184 XMLDocument doc;
1185 doc.Parse( xml );
1186 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
1187 XMLElement* ele1 = ele0->NextSiblingElement();
1188 bool equal = ele0->ShallowEqual( ele1 );
1189
1190 XMLTest( "Infinite loop in shallow equal.", true, equal );
1191 }
1192
Lee Thomason5708f812012-03-28 17:46:41 -07001193 // -------- Handles ------------
1194 {
1195 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1196 XMLDocument doc;
1197 doc.Parse( xml );
Lee Thomason5708f812012-03-28 17:46:41 -07001198
1199 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
1200 XMLTest( "Handle, success, mutable", ele->Value(), "sub" );
1201
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001202 XMLHandle docH( doc );
1203 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001204 XMLTest( "Handle, dne, mutable", false, ele != 0 );
Lee Thomason5708f812012-03-28 17:46:41 -07001205 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001206
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001207 {
1208 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1209 XMLDocument doc;
1210 doc.Parse( xml );
1211 XMLConstHandle docH( doc );
1212
1213 const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
1214 XMLTest( "Handle, success, const", ele->Value(), "sub" );
1215
1216 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001217 XMLTest( "Handle, dne, const", false, ele != 0 );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001218 }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001219 {
1220 // Default Declaration & BOM
1221 XMLDocument doc;
1222 doc.InsertEndChild( doc.NewDeclaration() );
1223 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001224
Lee Thomasonf68c4382012-04-28 14:37:11 -07001225 XMLPrinter printer;
1226 doc.Print( &printer );
1227
1228 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1229 XMLTest( "BOM and default declaration", printer.CStr(), result, false );
Lee Thomason (grinliz)48ea0bc2012-05-26 14:41:14 -07001230 XMLTest( "CStrSize", printer.CStrSize(), 42, false );
Lee Thomasonf68c4382012-04-28 14:37:11 -07001231 }
Lee Thomason21be8822012-07-15 17:27:22 -07001232 {
1233 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1234 XMLDocument doc;
1235 doc.Parse( xml );
1236 XMLTest( "Ill formed XML", true, doc.Error() );
1237 }
1238
1239 // QueryXYZText
1240 {
1241 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1242 XMLDocument doc;
1243 doc.Parse( xml );
1244
1245 const XMLElement* pointElement = doc.RootElement();
1246
1247 int intValue = 0;
1248 unsigned unsignedValue = 0;
1249 float floatValue = 0;
1250 double doubleValue = 0;
1251 bool boolValue = false;
1252
1253 pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1254 pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1255 pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1256 pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1257 pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1258
1259
1260 XMLTest( "QueryIntText", intValue, 1, false );
1261 XMLTest( "QueryUnsignedText", unsignedValue, (unsigned)1, false );
1262 XMLTest( "QueryFloatText", floatValue, 1.2f, false );
1263 XMLTest( "QueryDoubleText", doubleValue, 1.2, false );
1264 XMLTest( "QueryBoolText", boolValue, true, false );
1265 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001266
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001267 {
1268 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1269 XMLDocument doc;
1270 doc.Parse( xml );
1271 XMLTest( "Non-alpha element lead letter parses.", doc.Error(), false );
1272 }
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001273
1274 {
1275 const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1276 XMLDocument doc;
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001277 doc.Parse( xml );
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001278 XMLTest("Non-alpha attribute lead character parses.", doc.Error(), false);
1279 }
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001280
1281 {
1282 const char* xml = "<3lement></3lement>";
1283 XMLDocument doc;
1284 doc.Parse( xml );
1285 XMLTest("Element names with lead digit fail to parse.", doc.Error(), true);
1286 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -07001287
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001288 {
1289 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1290 XMLDocument doc;
1291 doc.Parse( xml, 10 );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001292 XMLTest( "Set length of incoming data", doc.Error(), false );
1293 }
1294
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001295 {
1296 XMLDocument doc;
Dmitry-Me48b5df02015-04-06 18:20:25 +03001297 XMLTest( "Document is initially empty", doc.NoChildren(), true );
1298 doc.Clear();
1299 XMLTest( "Empty is empty after Clear()", doc.NoChildren(), true );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001300 doc.LoadFile( "resources/dream.xml" );
Dmitry-Meaaa4cea2015-02-06 16:00:46 +03001301 XMLTest( "Document has something to Clear()", doc.NoChildren(), false );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001302 doc.Clear();
1303 XMLTest( "Document Clear()'s", doc.NoChildren(), true );
1304 }
1305
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001306 // ----------- Whitespace ------------
1307 {
1308 const char* xml = "<element>"
1309 "<a> This \nis &apos; text &apos; </a>"
1310 "<b> This is &apos; text &apos; \n</b>"
1311 "<c>This is &apos; \n\n text &apos;</c>"
1312 "</element>";
1313 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1314 doc.Parse( xml );
1315
1316 const XMLElement* element = doc.FirstChildElement();
1317 for( const XMLElement* parent = element->FirstChildElement();
1318 parent;
1319 parent = parent->NextSiblingElement() )
1320 {
1321 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1322 }
1323 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001324
Lee Thomasonae9ab072012-10-24 10:17:53 -07001325#if 0
1326 {
1327 // Passes if assert doesn't fire.
1328 XMLDocument xmlDoc;
1329
1330 xmlDoc.NewDeclaration();
1331 xmlDoc.NewComment("Configuration file");
1332
1333 XMLElement *root = xmlDoc.NewElement("settings");
1334 root->SetAttribute("version", 2);
1335 }
1336#endif
1337
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001338 {
1339 const char* xml = "<element> </element>";
1340 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1341 doc.Parse( xml );
1342 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1343 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001344
Lee Thomason5b0a6772012-11-19 13:54:42 -08001345 {
1346 // An assert should not fire.
1347 const char* xml = "<element/>";
1348 XMLDocument doc;
1349 doc.Parse( xml );
1350 XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope.
1351 XMLTest( "Tracking unused elements", true, ele != 0, false );
1352 }
1353
Lee Thomasona6412ac2012-12-13 15:39:11 -08001354
1355 {
1356 const char* xml = "<parent><child>abc</child></parent>";
1357 XMLDocument doc;
1358 doc.Parse( xml );
1359 XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
1360
1361 XMLPrinter printer;
1362 ele->Accept( &printer );
1363 XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1364 }
1365
1366
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001367 {
1368 XMLDocument doc;
1369 XMLError error = doc.LoadFile( "resources/empty.xml" );
1370 XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
Lee Thomason331596e2014-09-11 14:56:43 -07001371 XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() );
Lee Thomasonc7556672014-09-14 12:39:42 -07001372 doc.PrintError();
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001373 }
1374
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001375 {
1376 // BOM preservation
1377 static const char* xml_bom_preservation = "\xef\xbb\xbf<element/>\n";
1378 {
1379 XMLDocument doc;
Lee Thomason85536252016-06-04 19:10:53 -07001380 XMLTest( "BOM preservation (parse)", XML_SUCCESS, doc.Parse( xml_bom_preservation ), false );
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001381 XMLPrinter printer;
1382 doc.Print( &printer );
1383
1384 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1385 doc.SaveFile( "resources/bomtest.xml" );
1386 }
1387 {
1388 XMLDocument doc;
1389 doc.LoadFile( "resources/bomtest.xml" );
1390 XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
1391
1392 XMLPrinter printer;
1393 doc.Print( &printer );
1394 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1395 }
1396 }
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001397
Michael Daumlinged523282013-10-23 07:47:29 +02001398 {
1399 // Insertion with Removal
1400 const char* xml = "<?xml version=\"1.0\" ?>"
1401 "<root>"
1402 "<one>"
1403 "<subtree>"
1404 "<elem>element 1</elem>text<!-- comment -->"
1405 "</subtree>"
1406 "</one>"
1407 "<two/>"
1408 "</root>";
1409 const char* xmlInsideTwo = "<?xml version=\"1.0\" ?>"
1410 "<root>"
1411 "<one/>"
1412 "<two>"
1413 "<subtree>"
1414 "<elem>element 1</elem>text<!-- comment -->"
1415 "</subtree>"
1416 "</two>"
1417 "</root>";
1418 const char* xmlAfterOne = "<?xml version=\"1.0\" ?>"
1419 "<root>"
1420 "<one/>"
1421 "<subtree>"
1422 "<elem>element 1</elem>text<!-- comment -->"
1423 "</subtree>"
1424 "<two/>"
1425 "</root>";
1426 const char* xmlAfterTwo = "<?xml version=\"1.0\" ?>"
1427 "<root>"
1428 "<one/>"
1429 "<two/>"
1430 "<subtree>"
1431 "<elem>element 1</elem>text<!-- comment -->"
1432 "</subtree>"
1433 "</root>";
1434
1435 XMLDocument doc;
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001436 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001437 XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1438 XMLElement* two = doc.RootElement()->FirstChildElement("two");
1439 two->InsertFirstChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001440 XMLPrinter printer1(0, true);
1441 doc.Accept(&printer1);
1442 XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
Michael Daumlinged523282013-10-23 07:47:29 +02001443
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001444 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001445 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1446 two = doc.RootElement()->FirstChildElement("two");
1447 doc.RootElement()->InsertAfterChild(two, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001448 XMLPrinter printer2(0, true);
1449 doc.Accept(&printer2);
1450 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001451
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001452 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001453 XMLNode* one = doc.RootElement()->FirstChildElement("one");
1454 subtree = one->FirstChildElement("subtree");
1455 doc.RootElement()->InsertAfterChild(one, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001456 XMLPrinter printer3(0, true);
1457 doc.Accept(&printer3);
1458 XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001459
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001460 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001461 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1462 two = doc.RootElement()->FirstChildElement("two");
1463 doc.RootElement()->InsertEndChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001464 XMLPrinter printer4(0, true);
1465 doc.Accept(&printer4);
1466 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001467 }
1468
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001469 {
1470 const char* xml = "<svg width = \"128\" height = \"128\">"
1471 " <text> </text>"
1472 "</svg>";
1473 XMLDocument doc;
1474 doc.Parse(xml);
1475 doc.Print();
1476 }
1477
Lee Thomason92e521b2014-11-15 17:45:51 -08001478 {
1479 // Test that it doesn't crash.
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001480 const char* xml = "<?xml version=\"1.0\"?><root><sample><field0><1</field0><field1>2</field1></sample></root>";
1481 XMLDocument doc;
1482 doc.Parse(xml);
1483 doc.PrintError();
Lee Thomason92e521b2014-11-15 17:45:51 -08001484 }
1485
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001486#if 1
1487 // the question being explored is what kind of print to use:
1488 // https://github.com/leethomason/tinyxml2/issues/63
1489 {
1490 //const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
1491 const char* xml = "<element/>";
1492 XMLDocument doc;
1493 doc.Parse( xml );
1494 doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
1495 doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
1496 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
1497 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
1498 doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
1499 doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
1500
1501 doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
1502 doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
1503 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
1504 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
1505 doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
1506 doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
1507
1508 doc.Print();
1509
1510 /* The result of this test is platform, compiler, and library version dependent. :("
1511 XMLPrinter printer;
1512 doc.Print( &printer );
1513 XMLTest( "Float and double formatting.",
1514 "<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",
1515 printer.CStr(),
1516 true );
1517 */
1518 }
1519#endif
Lee Thomasonf07b9522014-10-30 13:25:12 -07001520
1521 {
1522 // Issue #184
1523 // If it doesn't assert, it passes. Caused by objects
1524 // getting created during parsing which are then
1525 // inaccessible in the memory pools.
1526 {
1527 XMLDocument doc;
1528 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1529 }
1530 {
1531 XMLDocument doc;
1532 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1533 doc.Clear();
1534 }
1535 }
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001536
1537 {
1538 // If this doesn't assert in DEBUG, all is well.
1539 tinyxml2::XMLDocument doc;
1540 tinyxml2::XMLElement *pRoot = doc.NewElement("Root");
1541 doc.DeleteNode(pRoot);
1542 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001543
Dmitry-Me8b67d742014-12-22 11:35:12 +03001544 {
1545 // Should not assert in DEBUG
1546 XMLPrinter printer;
1547 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001548
Dmitry-Me6f51c802015-03-14 13:25:03 +03001549 {
1550 // Issue 291. Should not crash
1551 const char* xml = "&#0</a>";
1552 XMLDocument doc;
1553 doc.Parse( xml );
1554
1555 XMLPrinter printer;
1556 doc.Print( &printer );
1557 }
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001558 {
1559 // Issue 299. Can print elements that are not linked in.
1560 // Will crash if issue not fixed.
1561 XMLDocument doc;
1562 XMLElement* newElement = doc.NewElement( "printme" );
1563 XMLPrinter printer;
1564 newElement->Accept( &printer );
Dmitry-Me5daa54c2015-04-08 17:45:07 +03001565 // Delete the node to avoid possible memory leak report in debug output
1566 doc.DeleteNode( newElement );
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001567 }
Lee Thomasonf6577832015-03-26 11:18:21 -07001568 {
Ant Mitchell189198f2015-03-24 16:20:36 +00001569 // Issue 302. Clear errors from LoadFile/SaveFile
1570 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001571 XMLTest( "Issue 302. Should be no error initially", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001572 doc.SaveFile( "./no/such/path/pretty.xml" );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001573 XMLTest( "Issue 302. Fail to save", "XML_ERROR_FILE_COULD_NOT_BE_OPENED", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001574 doc.SaveFile( "./resources/out/compact.xml", true );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001575 XMLTest( "Issue 302. Subsequent success in saving", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001576 }
Dmitry-Me6f51c802015-03-14 13:25:03 +03001577
Dmitry-Med9852a52015-03-25 10:17:49 +03001578 {
1579 // If a document fails to load then subsequent
1580 // successful loads should clear the error
1581 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001582 XMLTest( "Should be no error initially", false, doc.Error() );
Dmitry-Med9852a52015-03-25 10:17:49 +03001583 doc.LoadFile( "resources/no-such-file.xml" );
1584 XMLTest( "No such file - should fail", true, doc.Error() );
1585
1586 doc.LoadFile( "resources/dream.xml" );
1587 XMLTest( "Error should be cleared", false, doc.Error() );
1588 }
Sarat Addepalli8e85afa2015-05-19 09:07:03 +05301589
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301590 {
1591 // Check that declarations are parsed only as the FirstChild
Lee Thomason85492022015-05-22 11:07:45 -07001592 const char* xml0 = "<?xml version=\"1.0\" ?>"
1593 " <!-- xml version=\"1.1\" -->"
1594 "<first />";
1595 const char* xml1 = "<?xml version=\"1.0\" ?>"
1596 " <?xml version=\"1.1\" ?>"
1597 "<first />";
1598 const char* xml2 = "<first />"
1599 "<?xml version=\"1.0\" ?>";
1600 XMLDocument doc;
1601 doc.Parse(xml0);
1602 XMLTest("Test that the code changes do not affect normal parsing", doc.Error(), false);
1603 doc.Parse(xml1);
1604 XMLTest("Test that the second declaration throws an error", doc.ErrorID(), XML_ERROR_PARSING_DECLARATION);
1605 doc.Parse(xml2);
1606 XMLTest("Test that declaration after a child throws an error", doc.ErrorID(), XML_ERROR_PARSING_DECLARATION);
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301607 }
Dmitry-Med9852a52015-03-25 10:17:49 +03001608
Lee Thomason85492022015-05-22 11:07:45 -07001609 {
1610 // No matter - before or after successfully parsing a text -
1611 // calling XMLDocument::Value() causes an assert in debug.
1612 const char* validXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
1613 "<first />"
1614 "<second />";
1615 XMLDocument* doc = new XMLDocument();
1616 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1617 doc->Parse( validXml );
1618 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1619 delete doc;
1620 }
1621
Dmitry-Mea1beddf2015-05-26 16:19:21 +03001622 {
1623 XMLDocument doc;
1624 for( int i = 0; i < XML_ERROR_COUNT; i++ ) {
1625 doc.SetError( (XMLError)i, 0, 0 );
1626 doc.ErrorName();
1627 }
1628 }
1629
Lee Thomason85492022015-05-22 11:07:45 -07001630 // ----------- Performance tracking --------------
Lee Thomason6f381b72012-03-02 12:59:39 -08001631 {
1632#if defined( _MSC_VER )
1633 __int64 start, end, freq;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001634 QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
Lee Thomason6f381b72012-03-02 12:59:39 -08001635#endif
1636
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001637 FILE* perfFP = fopen("resources/dream.xml", "r");
1638 fseek(perfFP, 0, SEEK_END);
Armagetron3c21d6f2016-10-13 13:31:23 +02001639 long size = ftell(perfFP);
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001640 fseek(perfFP, 0, SEEK_SET);
Lee Thomason6f381b72012-03-02 12:59:39 -08001641
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001642 char* mem = new char[size + 1];
1643 fread(mem, size, 1, perfFP);
1644 fclose(perfFP);
Lee Thomason6f381b72012-03-02 12:59:39 -08001645 mem[size] = 0;
1646
1647#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001648 QueryPerformanceCounter((LARGE_INTEGER*)&start);
Lee Thomason6f381b72012-03-02 12:59:39 -08001649#else
1650 clock_t cstart = clock();
1651#endif
1652 static const int COUNT = 10;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001653 for (int i = 0; i < COUNT; ++i) {
Lee Thomason6f381b72012-03-02 12:59:39 -08001654 XMLDocument doc;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001655 doc.Parse(mem);
Lee Thomason6f381b72012-03-02 12:59:39 -08001656 }
1657#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001658 QueryPerformanceCounter((LARGE_INTEGER*)&end);
Lee Thomason6f381b72012-03-02 12:59:39 -08001659#else
1660 clock_t cend = clock();
1661#endif
1662
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001663 delete[] mem;
Lee Thomason6f381b72012-03-02 12:59:39 -08001664
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001665 static const char* note =
Lee Thomason6f381b72012-03-02 12:59:39 -08001666#ifdef DEBUG
1667 "DEBUG";
1668#else
1669 "Release";
1670#endif
1671
1672#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001673 printf("\nParsing %s of dream.xml: %.3f milli-seconds\n", note, 1000.0 * (double)(end - start) / ((double)freq * (double)COUNT));
Lee Thomason6f381b72012-03-02 12:59:39 -08001674#else
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001675 printf("\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart) / (double)COUNT);
Lee Thomason6f381b72012-03-02 12:59:39 -08001676#endif
1677 }
1678
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -08001679 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001680 _CrtMemCheckpoint( &endMemState );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001681
1682 _CrtMemState diffMemState;
1683 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
1684 _CrtMemDumpStatistics( &diffMemState );
1685 #endif
1686
1687 printf ("\nPass %d, Fail %d\n", gPass, gFail);
Lee Thomason (grinliz)db304252013-07-31 12:24:52 -07001688
1689 return gFail;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08001690}