blob: 3fdc0bd1955c19e9ec6d8e7be93acf02a0d07d38 [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 Thomasonaf9bce12016-07-17 22:35:52 -0700429 XMLTest("User data", 2, (int)comment->GetUserData());
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" ) );
439 int value = 10;
440 int result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value );
Lee Thomason21be8822012-07-15 17:27:22 -0700441 XMLTest( "Programmatic DOM", result, (int)XML_NO_ATTRIBUTE );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800442 XMLTest( "Programmatic DOM", value, 10 );
443
444 doc->Print();
445
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700446 {
447 XMLPrinter streamer;
448 doc->Print( &streamer );
449 printf( "%s", streamer.CStr() );
450 }
451 {
452 XMLPrinter streamer( 0, true );
453 doc->Print( &streamer );
454 XMLTest( "Compact mode", "<element><sub attrib=\"1\"/><sub/></element>", streamer.CStr(), false );
455 }
Lee Thomason (grinliz)6b8b0122012-09-08 21:21:00 -0700456 doc->SaveFile( "./resources/out/pretty.xml" );
457 doc->SaveFile( "./resources/out/compact.xml", true );
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800458 delete doc;
459 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800460 {
461 // Test: Dream
462 // XML1 : 1,187,569 bytes in 31,209 allocations
463 // XML2 : 469,073 bytes in 323 allocations
464 //int newStart = gNew;
465 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300466 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800467
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400468 doc.SaveFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800469 doc.PrintError();
470
471 XMLTest( "Dream", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400472 doc.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800473 XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false );
474 XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
475 doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
476 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400477 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800478 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
481 XMLDocument doc2;
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400482 doc2.LoadFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800483 XMLTest( "Dream-out", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400484 doc2.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800485 XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false );
486 XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
487 doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
488 XMLTest( "Dream-out", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400489 doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800490
491 //gNewTotal = gNew - newStart;
492 }
Lee Thomason6f381b72012-03-02 12:59:39 -0800493
494
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800495 {
496 const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
497 "<passages count=\"006\" formatversion=\"20020620\">\n"
498 " <wrong error>\n"
499 "</passages>";
500
501 XMLDocument doc;
502 doc.Parse( error );
Lee Thomason2fa81722012-11-09 12:37:46 -0800503 XMLTest( "Bad XML", doc.ErrorID(), XML_ERROR_PARSING_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800504 }
505
506 {
507 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
508
509 XMLDocument doc;
510 doc.Parse( str );
511
512 XMLElement* ele = doc.FirstChildElement();
513
514 int iVal, result;
515 double dVal;
516
517 result = ele->QueryDoubleAttribute( "attr0", &dVal );
Lee Thomason85536252016-06-04 19:10:53 -0700518 XMLTest( "Query attribute: int as double", result, (int)XML_SUCCESS);
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800519 XMLTest( "Query attribute: int as double", (int)dVal, 1 );
520 result = ele->QueryDoubleAttribute( "attr1", &dVal );
Lee Thomason85536252016-06-04 19:10:53 -0700521 XMLTest( "Query attribute: double as double", result, (int)XML_SUCCESS);
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800522 XMLTest( "Query attribute: double as double", (int)dVal, 2 );
523 result = ele->QueryIntAttribute( "attr1", &iVal );
Lee Thomason85536252016-06-04 19:10:53 -0700524 XMLTest( "Query attribute: double as int", result, (int)XML_SUCCESS);
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800525 XMLTest( "Query attribute: double as int", iVal, 2 );
526 result = ele->QueryIntAttribute( "attr2", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700527 XMLTest( "Query attribute: not a number", result, (int)XML_WRONG_ATTRIBUTE_TYPE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800528 result = ele->QueryIntAttribute( "bar", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700529 XMLTest( "Query attribute: does not exist", result, (int)XML_NO_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800530 }
531
532 {
533 const char* str = "<doc/>";
534
535 XMLDocument doc;
536 doc.Parse( str );
537
538 XMLElement* ele = doc.FirstChildElement();
539
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800540 int iVal, iVal2;
541 double dVal, dVal2;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800542
543 ele->SetAttribute( "str", "strValue" );
544 ele->SetAttribute( "int", 1 );
545 ele->SetAttribute( "double", -1.0 );
546
547 const char* cStr = ele->Attribute( "str" );
548 ele->QueryIntAttribute( "int", &iVal );
549 ele->QueryDoubleAttribute( "double", &dVal );
550
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800551 ele->QueryAttribute( "int", &iVal2 );
552 ele->QueryAttribute( "double", &dVal2 );
553
Lee Thomason8ba7f7d2012-03-24 13:04:04 -0700554 XMLTest( "Attribute match test", ele->Attribute( "str", "strValue" ), "strValue" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800555 XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
556 XMLTest( "Attribute round trip. int.", 1, iVal );
557 XMLTest( "Attribute round trip. double.", -1, (int)dVal );
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800558 XMLTest( "Alternate query", true, iVal == iVal2 );
559 XMLTest( "Alternate query", true, dVal == dVal2 );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800560 }
561
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800562 {
563 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300564 doc.LoadFile( "resources/utf8test.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800565
566 // Get the attribute "value" from the "Russian" element and check it.
567 XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700568 const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800569 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
570
571 XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
572
573 const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U,
574 0xd1U, 0x81U, 0xd1U, 0x81U,
575 0xd0U, 0xbaU, 0xd0U, 0xb8U,
576 0xd0U, 0xb9U, 0 };
577 const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
578
579 XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
580 XMLTest( "UTF-8: Browsing russian element name.",
581 russianText,
582 text->Value() );
583
584 // Now try for a round trip.
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400585 doc.SaveFile( "resources/out/utf8testout.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800586
587 // Check the round trip.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800588 int okay = 0;
589
Thomas Roßa6dd8c62012-07-26 20:42:18 +0200590 FILE* saved = fopen( "resources/out/utf8testout.xml", "r" );
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300591 FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800592
593 if ( saved && verify )
594 {
595 okay = 1;
PKEuSc28ba3a2012-07-16 03:08:47 -0700596 char verifyBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800597 while ( fgets( verifyBuf, 256, verify ) )
598 {
PKEuSc28ba3a2012-07-16 03:08:47 -0700599 char savedBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800600 fgets( savedBuf, 256, saved );
601 NullLineEndings( verifyBuf );
602 NullLineEndings( savedBuf );
603
604 if ( strcmp( verifyBuf, savedBuf ) )
605 {
606 printf( "verify:%s<\n", verifyBuf );
607 printf( "saved :%s<\n", savedBuf );
608 okay = 0;
609 break;
610 }
611 }
612 }
613 if ( saved )
614 fclose( saved );
615 if ( verify )
616 fclose( verify );
617 XMLTest( "UTF-8: Verified multi-language round trip.", 1, okay );
618 }
619
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800620 // --------GetText()-----------
621 {
622 const char* str = "<foo>This is text</foo>";
623 XMLDocument doc;
624 doc.Parse( str );
625 const XMLElement* element = doc.RootElement();
626
627 XMLTest( "GetText() normal use.", "This is text", element->GetText() );
628
629 str = "<foo><b>This is text</b></foo>";
630 doc.Parse( str );
631 element = doc.RootElement();
632
633 XMLTest( "GetText() contained element.", element->GetText() == 0, true );
634 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800635
Lee Thomasond6277762012-02-22 16:00:12 -0800636
Uli Kusterer321072e2014-01-21 01:57:38 +0100637 // --------SetText()-----------
638 {
639 const char* str = "<foo></foo>";
640 XMLDocument doc;
641 doc.Parse( str );
642 XMLElement* element = doc.RootElement();
643
Lee Thomason9c0678a2014-01-24 10:18:27 -0800644 element->SetText("darkness.");
645 XMLTest( "SetText() normal use (open/close).", "darkness.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100646
Lee Thomason9c0678a2014-01-24 10:18:27 -0800647 element->SetText("blue flame.");
648 XMLTest( "SetText() replace.", "blue flame.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100649
650 str = "<foo/>";
651 doc.Parse( str );
652 element = doc.RootElement();
653
Lee Thomason9c0678a2014-01-24 10:18:27 -0800654 element->SetText("The driver");
655 XMLTest( "SetText() normal use. (self-closing)", "The driver", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100656
Lee Thomason9c0678a2014-01-24 10:18:27 -0800657 element->SetText("<b>horses</b>");
658 XMLTest( "SetText() replace with tag-like text.", "<b>horses</b>", element->GetText() );
659 //doc.Print();
Uli Kusterer321072e2014-01-21 01:57:38 +0100660
661 str = "<foo><bar>Text in nested element</bar></foo>";
662 doc.Parse( str );
663 element = doc.RootElement();
664
Lee Thomason9c0678a2014-01-24 10:18:27 -0800665 element->SetText("wolves");
666 XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800667
668 str = "<foo/>";
669 doc.Parse( str );
670 element = doc.RootElement();
671
672 element->SetText( "str" );
673 XMLTest( "SetText types", "str", element->GetText() );
674
675 element->SetText( 1 );
676 XMLTest( "SetText types", "1", element->GetText() );
677
678 element->SetText( 1U );
679 XMLTest( "SetText types", "1", element->GetText() );
680
681 element->SetText( true );
682 XMLTest( "SetText types", "1", element->GetText() ); // TODO: should be 'true'?
683
684 element->SetText( 1.5f );
685 XMLTest( "SetText types", "1.5", element->GetText() );
686
687 element->SetText( 1.5 );
688 XMLTest( "SetText types", "1.5", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100689 }
690
Lee Thomason51c12712016-06-04 20:18:49 -0700691 // ---------- Attributes ---------
692 {
693 static const int64_t BIG = -123456789012345678;
694 XMLDocument doc;
695 XMLElement* element = doc.NewElement("element");
696 doc.InsertFirstChild(element);
697
698 {
699 element->SetAttribute("attrib", int(-100));
700 int v = 0;
701 element->QueryIntAttribute("attrib", &v);
702 XMLTest("Attribute: int", -100, v, true);
703 element->QueryAttribute("attrib", &v);
704 XMLTest("Attribute: int", -100, v, true);
705 }
706 {
707 element->SetAttribute("attrib", unsigned(100));
708 unsigned v = 0;
709 element->QueryUnsignedAttribute("attrib", &v);
710 XMLTest("Attribute: unsigned", unsigned(100), v, true);
711 element->QueryAttribute("attrib", &v);
712 XMLTest("Attribute: unsigned", unsigned(100), v, true);
713 }
714 {
715 element->SetAttribute("attrib", BIG);
716 int64_t v = 0;
717 element->QueryInt64Attribute("attrib", &v);
718 XMLTest("Attribute: int64_t", BIG, v, true);
719 element->QueryAttribute("attrib", &v);
720 XMLTest("Attribute: int64_t", BIG, v, true);
721 }
722 {
723 element->SetAttribute("attrib", true);
724 bool v = false;
725 element->QueryBoolAttribute("attrib", &v);
726 XMLTest("Attribute: bool", true, v, true);
727 element->QueryAttribute("attrib", &v);
728 XMLTest("Attribute: bool", true, v, true);
729 }
730 {
731 element->SetAttribute("attrib", 100.0);
732 double v = 0;
733 element->QueryDoubleAttribute("attrib", &v);
734 XMLTest("Attribute: double", 100.0, v, true);
735 element->QueryAttribute("attrib", &v);
736 XMLTest("Attribute: double", 100.0, v, true);
737 }
738 {
739 element->SetAttribute("attrib", 100.0f);
740 float v = 0;
741 element->QueryFloatAttribute("attrib", &v);
742 XMLTest("Attribute: float", 100.0f, v, true);
743 element->QueryAttribute("attrib", &v);
744 XMLTest("Attribute: float", 100.0f, v, true);
745 }
746 {
747 element->SetText(BIG);
748 int64_t v = 0;
749 element->QueryInt64Text(&v);
750 XMLTest("Element: int64_t", BIG, v, true);
751 }
752 }
753
754 // ---------- XMLPrinter stream mode ------
755 {
756 {
757 FILE* printerfp = fopen("resources/printer.xml", "w");
758 XMLPrinter printer(printerfp);
759 printer.OpenElement("foo");
760 printer.PushAttribute("attrib-text", "text");
761 printer.PushAttribute("attrib-int", int(1));
762 printer.PushAttribute("attrib-unsigned", unsigned(2));
763 printer.PushAttribute("attrib-int64", int64_t(3));
764 printer.PushAttribute("attrib-bool", true);
765 printer.PushAttribute("attrib-double", 4.0);
766 printer.CloseElement();
767 fclose(printerfp);
768 }
769 {
770 XMLDocument doc;
771 doc.LoadFile("resources/printer.xml");
772 XMLTest("XMLPrinter Stream mode: load", doc.ErrorID(), XML_SUCCESS, true);
773
774 const XMLDocument& cdoc = doc;
775
776 const XMLAttribute* attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-text");
777 XMLTest("attrib-text", "text", attrib->Value(), true);
778 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int");
779 XMLTest("attrib-int", int(1), attrib->IntValue(), true);
780 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-unsigned");
781 XMLTest("attrib-unsigned", unsigned(2), attrib->UnsignedValue(), true);
782 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int64");
783 XMLTest("attrib-int64", int64_t(3), attrib->Int64Value(), true);
784 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-bool");
785 XMLTest("attrib-bool", true, attrib->BoolValue(), true);
786 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-double");
787 XMLTest("attrib-double", 4.0, attrib->DoubleValue(), true);
788 }
789
790 }
791
Uli Kusterer321072e2014-01-21 01:57:38 +0100792
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800793 // ---------- CDATA ---------------
794 {
795 const char* str = "<xmlElement>"
796 "<![CDATA["
797 "I am > the rules!\n"
798 "...since I make symbolic puns"
799 "]]>"
800 "</xmlElement>";
801 XMLDocument doc;
802 doc.Parse( str );
803 doc.Print();
Lee Thomasond6277762012-02-22 16:00:12 -0800804
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700805 XMLTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800806 "I am > the rules!\n...since I make symbolic puns",
Lee Thomasond6277762012-02-22 16:00:12 -0800807 false );
808 }
809
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800810 // ----------- CDATA -------------
811 {
812 const char* str = "<xmlElement>"
813 "<![CDATA["
814 "<b>I am > the rules!</b>\n"
815 "...since I make symbolic puns"
816 "]]>"
817 "</xmlElement>";
818 XMLDocument doc;
819 doc.Parse( str );
820 doc.Print();
821
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700822 XMLTest( "CDATA parse. [ tixml1:1480107 ]", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800823 "<b>I am > the rules!</b>\n...since I make symbolic puns",
824 false );
825 }
826
827 // InsertAfterChild causes crash.
828 {
829 // InsertBeforeChild and InsertAfterChild causes crash.
830 XMLDocument doc;
831 XMLElement* parent = doc.NewElement( "Parent" );
832 doc.InsertFirstChild( parent );
833
834 XMLElement* childText0 = doc.NewElement( "childText0" );
835 XMLElement* childText1 = doc.NewElement( "childText1" );
836
837 XMLNode* childNode0 = parent->InsertEndChild( childText0 );
838 XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
839
840 XMLTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent->LastChild() ), true );
841 }
Lee Thomasond6277762012-02-22 16:00:12 -0800842
843 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800844 // Entities not being written correctly.
845 // From Lynn Allen
Lee Thomasond6277762012-02-22 16:00:12 -0800846
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800847 const char* passages =
848 "<?xml version=\"1.0\" standalone=\"no\" ?>"
849 "<passages count=\"006\" formatversion=\"20020620\">"
850 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
851 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
852 "</passages>";
Lee Thomasond6277762012-02-22 16:00:12 -0800853
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800854 XMLDocument doc;
855 doc.Parse( passages );
856 XMLElement* psg = doc.RootElement()->FirstChildElement();
857 const char* context = psg->Attribute( "context" );
858 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 -0800859
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800860 XMLTest( "Entity transformation: read. ", expected, context, true );
Lee Thomasond6277762012-02-22 16:00:12 -0800861
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400862 FILE* textfile = fopen( "resources/out/textfile.txt", "w" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800863 if ( textfile )
864 {
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800865 XMLPrinter streamer( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800866 psg->Accept( &streamer );
867 fclose( textfile );
868 }
Thomas Roß0922b732012-09-23 16:31:22 +0200869
870 textfile = fopen( "resources/out/textfile.txt", "r" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800871 TIXMLASSERT( textfile );
872 if ( textfile )
873 {
874 char buf[ 1024 ];
875 fgets( buf, 1024, textfile );
876 XMLTest( "Entity transformation: write. ",
877 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
878 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
879 buf, false );
PKEuSc28ba3a2012-07-16 03:08:47 -0700880 fclose( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800881 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800882 }
883
884 {
Lee Thomason6f381b72012-03-02 12:59:39 -0800885 // Suppress entities.
886 const char* passages =
887 "<?xml version=\"1.0\" standalone=\"no\" ?>"
888 "<passages count=\"006\" formatversion=\"20020620\">"
889 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
890 "</passages>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700891
Lee Thomason6f381b72012-03-02 12:59:39 -0800892 XMLDocument doc( false );
893 doc.Parse( passages );
894
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700895 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ),
Lee Thomason6f381b72012-03-02 12:59:39 -0800896 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;." );
897 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value(),
898 "Crazy &ttk;" );
899 doc.Print();
900 }
901
902 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400903 const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800904
905 XMLDocument doc;
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400906 doc.Parse( test );
907 XMLTest( "dot in names", doc.Error(), false );
908 XMLTest( "dot in names", doc.FirstChildElement()->Name(), "a.elem" );
909 XMLTest( "dot in names", doc.FirstChildElement()->Attribute( "xmi.version" ), "2.0" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800910 }
911
912 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400913 const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800914
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400915 XMLDocument doc;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800916 doc.Parse( test );
917
918 XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
919 XMLTest( "Entity with one digit.",
920 text->Value(), "1.1 Start easy ignore fin thickness\n",
921 false );
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400922 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800923
924 {
925 // DOCTYPE not preserved (950171)
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700926 //
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800927 const char* doctype =
928 "<?xml version=\"1.0\" ?>"
929 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
930 "<!ELEMENT title (#PCDATA)>"
931 "<!ELEMENT books (title,authors)>"
932 "<element />";
933
934 XMLDocument doc;
935 doc.Parse( doctype );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400936 doc.SaveFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800937 doc.DeleteChild( doc.RootElement() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400938 doc.LoadFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800939 doc.Print();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700940
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800941 const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
942 XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
943
944 }
945
946 {
947 // Comments do not stream out correctly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700948 const char* doctype =
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800949 "<!-- Somewhat<evil> -->";
950 XMLDocument doc;
951 doc.Parse( doctype );
952
953 XMLComment* comment = doc.FirstChild()->ToComment();
954
955 XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
956 }
957 {
958 // Double attributes
959 const char* doctype = "<element attr='red' attr='blue' />";
960
961 XMLDocument doc;
962 doc.Parse( doctype );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700963
Lee Thomason2fa81722012-11-09 12:37:46 -0800964 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 -0800965 doc.PrintError();
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800966 }
967
968 {
969 // Embedded null in stream.
970 const char* doctype = "<element att\0r='red' attr='blue' />";
971
972 XMLDocument doc;
973 doc.Parse( doctype );
974 XMLTest( "Embedded null throws error.", true, doc.Error() );
975 }
976
977 {
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700978 // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
Dmitry-Me588bb8d2014-12-25 18:59:18 +0300979 const char* str = "";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800980 XMLDocument doc;
981 doc.Parse( str );
Lee Thomason2fa81722012-11-09 12:37:46 -0800982 XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800983 }
984
985 {
Dmitry-Me588bb8d2014-12-25 18:59:18 +0300986 // Documents with all whitespaces should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
987 const char* str = " ";
988 XMLDocument doc;
989 doc.Parse( str );
990 XMLTest( "All whitespaces document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
991 }
992
993 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800994 // Low entities
995 XMLDocument doc;
996 doc.Parse( "<test>&#x0e;</test>" );
997 const char result[] = { 0x0e, 0 };
998 XMLTest( "Low entities.", doc.FirstChildElement()->GetText(), result );
999 doc.Print();
1000 }
1001
1002 {
1003 // Attribute values with trailing quotes not handled correctly
1004 XMLDocument doc;
1005 doc.Parse( "<foo attribute=bar\" />" );
1006 XMLTest( "Throw error with bad end quotes.", doc.Error(), true );
1007 }
1008
1009 {
1010 // [ 1663758 ] Failure to report error on bad XML
1011 XMLDocument xml;
1012 xml.Parse("<x>");
1013 XMLTest("Missing end tag at end of input", xml.Error(), true);
1014 xml.Parse("<x> ");
1015 XMLTest("Missing end tag with trailing whitespace", xml.Error(), true);
1016 xml.Parse("<x></y>");
Lee Thomason2fa81722012-11-09 12:37:46 -08001017 XMLTest("Mismatched tags", xml.ErrorID(), XML_ERROR_MISMATCHED_ELEMENT);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001018 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001019
1020
1021 {
1022 // [ 1475201 ] TinyXML parses entities in comments
1023 XMLDocument xml;
1024 xml.Parse("<!-- declarations for <head> & <body> -->"
1025 "<!-- far &amp; away -->" );
1026
1027 XMLNode* e0 = xml.FirstChild();
1028 XMLNode* e1 = e0->NextSibling();
1029 XMLComment* c0 = e0->ToComment();
1030 XMLComment* c1 = e1->ToComment();
1031
1032 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
1033 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
1034 }
1035
1036 {
1037 XMLDocument xml;
1038 xml.Parse( "<Parent>"
1039 "<child1 att=''/>"
1040 "<!-- With this comment, child2 will not be parsed! -->"
1041 "<child2 att=''/>"
1042 "</Parent>" );
1043 xml.Print();
1044
1045 int count = 0;
1046
1047 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
1048 ele;
1049 ele = ele->NextSibling() )
1050 {
1051 ++count;
1052 }
1053
1054 XMLTest( "Comments iterate correctly.", 3, count );
1055 }
1056
1057 {
1058 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
1059 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
1060 buf[60] = 239;
1061 buf[61] = 0;
1062
1063 XMLDocument doc;
1064 doc.Parse( (const char*)buf);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001065 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001066
1067
1068 {
1069 // bug 1827248 Error while parsing a little bit malformed file
1070 // Actually not malformed - should work.
1071 XMLDocument xml;
1072 xml.Parse( "<attributelist> </attributelist >" );
1073 XMLTest( "Handle end tag whitespace", false, xml.Error() );
1074 }
1075
1076 {
1077 // This one must not result in an infinite loop
1078 XMLDocument xml;
1079 xml.Parse( "<infinite>loop" );
1080 XMLTest( "Infinite loop test.", true, true );
1081 }
1082#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001083 {
1084 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
1085 XMLDocument doc;
1086 doc.Parse( pub );
1087
1088 XMLDocument clone;
1089 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
1090 XMLNode* copy = node->ShallowClone( &clone );
1091 clone.InsertEndChild( copy );
1092 }
1093
1094 clone.Print();
1095
1096 int count=0;
1097 const XMLNode* a=clone.FirstChild();
1098 const XMLNode* b=doc.FirstChild();
1099 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
1100 ++count;
1101 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
1102 }
1103 XMLTest( "Clone and Equal", 4, count );
1104 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001105
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001106 {
1107 // This shouldn't crash.
1108 XMLDocument doc;
Lee Thomason85536252016-06-04 19:10:53 -07001109 if(XML_SUCCESS != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001110 {
1111 doc.PrintError();
1112 }
1113 XMLTest( "Error in snprinf handling.", true, doc.Error() );
1114 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001115
Lee Thomason5e3803c2012-04-16 08:57:05 -07001116 {
1117 // Attribute ordering.
1118 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
1119 XMLDocument doc;
1120 doc.Parse( xml );
1121 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001122
Lee Thomason5e3803c2012-04-16 08:57:05 -07001123 const XMLAttribute* a = ele->FirstAttribute();
1124 XMLTest( "Attribute order", "1", a->Value() );
1125 a = a->Next();
1126 XMLTest( "Attribute order", "2", a->Value() );
1127 a = a->Next();
1128 XMLTest( "Attribute order", "3", a->Value() );
1129 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001130
Lee Thomason5e3803c2012-04-16 08:57:05 -07001131 ele->DeleteAttribute( "attrib2" );
1132 a = ele->FirstAttribute();
1133 XMLTest( "Attribute order", "1", a->Value() );
1134 a = a->Next();
1135 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001136
Lee Thomason5e3803c2012-04-16 08:57:05 -07001137 ele->DeleteAttribute( "attrib1" );
1138 ele->DeleteAttribute( "attrib3" );
1139 XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
1140 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001141
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001142 {
1143 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -07001144 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
1145 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
1146 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
1147 XMLDocument doc0;
1148 doc0.Parse( xml0 );
1149 XMLDocument doc1;
1150 doc1.Parse( xml1 );
1151 XMLDocument doc2;
1152 doc2.Parse( xml2 );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001153
Lee Thomason78a773d2012-07-02 10:10:19 -07001154 XMLElement* ele = 0;
1155 ele = doc0.FirstChildElement();
1156 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
1157 ele = doc1.FirstChildElement();
1158 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
1159 ele = doc2.FirstChildElement();
1160 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001161 }
1162
1163 {
1164 // Make sure we don't go into an infinite loop.
1165 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
1166 XMLDocument doc;
1167 doc.Parse( xml );
1168 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
1169 XMLElement* ele1 = ele0->NextSiblingElement();
1170 bool equal = ele0->ShallowEqual( ele1 );
1171
1172 XMLTest( "Infinite loop in shallow equal.", true, equal );
1173 }
1174
Lee Thomason5708f812012-03-28 17:46:41 -07001175 // -------- Handles ------------
1176 {
1177 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1178 XMLDocument doc;
1179 doc.Parse( xml );
Lee Thomason5708f812012-03-28 17:46:41 -07001180
1181 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
1182 XMLTest( "Handle, success, mutable", ele->Value(), "sub" );
1183
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001184 XMLHandle docH( doc );
1185 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001186 XMLTest( "Handle, dne, mutable", false, ele != 0 );
Lee Thomason5708f812012-03-28 17:46:41 -07001187 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001188
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001189 {
1190 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1191 XMLDocument doc;
1192 doc.Parse( xml );
1193 XMLConstHandle docH( doc );
1194
1195 const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
1196 XMLTest( "Handle, success, const", ele->Value(), "sub" );
1197
1198 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001199 XMLTest( "Handle, dne, const", false, ele != 0 );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001200 }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001201 {
1202 // Default Declaration & BOM
1203 XMLDocument doc;
1204 doc.InsertEndChild( doc.NewDeclaration() );
1205 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001206
Lee Thomasonf68c4382012-04-28 14:37:11 -07001207 XMLPrinter printer;
1208 doc.Print( &printer );
1209
1210 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1211 XMLTest( "BOM and default declaration", printer.CStr(), result, false );
Lee Thomason (grinliz)48ea0bc2012-05-26 14:41:14 -07001212 XMLTest( "CStrSize", printer.CStrSize(), 42, false );
Lee Thomasonf68c4382012-04-28 14:37:11 -07001213 }
Lee Thomason21be8822012-07-15 17:27:22 -07001214 {
1215 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1216 XMLDocument doc;
1217 doc.Parse( xml );
1218 XMLTest( "Ill formed XML", true, doc.Error() );
1219 }
1220
1221 // QueryXYZText
1222 {
1223 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1224 XMLDocument doc;
1225 doc.Parse( xml );
1226
1227 const XMLElement* pointElement = doc.RootElement();
1228
1229 int intValue = 0;
1230 unsigned unsignedValue = 0;
1231 float floatValue = 0;
1232 double doubleValue = 0;
1233 bool boolValue = false;
1234
1235 pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1236 pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1237 pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1238 pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1239 pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1240
1241
1242 XMLTest( "QueryIntText", intValue, 1, false );
1243 XMLTest( "QueryUnsignedText", unsignedValue, (unsigned)1, false );
1244 XMLTest( "QueryFloatText", floatValue, 1.2f, false );
1245 XMLTest( "QueryDoubleText", doubleValue, 1.2, false );
1246 XMLTest( "QueryBoolText", boolValue, true, false );
1247 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001248
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001249 {
1250 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1251 XMLDocument doc;
1252 doc.Parse( xml );
1253 XMLTest( "Non-alpha element lead letter parses.", doc.Error(), false );
1254 }
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001255
1256 {
1257 const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1258 XMLDocument doc;
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001259 doc.Parse( xml );
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001260 XMLTest("Non-alpha attribute lead character parses.", doc.Error(), false);
1261 }
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001262
1263 {
1264 const char* xml = "<3lement></3lement>";
1265 XMLDocument doc;
1266 doc.Parse( xml );
1267 XMLTest("Element names with lead digit fail to parse.", doc.Error(), true);
1268 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -07001269
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001270 {
1271 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1272 XMLDocument doc;
1273 doc.Parse( xml, 10 );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001274 XMLTest( "Set length of incoming data", doc.Error(), false );
1275 }
1276
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001277 {
1278 XMLDocument doc;
Dmitry-Me48b5df02015-04-06 18:20:25 +03001279 XMLTest( "Document is initially empty", doc.NoChildren(), true );
1280 doc.Clear();
1281 XMLTest( "Empty is empty after Clear()", doc.NoChildren(), true );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001282 doc.LoadFile( "resources/dream.xml" );
Dmitry-Meaaa4cea2015-02-06 16:00:46 +03001283 XMLTest( "Document has something to Clear()", doc.NoChildren(), false );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001284 doc.Clear();
1285 XMLTest( "Document Clear()'s", doc.NoChildren(), true );
1286 }
1287
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001288 // ----------- Whitespace ------------
1289 {
1290 const char* xml = "<element>"
1291 "<a> This \nis &apos; text &apos; </a>"
1292 "<b> This is &apos; text &apos; \n</b>"
1293 "<c>This is &apos; \n\n text &apos;</c>"
1294 "</element>";
1295 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1296 doc.Parse( xml );
1297
1298 const XMLElement* element = doc.FirstChildElement();
1299 for( const XMLElement* parent = element->FirstChildElement();
1300 parent;
1301 parent = parent->NextSiblingElement() )
1302 {
1303 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1304 }
1305 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001306
Lee Thomasonae9ab072012-10-24 10:17:53 -07001307#if 0
1308 {
1309 // Passes if assert doesn't fire.
1310 XMLDocument xmlDoc;
1311
1312 xmlDoc.NewDeclaration();
1313 xmlDoc.NewComment("Configuration file");
1314
1315 XMLElement *root = xmlDoc.NewElement("settings");
1316 root->SetAttribute("version", 2);
1317 }
1318#endif
1319
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001320 {
1321 const char* xml = "<element> </element>";
1322 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1323 doc.Parse( xml );
1324 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1325 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001326
Lee Thomason5b0a6772012-11-19 13:54:42 -08001327 {
1328 // An assert should not fire.
1329 const char* xml = "<element/>";
1330 XMLDocument doc;
1331 doc.Parse( xml );
1332 XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope.
1333 XMLTest( "Tracking unused elements", true, ele != 0, false );
1334 }
1335
Lee Thomasona6412ac2012-12-13 15:39:11 -08001336
1337 {
1338 const char* xml = "<parent><child>abc</child></parent>";
1339 XMLDocument doc;
1340 doc.Parse( xml );
1341 XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
1342
1343 XMLPrinter printer;
1344 ele->Accept( &printer );
1345 XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1346 }
1347
1348
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001349 {
1350 XMLDocument doc;
1351 XMLError error = doc.LoadFile( "resources/empty.xml" );
1352 XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
Lee Thomason331596e2014-09-11 14:56:43 -07001353 XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() );
Lee Thomasonc7556672014-09-14 12:39:42 -07001354 doc.PrintError();
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001355 }
1356
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001357 {
1358 // BOM preservation
1359 static const char* xml_bom_preservation = "\xef\xbb\xbf<element/>\n";
1360 {
1361 XMLDocument doc;
Lee Thomason85536252016-06-04 19:10:53 -07001362 XMLTest( "BOM preservation (parse)", XML_SUCCESS, doc.Parse( xml_bom_preservation ), false );
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001363 XMLPrinter printer;
1364 doc.Print( &printer );
1365
1366 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1367 doc.SaveFile( "resources/bomtest.xml" );
1368 }
1369 {
1370 XMLDocument doc;
1371 doc.LoadFile( "resources/bomtest.xml" );
1372 XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
1373
1374 XMLPrinter printer;
1375 doc.Print( &printer );
1376 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1377 }
1378 }
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001379
Michael Daumlinged523282013-10-23 07:47:29 +02001380 {
1381 // Insertion with Removal
1382 const char* xml = "<?xml version=\"1.0\" ?>"
1383 "<root>"
1384 "<one>"
1385 "<subtree>"
1386 "<elem>element 1</elem>text<!-- comment -->"
1387 "</subtree>"
1388 "</one>"
1389 "<two/>"
1390 "</root>";
1391 const char* xmlInsideTwo = "<?xml version=\"1.0\" ?>"
1392 "<root>"
1393 "<one/>"
1394 "<two>"
1395 "<subtree>"
1396 "<elem>element 1</elem>text<!-- comment -->"
1397 "</subtree>"
1398 "</two>"
1399 "</root>";
1400 const char* xmlAfterOne = "<?xml version=\"1.0\" ?>"
1401 "<root>"
1402 "<one/>"
1403 "<subtree>"
1404 "<elem>element 1</elem>text<!-- comment -->"
1405 "</subtree>"
1406 "<two/>"
1407 "</root>";
1408 const char* xmlAfterTwo = "<?xml version=\"1.0\" ?>"
1409 "<root>"
1410 "<one/>"
1411 "<two/>"
1412 "<subtree>"
1413 "<elem>element 1</elem>text<!-- comment -->"
1414 "</subtree>"
1415 "</root>";
1416
1417 XMLDocument doc;
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001418 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001419 XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1420 XMLElement* two = doc.RootElement()->FirstChildElement("two");
1421 two->InsertFirstChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001422 XMLPrinter printer1(0, true);
1423 doc.Accept(&printer1);
1424 XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
Michael Daumlinged523282013-10-23 07:47:29 +02001425
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001426 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001427 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1428 two = doc.RootElement()->FirstChildElement("two");
1429 doc.RootElement()->InsertAfterChild(two, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001430 XMLPrinter printer2(0, true);
1431 doc.Accept(&printer2);
1432 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001433
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001434 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001435 XMLNode* one = doc.RootElement()->FirstChildElement("one");
1436 subtree = one->FirstChildElement("subtree");
1437 doc.RootElement()->InsertAfterChild(one, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001438 XMLPrinter printer3(0, true);
1439 doc.Accept(&printer3);
1440 XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001441
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001442 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001443 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1444 two = doc.RootElement()->FirstChildElement("two");
1445 doc.RootElement()->InsertEndChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001446 XMLPrinter printer4(0, true);
1447 doc.Accept(&printer4);
1448 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001449 }
1450
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001451 {
1452 const char* xml = "<svg width = \"128\" height = \"128\">"
1453 " <text> </text>"
1454 "</svg>";
1455 XMLDocument doc;
1456 doc.Parse(xml);
1457 doc.Print();
1458 }
1459
Lee Thomason92e521b2014-11-15 17:45:51 -08001460 {
1461 // Test that it doesn't crash.
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001462 const char* xml = "<?xml version=\"1.0\"?><root><sample><field0><1</field0><field1>2</field1></sample></root>";
1463 XMLDocument doc;
1464 doc.Parse(xml);
1465 doc.PrintError();
Lee Thomason92e521b2014-11-15 17:45:51 -08001466 }
1467
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001468#if 1
1469 // the question being explored is what kind of print to use:
1470 // https://github.com/leethomason/tinyxml2/issues/63
1471 {
1472 //const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
1473 const char* xml = "<element/>";
1474 XMLDocument doc;
1475 doc.Parse( xml );
1476 doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
1477 doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
1478 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
1479 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
1480 doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
1481 doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
1482
1483 doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
1484 doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
1485 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
1486 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
1487 doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
1488 doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
1489
1490 doc.Print();
1491
1492 /* The result of this test is platform, compiler, and library version dependent. :("
1493 XMLPrinter printer;
1494 doc.Print( &printer );
1495 XMLTest( "Float and double formatting.",
1496 "<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",
1497 printer.CStr(),
1498 true );
1499 */
1500 }
1501#endif
Lee Thomasonf07b9522014-10-30 13:25:12 -07001502
1503 {
1504 // Issue #184
1505 // If it doesn't assert, it passes. Caused by objects
1506 // getting created during parsing which are then
1507 // inaccessible in the memory pools.
1508 {
1509 XMLDocument doc;
1510 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1511 }
1512 {
1513 XMLDocument doc;
1514 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1515 doc.Clear();
1516 }
1517 }
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001518
1519 {
1520 // If this doesn't assert in DEBUG, all is well.
1521 tinyxml2::XMLDocument doc;
1522 tinyxml2::XMLElement *pRoot = doc.NewElement("Root");
1523 doc.DeleteNode(pRoot);
1524 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001525
Dmitry-Me8b67d742014-12-22 11:35:12 +03001526 {
1527 // Should not assert in DEBUG
1528 XMLPrinter printer;
1529 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001530
Dmitry-Me6f51c802015-03-14 13:25:03 +03001531 {
1532 // Issue 291. Should not crash
1533 const char* xml = "&#0</a>";
1534 XMLDocument doc;
1535 doc.Parse( xml );
1536
1537 XMLPrinter printer;
1538 doc.Print( &printer );
1539 }
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001540 {
1541 // Issue 299. Can print elements that are not linked in.
1542 // Will crash if issue not fixed.
1543 XMLDocument doc;
1544 XMLElement* newElement = doc.NewElement( "printme" );
1545 XMLPrinter printer;
1546 newElement->Accept( &printer );
Dmitry-Me5daa54c2015-04-08 17:45:07 +03001547 // Delete the node to avoid possible memory leak report in debug output
1548 doc.DeleteNode( newElement );
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001549 }
Lee Thomasonf6577832015-03-26 11:18:21 -07001550 {
Ant Mitchell189198f2015-03-24 16:20:36 +00001551 // Issue 302. Clear errors from LoadFile/SaveFile
1552 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001553 XMLTest( "Issue 302. Should be no error initially", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001554 doc.SaveFile( "./no/such/path/pretty.xml" );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001555 XMLTest( "Issue 302. Fail to save", "XML_ERROR_FILE_COULD_NOT_BE_OPENED", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001556 doc.SaveFile( "./resources/out/compact.xml", true );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001557 XMLTest( "Issue 302. Subsequent success in saving", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001558 }
Dmitry-Me6f51c802015-03-14 13:25:03 +03001559
Dmitry-Med9852a52015-03-25 10:17:49 +03001560 {
1561 // If a document fails to load then subsequent
1562 // successful loads should clear the error
1563 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001564 XMLTest( "Should be no error initially", false, doc.Error() );
Dmitry-Med9852a52015-03-25 10:17:49 +03001565 doc.LoadFile( "resources/no-such-file.xml" );
1566 XMLTest( "No such file - should fail", true, doc.Error() );
1567
1568 doc.LoadFile( "resources/dream.xml" );
1569 XMLTest( "Error should be cleared", false, doc.Error() );
1570 }
Sarat Addepalli8e85afa2015-05-19 09:07:03 +05301571
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301572 {
1573 // Check that declarations are parsed only as the FirstChild
Lee Thomason85492022015-05-22 11:07:45 -07001574 const char* xml0 = "<?xml version=\"1.0\" ?>"
1575 " <!-- xml version=\"1.1\" -->"
1576 "<first />";
1577 const char* xml1 = "<?xml version=\"1.0\" ?>"
1578 " <?xml version=\"1.1\" ?>"
1579 "<first />";
1580 const char* xml2 = "<first />"
1581 "<?xml version=\"1.0\" ?>";
1582 XMLDocument doc;
1583 doc.Parse(xml0);
1584 XMLTest("Test that the code changes do not affect normal parsing", doc.Error(), false);
1585 doc.Parse(xml1);
1586 XMLTest("Test that the second declaration throws an error", doc.ErrorID(), XML_ERROR_PARSING_DECLARATION);
1587 doc.Parse(xml2);
1588 XMLTest("Test that declaration after a child throws an error", doc.ErrorID(), XML_ERROR_PARSING_DECLARATION);
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301589 }
Dmitry-Med9852a52015-03-25 10:17:49 +03001590
Lee Thomason85492022015-05-22 11:07:45 -07001591 {
1592 // No matter - before or after successfully parsing a text -
1593 // calling XMLDocument::Value() causes an assert in debug.
1594 const char* validXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
1595 "<first />"
1596 "<second />";
1597 XMLDocument* doc = new XMLDocument();
1598 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1599 doc->Parse( validXml );
1600 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1601 delete doc;
1602 }
1603
Dmitry-Mea1beddf2015-05-26 16:19:21 +03001604 {
1605 XMLDocument doc;
1606 for( int i = 0; i < XML_ERROR_COUNT; i++ ) {
1607 doc.SetError( (XMLError)i, 0, 0 );
1608 doc.ErrorName();
1609 }
1610 }
1611
Lee Thomason85492022015-05-22 11:07:45 -07001612 // ----------- Performance tracking --------------
Lee Thomason6f381b72012-03-02 12:59:39 -08001613 {
1614#if defined( _MSC_VER )
1615 __int64 start, end, freq;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001616 QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
Lee Thomason6f381b72012-03-02 12:59:39 -08001617#endif
1618
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001619 FILE* perfFP = fopen("resources/dream.xml", "r");
1620 fseek(perfFP, 0, SEEK_END);
1621 long size = ftell(fp);
1622 fseek(perfFP, 0, SEEK_SET);
Lee Thomason6f381b72012-03-02 12:59:39 -08001623
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001624 char* mem = new char[size + 1];
1625 fread(mem, size, 1, perfFP);
1626 fclose(perfFP);
Lee Thomason6f381b72012-03-02 12:59:39 -08001627 mem[size] = 0;
1628
1629#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001630 QueryPerformanceCounter((LARGE_INTEGER*)&start);
Lee Thomason6f381b72012-03-02 12:59:39 -08001631#else
1632 clock_t cstart = clock();
1633#endif
1634 static const int COUNT = 10;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001635 for (int i = 0; i < COUNT; ++i) {
Lee Thomason6f381b72012-03-02 12:59:39 -08001636 XMLDocument doc;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001637 doc.Parse(mem);
Lee Thomason6f381b72012-03-02 12:59:39 -08001638 }
1639#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001640 QueryPerformanceCounter((LARGE_INTEGER*)&end);
Lee Thomason6f381b72012-03-02 12:59:39 -08001641#else
1642 clock_t cend = clock();
1643#endif
1644
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001645 delete[] mem;
Lee Thomason6f381b72012-03-02 12:59:39 -08001646
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001647 static const char* note =
Lee Thomason6f381b72012-03-02 12:59:39 -08001648#ifdef DEBUG
1649 "DEBUG";
1650#else
1651 "Release";
1652#endif
1653
1654#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001655 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 -08001656#else
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001657 printf("\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart) / (double)COUNT);
Lee Thomason6f381b72012-03-02 12:59:39 -08001658#endif
1659 }
1660
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -08001661 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001662 _CrtMemCheckpoint( &endMemState );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001663
1664 _CrtMemState diffMemState;
1665 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
1666 _CrtMemDumpStatistics( &diffMemState );
1667 #endif
1668
1669 printf ("\nPass %d, Fail %d\n", gPass, gFail);
Lee Thomason (grinliz)db304252013-07-31 12:24:52 -07001670
1671 return gFail;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08001672}