blob: 2009d1a07212a29aa73ab532fab49a6d86c2228a [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" ) );
419 element->InsertAfterChild( comment, sub[0] );
420 element->InsertAfterChild( sub[0], sub[1] );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800421 sub[2]->InsertFirstChild( doc->NewText( "& Text!" ));
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800422 doc->Print();
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800423 XMLTest( "Programmatic DOM", "comment", doc->FirstChildElement( "element" )->FirstChild()->Value() );
424 XMLTest( "Programmatic DOM", "0", doc->FirstChildElement( "element" )->FirstChildElement()->Attribute( "attrib" ) );
425 XMLTest( "Programmatic DOM", 2, doc->FirstChildElement()->LastChildElement( "sub" )->IntAttribute( "attrib" ) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700426 XMLTest( "Programmatic DOM", "& Text!",
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800427 doc->FirstChildElement()->LastChildElement( "sub" )->FirstChild()->ToText()->Value() );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800428
429 // And now deletion:
430 element->DeleteChild( sub[2] );
431 doc->DeleteNode( comment );
432
433 element->FirstChildElement()->SetAttribute( "attrib", true );
434 element->LastChildElement()->DeleteAttribute( "attrib" );
435
436 XMLTest( "Programmatic DOM", true, doc->FirstChildElement()->FirstChildElement()->BoolAttribute( "attrib" ) );
437 int value = 10;
438 int result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value );
Lee Thomason21be8822012-07-15 17:27:22 -0700439 XMLTest( "Programmatic DOM", result, (int)XML_NO_ATTRIBUTE );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800440 XMLTest( "Programmatic DOM", value, 10 );
441
442 doc->Print();
443
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700444 {
445 XMLPrinter streamer;
446 doc->Print( &streamer );
447 printf( "%s", streamer.CStr() );
448 }
449 {
450 XMLPrinter streamer( 0, true );
451 doc->Print( &streamer );
452 XMLTest( "Compact mode", "<element><sub attrib=\"1\"/><sub/></element>", streamer.CStr(), false );
453 }
Lee Thomason (grinliz)6b8b0122012-09-08 21:21:00 -0700454 doc->SaveFile( "./resources/out/pretty.xml" );
455 doc->SaveFile( "./resources/out/compact.xml", true );
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800456 delete doc;
457 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800458 {
459 // Test: Dream
460 // XML1 : 1,187,569 bytes in 31,209 allocations
461 // XML2 : 469,073 bytes in 323 allocations
462 //int newStart = gNew;
463 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300464 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800465
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400466 doc.SaveFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800467 doc.PrintError();
468
469 XMLTest( "Dream", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400470 doc.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800471 XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false );
472 XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
473 doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
474 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400475 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800476 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
479 XMLDocument doc2;
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400480 doc2.LoadFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800481 XMLTest( "Dream-out", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400482 doc2.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800483 XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false );
484 XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
485 doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
486 XMLTest( "Dream-out", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400487 doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800488
489 //gNewTotal = gNew - newStart;
490 }
Lee Thomason6f381b72012-03-02 12:59:39 -0800491
492
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800493 {
494 const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
495 "<passages count=\"006\" formatversion=\"20020620\">\n"
496 " <wrong error>\n"
497 "</passages>";
498
499 XMLDocument doc;
500 doc.Parse( error );
Lee Thomason2fa81722012-11-09 12:37:46 -0800501 XMLTest( "Bad XML", doc.ErrorID(), XML_ERROR_PARSING_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800502 }
503
504 {
505 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
506
507 XMLDocument doc;
508 doc.Parse( str );
509
510 XMLElement* ele = doc.FirstChildElement();
511
512 int iVal, result;
513 double dVal;
514
515 result = ele->QueryDoubleAttribute( "attr0", &dVal );
Lee Thomason85536252016-06-04 19:10:53 -0700516 XMLTest( "Query attribute: int as double", result, (int)XML_SUCCESS);
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800517 XMLTest( "Query attribute: int as double", (int)dVal, 1 );
518 result = ele->QueryDoubleAttribute( "attr1", &dVal );
Lee Thomason85536252016-06-04 19:10:53 -0700519 XMLTest( "Query attribute: double as double", result, (int)XML_SUCCESS);
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800520 XMLTest( "Query attribute: double as double", (int)dVal, 2 );
521 result = ele->QueryIntAttribute( "attr1", &iVal );
Lee Thomason85536252016-06-04 19:10:53 -0700522 XMLTest( "Query attribute: double as int", result, (int)XML_SUCCESS);
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800523 XMLTest( "Query attribute: double as int", iVal, 2 );
524 result = ele->QueryIntAttribute( "attr2", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700525 XMLTest( "Query attribute: not a number", result, (int)XML_WRONG_ATTRIBUTE_TYPE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800526 result = ele->QueryIntAttribute( "bar", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700527 XMLTest( "Query attribute: does not exist", result, (int)XML_NO_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800528 }
529
530 {
531 const char* str = "<doc/>";
532
533 XMLDocument doc;
534 doc.Parse( str );
535
536 XMLElement* ele = doc.FirstChildElement();
537
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800538 int iVal, iVal2;
539 double dVal, dVal2;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800540
541 ele->SetAttribute( "str", "strValue" );
542 ele->SetAttribute( "int", 1 );
543 ele->SetAttribute( "double", -1.0 );
544
545 const char* cStr = ele->Attribute( "str" );
546 ele->QueryIntAttribute( "int", &iVal );
547 ele->QueryDoubleAttribute( "double", &dVal );
548
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800549 ele->QueryAttribute( "int", &iVal2 );
550 ele->QueryAttribute( "double", &dVal2 );
551
Lee Thomason8ba7f7d2012-03-24 13:04:04 -0700552 XMLTest( "Attribute match test", ele->Attribute( "str", "strValue" ), "strValue" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800553 XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
554 XMLTest( "Attribute round trip. int.", 1, iVal );
555 XMLTest( "Attribute round trip. double.", -1, (int)dVal );
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800556 XMLTest( "Alternate query", true, iVal == iVal2 );
557 XMLTest( "Alternate query", true, dVal == dVal2 );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800558 }
559
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800560 {
561 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300562 doc.LoadFile( "resources/utf8test.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800563
564 // Get the attribute "value" from the "Russian" element and check it.
565 XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700566 const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800567 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
568
569 XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
570
571 const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U,
572 0xd1U, 0x81U, 0xd1U, 0x81U,
573 0xd0U, 0xbaU, 0xd0U, 0xb8U,
574 0xd0U, 0xb9U, 0 };
575 const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
576
577 XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
578 XMLTest( "UTF-8: Browsing russian element name.",
579 russianText,
580 text->Value() );
581
582 // Now try for a round trip.
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400583 doc.SaveFile( "resources/out/utf8testout.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800584
585 // Check the round trip.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800586 int okay = 0;
587
Thomas Roßa6dd8c62012-07-26 20:42:18 +0200588 FILE* saved = fopen( "resources/out/utf8testout.xml", "r" );
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300589 FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800590
591 if ( saved && verify )
592 {
593 okay = 1;
PKEuSc28ba3a2012-07-16 03:08:47 -0700594 char verifyBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800595 while ( fgets( verifyBuf, 256, verify ) )
596 {
PKEuSc28ba3a2012-07-16 03:08:47 -0700597 char savedBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800598 fgets( savedBuf, 256, saved );
599 NullLineEndings( verifyBuf );
600 NullLineEndings( savedBuf );
601
602 if ( strcmp( verifyBuf, savedBuf ) )
603 {
604 printf( "verify:%s<\n", verifyBuf );
605 printf( "saved :%s<\n", savedBuf );
606 okay = 0;
607 break;
608 }
609 }
610 }
611 if ( saved )
612 fclose( saved );
613 if ( verify )
614 fclose( verify );
615 XMLTest( "UTF-8: Verified multi-language round trip.", 1, okay );
616 }
617
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800618 // --------GetText()-----------
619 {
620 const char* str = "<foo>This is text</foo>";
621 XMLDocument doc;
622 doc.Parse( str );
623 const XMLElement* element = doc.RootElement();
624
625 XMLTest( "GetText() normal use.", "This is text", element->GetText() );
626
627 str = "<foo><b>This is text</b></foo>";
628 doc.Parse( str );
629 element = doc.RootElement();
630
631 XMLTest( "GetText() contained element.", element->GetText() == 0, true );
632 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800633
Lee Thomasond6277762012-02-22 16:00:12 -0800634
Uli Kusterer321072e2014-01-21 01:57:38 +0100635 // --------SetText()-----------
636 {
637 const char* str = "<foo></foo>";
638 XMLDocument doc;
639 doc.Parse( str );
640 XMLElement* element = doc.RootElement();
641
Lee Thomason9c0678a2014-01-24 10:18:27 -0800642 element->SetText("darkness.");
643 XMLTest( "SetText() normal use (open/close).", "darkness.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100644
Lee Thomason9c0678a2014-01-24 10:18:27 -0800645 element->SetText("blue flame.");
646 XMLTest( "SetText() replace.", "blue flame.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100647
648 str = "<foo/>";
649 doc.Parse( str );
650 element = doc.RootElement();
651
Lee Thomason9c0678a2014-01-24 10:18:27 -0800652 element->SetText("The driver");
653 XMLTest( "SetText() normal use. (self-closing)", "The driver", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100654
Lee Thomason9c0678a2014-01-24 10:18:27 -0800655 element->SetText("<b>horses</b>");
656 XMLTest( "SetText() replace with tag-like text.", "<b>horses</b>", element->GetText() );
657 //doc.Print();
Uli Kusterer321072e2014-01-21 01:57:38 +0100658
659 str = "<foo><bar>Text in nested element</bar></foo>";
660 doc.Parse( str );
661 element = doc.RootElement();
662
Lee Thomason9c0678a2014-01-24 10:18:27 -0800663 element->SetText("wolves");
664 XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800665
666 str = "<foo/>";
667 doc.Parse( str );
668 element = doc.RootElement();
669
670 element->SetText( "str" );
671 XMLTest( "SetText types", "str", element->GetText() );
672
673 element->SetText( 1 );
674 XMLTest( "SetText types", "1", element->GetText() );
675
676 element->SetText( 1U );
677 XMLTest( "SetText types", "1", element->GetText() );
678
679 element->SetText( true );
680 XMLTest( "SetText types", "1", element->GetText() ); // TODO: should be 'true'?
681
682 element->SetText( 1.5f );
683 XMLTest( "SetText types", "1.5", element->GetText() );
684
685 element->SetText( 1.5 );
686 XMLTest( "SetText types", "1.5", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100687 }
688
Lee Thomason51c12712016-06-04 20:18:49 -0700689 // ---------- Attributes ---------
690 {
691 static const int64_t BIG = -123456789012345678;
692 XMLDocument doc;
693 XMLElement* element = doc.NewElement("element");
694 doc.InsertFirstChild(element);
695
696 {
697 element->SetAttribute("attrib", int(-100));
698 int v = 0;
699 element->QueryIntAttribute("attrib", &v);
700 XMLTest("Attribute: int", -100, v, true);
701 element->QueryAttribute("attrib", &v);
702 XMLTest("Attribute: int", -100, v, true);
703 }
704 {
705 element->SetAttribute("attrib", unsigned(100));
706 unsigned v = 0;
707 element->QueryUnsignedAttribute("attrib", &v);
708 XMLTest("Attribute: unsigned", unsigned(100), v, true);
709 element->QueryAttribute("attrib", &v);
710 XMLTest("Attribute: unsigned", unsigned(100), v, true);
711 }
712 {
713 element->SetAttribute("attrib", BIG);
714 int64_t v = 0;
715 element->QueryInt64Attribute("attrib", &v);
716 XMLTest("Attribute: int64_t", BIG, v, true);
717 element->QueryAttribute("attrib", &v);
718 XMLTest("Attribute: int64_t", BIG, v, true);
719 }
720 {
721 element->SetAttribute("attrib", true);
722 bool v = false;
723 element->QueryBoolAttribute("attrib", &v);
724 XMLTest("Attribute: bool", true, v, true);
725 element->QueryAttribute("attrib", &v);
726 XMLTest("Attribute: bool", true, v, true);
727 }
728 {
729 element->SetAttribute("attrib", 100.0);
730 double v = 0;
731 element->QueryDoubleAttribute("attrib", &v);
732 XMLTest("Attribute: double", 100.0, v, true);
733 element->QueryAttribute("attrib", &v);
734 XMLTest("Attribute: double", 100.0, v, true);
735 }
736 {
737 element->SetAttribute("attrib", 100.0f);
738 float v = 0;
739 element->QueryFloatAttribute("attrib", &v);
740 XMLTest("Attribute: float", 100.0f, v, true);
741 element->QueryAttribute("attrib", &v);
742 XMLTest("Attribute: float", 100.0f, v, true);
743 }
744 {
745 element->SetText(BIG);
746 int64_t v = 0;
747 element->QueryInt64Text(&v);
748 XMLTest("Element: int64_t", BIG, v, true);
749 }
750 }
751
752 // ---------- XMLPrinter stream mode ------
753 {
754 {
755 FILE* printerfp = fopen("resources/printer.xml", "w");
756 XMLPrinter printer(printerfp);
757 printer.OpenElement("foo");
758 printer.PushAttribute("attrib-text", "text");
759 printer.PushAttribute("attrib-int", int(1));
760 printer.PushAttribute("attrib-unsigned", unsigned(2));
761 printer.PushAttribute("attrib-int64", int64_t(3));
762 printer.PushAttribute("attrib-bool", true);
763 printer.PushAttribute("attrib-double", 4.0);
764 printer.CloseElement();
765 fclose(printerfp);
766 }
767 {
768 XMLDocument doc;
769 doc.LoadFile("resources/printer.xml");
770 XMLTest("XMLPrinter Stream mode: load", doc.ErrorID(), XML_SUCCESS, true);
771
772 const XMLDocument& cdoc = doc;
773
774 const XMLAttribute* attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-text");
775 XMLTest("attrib-text", "text", attrib->Value(), true);
776 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int");
777 XMLTest("attrib-int", int(1), attrib->IntValue(), true);
778 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-unsigned");
779 XMLTest("attrib-unsigned", unsigned(2), attrib->UnsignedValue(), true);
780 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int64");
781 XMLTest("attrib-int64", int64_t(3), attrib->Int64Value(), true);
782 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-bool");
783 XMLTest("attrib-bool", true, attrib->BoolValue(), true);
784 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-double");
785 XMLTest("attrib-double", 4.0, attrib->DoubleValue(), true);
786 }
787
788 }
789
Uli Kusterer321072e2014-01-21 01:57:38 +0100790
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800791 // ---------- CDATA ---------------
792 {
793 const char* str = "<xmlElement>"
794 "<![CDATA["
795 "I am > the rules!\n"
796 "...since I make symbolic puns"
797 "]]>"
798 "</xmlElement>";
799 XMLDocument doc;
800 doc.Parse( str );
801 doc.Print();
Lee Thomasond6277762012-02-22 16:00:12 -0800802
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700803 XMLTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800804 "I am > the rules!\n...since I make symbolic puns",
Lee Thomasond6277762012-02-22 16:00:12 -0800805 false );
806 }
807
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800808 // ----------- CDATA -------------
809 {
810 const char* str = "<xmlElement>"
811 "<![CDATA["
812 "<b>I am > the rules!</b>\n"
813 "...since I make symbolic puns"
814 "]]>"
815 "</xmlElement>";
816 XMLDocument doc;
817 doc.Parse( str );
818 doc.Print();
819
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700820 XMLTest( "CDATA parse. [ tixml1:1480107 ]", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800821 "<b>I am > the rules!</b>\n...since I make symbolic puns",
822 false );
823 }
824
825 // InsertAfterChild causes crash.
826 {
827 // InsertBeforeChild and InsertAfterChild causes crash.
828 XMLDocument doc;
829 XMLElement* parent = doc.NewElement( "Parent" );
830 doc.InsertFirstChild( parent );
831
832 XMLElement* childText0 = doc.NewElement( "childText0" );
833 XMLElement* childText1 = doc.NewElement( "childText1" );
834
835 XMLNode* childNode0 = parent->InsertEndChild( childText0 );
836 XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
837
838 XMLTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent->LastChild() ), true );
839 }
Lee Thomasond6277762012-02-22 16:00:12 -0800840
841 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800842 // Entities not being written correctly.
843 // From Lynn Allen
Lee Thomasond6277762012-02-22 16:00:12 -0800844
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800845 const char* passages =
846 "<?xml version=\"1.0\" standalone=\"no\" ?>"
847 "<passages count=\"006\" formatversion=\"20020620\">"
848 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
849 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
850 "</passages>";
Lee Thomasond6277762012-02-22 16:00:12 -0800851
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800852 XMLDocument doc;
853 doc.Parse( passages );
854 XMLElement* psg = doc.RootElement()->FirstChildElement();
855 const char* context = psg->Attribute( "context" );
856 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 -0800857
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800858 XMLTest( "Entity transformation: read. ", expected, context, true );
Lee Thomasond6277762012-02-22 16:00:12 -0800859
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400860 FILE* textfile = fopen( "resources/out/textfile.txt", "w" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800861 if ( textfile )
862 {
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800863 XMLPrinter streamer( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800864 psg->Accept( &streamer );
865 fclose( textfile );
866 }
Thomas Roß0922b732012-09-23 16:31:22 +0200867
868 textfile = fopen( "resources/out/textfile.txt", "r" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800869 TIXMLASSERT( textfile );
870 if ( textfile )
871 {
872 char buf[ 1024 ];
873 fgets( buf, 1024, textfile );
874 XMLTest( "Entity transformation: write. ",
875 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
876 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
877 buf, false );
PKEuSc28ba3a2012-07-16 03:08:47 -0700878 fclose( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800879 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800880 }
881
882 {
Lee Thomason6f381b72012-03-02 12:59:39 -0800883 // Suppress entities.
884 const char* passages =
885 "<?xml version=\"1.0\" standalone=\"no\" ?>"
886 "<passages count=\"006\" formatversion=\"20020620\">"
887 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
888 "</passages>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700889
Lee Thomason6f381b72012-03-02 12:59:39 -0800890 XMLDocument doc( false );
891 doc.Parse( passages );
892
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700893 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ),
Lee Thomason6f381b72012-03-02 12:59:39 -0800894 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;." );
895 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value(),
896 "Crazy &ttk;" );
897 doc.Print();
898 }
899
900 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400901 const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800902
903 XMLDocument doc;
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400904 doc.Parse( test );
905 XMLTest( "dot in names", doc.Error(), false );
906 XMLTest( "dot in names", doc.FirstChildElement()->Name(), "a.elem" );
907 XMLTest( "dot in names", doc.FirstChildElement()->Attribute( "xmi.version" ), "2.0" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800908 }
909
910 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400911 const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800912
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400913 XMLDocument doc;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800914 doc.Parse( test );
915
916 XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
917 XMLTest( "Entity with one digit.",
918 text->Value(), "1.1 Start easy ignore fin thickness\n",
919 false );
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400920 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800921
922 {
923 // DOCTYPE not preserved (950171)
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700924 //
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800925 const char* doctype =
926 "<?xml version=\"1.0\" ?>"
927 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
928 "<!ELEMENT title (#PCDATA)>"
929 "<!ELEMENT books (title,authors)>"
930 "<element />";
931
932 XMLDocument doc;
933 doc.Parse( doctype );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400934 doc.SaveFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800935 doc.DeleteChild( doc.RootElement() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400936 doc.LoadFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800937 doc.Print();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700938
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800939 const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
940 XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
941
942 }
943
944 {
945 // Comments do not stream out correctly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700946 const char* doctype =
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800947 "<!-- Somewhat<evil> -->";
948 XMLDocument doc;
949 doc.Parse( doctype );
950
951 XMLComment* comment = doc.FirstChild()->ToComment();
952
953 XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
954 }
955 {
956 // Double attributes
957 const char* doctype = "<element attr='red' attr='blue' />";
958
959 XMLDocument doc;
960 doc.Parse( doctype );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700961
Lee Thomason2fa81722012-11-09 12:37:46 -0800962 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 -0800963 doc.PrintError();
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800964 }
965
966 {
967 // Embedded null in stream.
968 const char* doctype = "<element att\0r='red' attr='blue' />";
969
970 XMLDocument doc;
971 doc.Parse( doctype );
972 XMLTest( "Embedded null throws error.", true, doc.Error() );
973 }
974
975 {
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700976 // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
Dmitry-Me588bb8d2014-12-25 18:59:18 +0300977 const char* str = "";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800978 XMLDocument doc;
979 doc.Parse( str );
Lee Thomason2fa81722012-11-09 12:37:46 -0800980 XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800981 }
982
983 {
Dmitry-Me588bb8d2014-12-25 18:59:18 +0300984 // Documents with all whitespaces should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
985 const char* str = " ";
986 XMLDocument doc;
987 doc.Parse( str );
988 XMLTest( "All whitespaces document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
989 }
990
991 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800992 // Low entities
993 XMLDocument doc;
994 doc.Parse( "<test>&#x0e;</test>" );
995 const char result[] = { 0x0e, 0 };
996 XMLTest( "Low entities.", doc.FirstChildElement()->GetText(), result );
997 doc.Print();
998 }
999
1000 {
1001 // Attribute values with trailing quotes not handled correctly
1002 XMLDocument doc;
1003 doc.Parse( "<foo attribute=bar\" />" );
1004 XMLTest( "Throw error with bad end quotes.", doc.Error(), true );
1005 }
1006
1007 {
1008 // [ 1663758 ] Failure to report error on bad XML
1009 XMLDocument xml;
1010 xml.Parse("<x>");
1011 XMLTest("Missing end tag at end of input", xml.Error(), true);
1012 xml.Parse("<x> ");
1013 XMLTest("Missing end tag with trailing whitespace", xml.Error(), true);
1014 xml.Parse("<x></y>");
Lee Thomason2fa81722012-11-09 12:37:46 -08001015 XMLTest("Mismatched tags", xml.ErrorID(), XML_ERROR_MISMATCHED_ELEMENT);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001016 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001017
1018
1019 {
1020 // [ 1475201 ] TinyXML parses entities in comments
1021 XMLDocument xml;
1022 xml.Parse("<!-- declarations for <head> & <body> -->"
1023 "<!-- far &amp; away -->" );
1024
1025 XMLNode* e0 = xml.FirstChild();
1026 XMLNode* e1 = e0->NextSibling();
1027 XMLComment* c0 = e0->ToComment();
1028 XMLComment* c1 = e1->ToComment();
1029
1030 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
1031 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
1032 }
1033
1034 {
1035 XMLDocument xml;
1036 xml.Parse( "<Parent>"
1037 "<child1 att=''/>"
1038 "<!-- With this comment, child2 will not be parsed! -->"
1039 "<child2 att=''/>"
1040 "</Parent>" );
1041 xml.Print();
1042
1043 int count = 0;
1044
1045 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
1046 ele;
1047 ele = ele->NextSibling() )
1048 {
1049 ++count;
1050 }
1051
1052 XMLTest( "Comments iterate correctly.", 3, count );
1053 }
1054
1055 {
1056 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
1057 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
1058 buf[60] = 239;
1059 buf[61] = 0;
1060
1061 XMLDocument doc;
1062 doc.Parse( (const char*)buf);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001063 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001064
1065
1066 {
1067 // bug 1827248 Error while parsing a little bit malformed file
1068 // Actually not malformed - should work.
1069 XMLDocument xml;
1070 xml.Parse( "<attributelist> </attributelist >" );
1071 XMLTest( "Handle end tag whitespace", false, xml.Error() );
1072 }
1073
1074 {
1075 // This one must not result in an infinite loop
1076 XMLDocument xml;
1077 xml.Parse( "<infinite>loop" );
1078 XMLTest( "Infinite loop test.", true, true );
1079 }
1080#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001081 {
1082 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
1083 XMLDocument doc;
1084 doc.Parse( pub );
1085
1086 XMLDocument clone;
1087 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
1088 XMLNode* copy = node->ShallowClone( &clone );
1089 clone.InsertEndChild( copy );
1090 }
1091
1092 clone.Print();
1093
1094 int count=0;
1095 const XMLNode* a=clone.FirstChild();
1096 const XMLNode* b=doc.FirstChild();
1097 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
1098 ++count;
1099 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
1100 }
1101 XMLTest( "Clone and Equal", 4, count );
1102 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001103
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001104 {
1105 // This shouldn't crash.
1106 XMLDocument doc;
Lee Thomason85536252016-06-04 19:10:53 -07001107 if(XML_SUCCESS != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001108 {
1109 doc.PrintError();
1110 }
1111 XMLTest( "Error in snprinf handling.", true, doc.Error() );
1112 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001113
Lee Thomason5e3803c2012-04-16 08:57:05 -07001114 {
1115 // Attribute ordering.
1116 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
1117 XMLDocument doc;
1118 doc.Parse( xml );
1119 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001120
Lee Thomason5e3803c2012-04-16 08:57:05 -07001121 const XMLAttribute* a = ele->FirstAttribute();
1122 XMLTest( "Attribute order", "1", a->Value() );
1123 a = a->Next();
1124 XMLTest( "Attribute order", "2", a->Value() );
1125 a = a->Next();
1126 XMLTest( "Attribute order", "3", a->Value() );
1127 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001128
Lee Thomason5e3803c2012-04-16 08:57:05 -07001129 ele->DeleteAttribute( "attrib2" );
1130 a = ele->FirstAttribute();
1131 XMLTest( "Attribute order", "1", a->Value() );
1132 a = a->Next();
1133 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001134
Lee Thomason5e3803c2012-04-16 08:57:05 -07001135 ele->DeleteAttribute( "attrib1" );
1136 ele->DeleteAttribute( "attrib3" );
1137 XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
1138 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001139
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001140 {
1141 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -07001142 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
1143 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
1144 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
1145 XMLDocument doc0;
1146 doc0.Parse( xml0 );
1147 XMLDocument doc1;
1148 doc1.Parse( xml1 );
1149 XMLDocument doc2;
1150 doc2.Parse( xml2 );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001151
Lee Thomason78a773d2012-07-02 10:10:19 -07001152 XMLElement* ele = 0;
1153 ele = doc0.FirstChildElement();
1154 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
1155 ele = doc1.FirstChildElement();
1156 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
1157 ele = doc2.FirstChildElement();
1158 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001159 }
1160
1161 {
1162 // Make sure we don't go into an infinite loop.
1163 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
1164 XMLDocument doc;
1165 doc.Parse( xml );
1166 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
1167 XMLElement* ele1 = ele0->NextSiblingElement();
1168 bool equal = ele0->ShallowEqual( ele1 );
1169
1170 XMLTest( "Infinite loop in shallow equal.", true, equal );
1171 }
1172
Lee Thomason5708f812012-03-28 17:46:41 -07001173 // -------- Handles ------------
1174 {
1175 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1176 XMLDocument doc;
1177 doc.Parse( xml );
Lee Thomason5708f812012-03-28 17:46:41 -07001178
1179 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
1180 XMLTest( "Handle, success, mutable", ele->Value(), "sub" );
1181
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001182 XMLHandle docH( doc );
1183 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001184 XMLTest( "Handle, dne, mutable", false, ele != 0 );
Lee Thomason5708f812012-03-28 17:46:41 -07001185 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001186
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001187 {
1188 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1189 XMLDocument doc;
1190 doc.Parse( xml );
1191 XMLConstHandle docH( doc );
1192
1193 const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
1194 XMLTest( "Handle, success, const", ele->Value(), "sub" );
1195
1196 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001197 XMLTest( "Handle, dne, const", false, ele != 0 );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001198 }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001199 {
1200 // Default Declaration & BOM
1201 XMLDocument doc;
1202 doc.InsertEndChild( doc.NewDeclaration() );
1203 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001204
Lee Thomasonf68c4382012-04-28 14:37:11 -07001205 XMLPrinter printer;
1206 doc.Print( &printer );
1207
1208 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1209 XMLTest( "BOM and default declaration", printer.CStr(), result, false );
Lee Thomason (grinliz)48ea0bc2012-05-26 14:41:14 -07001210 XMLTest( "CStrSize", printer.CStrSize(), 42, false );
Lee Thomasonf68c4382012-04-28 14:37:11 -07001211 }
Lee Thomason21be8822012-07-15 17:27:22 -07001212 {
1213 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1214 XMLDocument doc;
1215 doc.Parse( xml );
1216 XMLTest( "Ill formed XML", true, doc.Error() );
1217 }
1218
1219 // QueryXYZText
1220 {
1221 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1222 XMLDocument doc;
1223 doc.Parse( xml );
1224
1225 const XMLElement* pointElement = doc.RootElement();
1226
1227 int intValue = 0;
1228 unsigned unsignedValue = 0;
1229 float floatValue = 0;
1230 double doubleValue = 0;
1231 bool boolValue = false;
1232
1233 pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1234 pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1235 pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1236 pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1237 pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1238
1239
1240 XMLTest( "QueryIntText", intValue, 1, false );
1241 XMLTest( "QueryUnsignedText", unsignedValue, (unsigned)1, false );
1242 XMLTest( "QueryFloatText", floatValue, 1.2f, false );
1243 XMLTest( "QueryDoubleText", doubleValue, 1.2, false );
1244 XMLTest( "QueryBoolText", boolValue, true, false );
1245 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001246
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001247 {
1248 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1249 XMLDocument doc;
1250 doc.Parse( xml );
1251 XMLTest( "Non-alpha element lead letter parses.", doc.Error(), false );
1252 }
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001253
1254 {
1255 const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1256 XMLDocument doc;
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001257 doc.Parse( xml );
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001258 XMLTest("Non-alpha attribute lead character parses.", doc.Error(), false);
1259 }
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001260
1261 {
1262 const char* xml = "<3lement></3lement>";
1263 XMLDocument doc;
1264 doc.Parse( xml );
1265 XMLTest("Element names with lead digit fail to parse.", doc.Error(), true);
1266 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -07001267
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001268 {
1269 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1270 XMLDocument doc;
1271 doc.Parse( xml, 10 );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001272 XMLTest( "Set length of incoming data", doc.Error(), false );
1273 }
1274
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001275 {
1276 XMLDocument doc;
Dmitry-Me48b5df02015-04-06 18:20:25 +03001277 XMLTest( "Document is initially empty", doc.NoChildren(), true );
1278 doc.Clear();
1279 XMLTest( "Empty is empty after Clear()", doc.NoChildren(), true );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001280 doc.LoadFile( "resources/dream.xml" );
Dmitry-Meaaa4cea2015-02-06 16:00:46 +03001281 XMLTest( "Document has something to Clear()", doc.NoChildren(), false );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001282 doc.Clear();
1283 XMLTest( "Document Clear()'s", doc.NoChildren(), true );
1284 }
1285
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001286 // ----------- Whitespace ------------
1287 {
1288 const char* xml = "<element>"
1289 "<a> This \nis &apos; text &apos; </a>"
1290 "<b> This is &apos; text &apos; \n</b>"
1291 "<c>This is &apos; \n\n text &apos;</c>"
1292 "</element>";
1293 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1294 doc.Parse( xml );
1295
1296 const XMLElement* element = doc.FirstChildElement();
1297 for( const XMLElement* parent = element->FirstChildElement();
1298 parent;
1299 parent = parent->NextSiblingElement() )
1300 {
1301 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1302 }
1303 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001304
Lee Thomasonae9ab072012-10-24 10:17:53 -07001305#if 0
1306 {
1307 // Passes if assert doesn't fire.
1308 XMLDocument xmlDoc;
1309
1310 xmlDoc.NewDeclaration();
1311 xmlDoc.NewComment("Configuration file");
1312
1313 XMLElement *root = xmlDoc.NewElement("settings");
1314 root->SetAttribute("version", 2);
1315 }
1316#endif
1317
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001318 {
1319 const char* xml = "<element> </element>";
1320 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1321 doc.Parse( xml );
1322 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1323 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001324
Lee Thomason5b0a6772012-11-19 13:54:42 -08001325 {
1326 // An assert should not fire.
1327 const char* xml = "<element/>";
1328 XMLDocument doc;
1329 doc.Parse( xml );
1330 XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope.
1331 XMLTest( "Tracking unused elements", true, ele != 0, false );
1332 }
1333
Lee Thomasona6412ac2012-12-13 15:39:11 -08001334
1335 {
1336 const char* xml = "<parent><child>abc</child></parent>";
1337 XMLDocument doc;
1338 doc.Parse( xml );
1339 XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
1340
1341 XMLPrinter printer;
1342 ele->Accept( &printer );
1343 XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1344 }
1345
1346
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001347 {
1348 XMLDocument doc;
1349 XMLError error = doc.LoadFile( "resources/empty.xml" );
1350 XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
Lee Thomason331596e2014-09-11 14:56:43 -07001351 XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() );
Lee Thomasonc7556672014-09-14 12:39:42 -07001352 doc.PrintError();
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001353 }
1354
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001355 {
1356 // BOM preservation
1357 static const char* xml_bom_preservation = "\xef\xbb\xbf<element/>\n";
1358 {
1359 XMLDocument doc;
Lee Thomason85536252016-06-04 19:10:53 -07001360 XMLTest( "BOM preservation (parse)", XML_SUCCESS, doc.Parse( xml_bom_preservation ), false );
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001361 XMLPrinter printer;
1362 doc.Print( &printer );
1363
1364 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1365 doc.SaveFile( "resources/bomtest.xml" );
1366 }
1367 {
1368 XMLDocument doc;
1369 doc.LoadFile( "resources/bomtest.xml" );
1370 XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
1371
1372 XMLPrinter printer;
1373 doc.Print( &printer );
1374 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1375 }
1376 }
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001377
Michael Daumlinged523282013-10-23 07:47:29 +02001378 {
1379 // Insertion with Removal
1380 const char* xml = "<?xml version=\"1.0\" ?>"
1381 "<root>"
1382 "<one>"
1383 "<subtree>"
1384 "<elem>element 1</elem>text<!-- comment -->"
1385 "</subtree>"
1386 "</one>"
1387 "<two/>"
1388 "</root>";
1389 const char* xmlInsideTwo = "<?xml version=\"1.0\" ?>"
1390 "<root>"
1391 "<one/>"
1392 "<two>"
1393 "<subtree>"
1394 "<elem>element 1</elem>text<!-- comment -->"
1395 "</subtree>"
1396 "</two>"
1397 "</root>";
1398 const char* xmlAfterOne = "<?xml version=\"1.0\" ?>"
1399 "<root>"
1400 "<one/>"
1401 "<subtree>"
1402 "<elem>element 1</elem>text<!-- comment -->"
1403 "</subtree>"
1404 "<two/>"
1405 "</root>";
1406 const char* xmlAfterTwo = "<?xml version=\"1.0\" ?>"
1407 "<root>"
1408 "<one/>"
1409 "<two/>"
1410 "<subtree>"
1411 "<elem>element 1</elem>text<!-- comment -->"
1412 "</subtree>"
1413 "</root>";
1414
1415 XMLDocument doc;
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001416 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001417 XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1418 XMLElement* two = doc.RootElement()->FirstChildElement("two");
1419 two->InsertFirstChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001420 XMLPrinter printer1(0, true);
1421 doc.Accept(&printer1);
1422 XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
Michael Daumlinged523282013-10-23 07:47:29 +02001423
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001424 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001425 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1426 two = doc.RootElement()->FirstChildElement("two");
1427 doc.RootElement()->InsertAfterChild(two, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001428 XMLPrinter printer2(0, true);
1429 doc.Accept(&printer2);
1430 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001431
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001432 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001433 XMLNode* one = doc.RootElement()->FirstChildElement("one");
1434 subtree = one->FirstChildElement("subtree");
1435 doc.RootElement()->InsertAfterChild(one, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001436 XMLPrinter printer3(0, true);
1437 doc.Accept(&printer3);
1438 XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001439
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001440 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001441 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1442 two = doc.RootElement()->FirstChildElement("two");
1443 doc.RootElement()->InsertEndChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001444 XMLPrinter printer4(0, true);
1445 doc.Accept(&printer4);
1446 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001447 }
1448
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001449 {
1450 const char* xml = "<svg width = \"128\" height = \"128\">"
1451 " <text> </text>"
1452 "</svg>";
1453 XMLDocument doc;
1454 doc.Parse(xml);
1455 doc.Print();
1456 }
1457
Lee Thomason92e521b2014-11-15 17:45:51 -08001458 {
1459 // Test that it doesn't crash.
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001460 const char* xml = "<?xml version=\"1.0\"?><root><sample><field0><1</field0><field1>2</field1></sample></root>";
1461 XMLDocument doc;
1462 doc.Parse(xml);
1463 doc.PrintError();
Lee Thomason92e521b2014-11-15 17:45:51 -08001464 }
1465
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001466#if 1
1467 // the question being explored is what kind of print to use:
1468 // https://github.com/leethomason/tinyxml2/issues/63
1469 {
1470 //const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
1471 const char* xml = "<element/>";
1472 XMLDocument doc;
1473 doc.Parse( xml );
1474 doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
1475 doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
1476 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
1477 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
1478 doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
1479 doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
1480
1481 doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
1482 doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
1483 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
1484 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
1485 doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
1486 doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
1487
1488 doc.Print();
1489
1490 /* The result of this test is platform, compiler, and library version dependent. :("
1491 XMLPrinter printer;
1492 doc.Print( &printer );
1493 XMLTest( "Float and double formatting.",
1494 "<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",
1495 printer.CStr(),
1496 true );
1497 */
1498 }
1499#endif
Lee Thomasonf07b9522014-10-30 13:25:12 -07001500
1501 {
1502 // Issue #184
1503 // If it doesn't assert, it passes. Caused by objects
1504 // getting created during parsing which are then
1505 // inaccessible in the memory pools.
1506 {
1507 XMLDocument doc;
1508 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1509 }
1510 {
1511 XMLDocument doc;
1512 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1513 doc.Clear();
1514 }
1515 }
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001516
1517 {
1518 // If this doesn't assert in DEBUG, all is well.
1519 tinyxml2::XMLDocument doc;
1520 tinyxml2::XMLElement *pRoot = doc.NewElement("Root");
1521 doc.DeleteNode(pRoot);
1522 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001523
Dmitry-Me8b67d742014-12-22 11:35:12 +03001524 {
1525 // Should not assert in DEBUG
1526 XMLPrinter printer;
1527 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001528
Dmitry-Me6f51c802015-03-14 13:25:03 +03001529 {
1530 // Issue 291. Should not crash
1531 const char* xml = "&#0</a>";
1532 XMLDocument doc;
1533 doc.Parse( xml );
1534
1535 XMLPrinter printer;
1536 doc.Print( &printer );
1537 }
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001538 {
1539 // Issue 299. Can print elements that are not linked in.
1540 // Will crash if issue not fixed.
1541 XMLDocument doc;
1542 XMLElement* newElement = doc.NewElement( "printme" );
1543 XMLPrinter printer;
1544 newElement->Accept( &printer );
Dmitry-Me5daa54c2015-04-08 17:45:07 +03001545 // Delete the node to avoid possible memory leak report in debug output
1546 doc.DeleteNode( newElement );
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001547 }
Lee Thomasonf6577832015-03-26 11:18:21 -07001548 {
Ant Mitchell189198f2015-03-24 16:20:36 +00001549 // Issue 302. Clear errors from LoadFile/SaveFile
1550 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001551 XMLTest( "Issue 302. Should be no error initially", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001552 doc.SaveFile( "./no/such/path/pretty.xml" );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001553 XMLTest( "Issue 302. Fail to save", "XML_ERROR_FILE_COULD_NOT_BE_OPENED", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001554 doc.SaveFile( "./resources/out/compact.xml", true );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001555 XMLTest( "Issue 302. Subsequent success in saving", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001556 }
Dmitry-Me6f51c802015-03-14 13:25:03 +03001557
Dmitry-Med9852a52015-03-25 10:17:49 +03001558 {
1559 // If a document fails to load then subsequent
1560 // successful loads should clear the error
1561 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001562 XMLTest( "Should be no error initially", false, doc.Error() );
Dmitry-Med9852a52015-03-25 10:17:49 +03001563 doc.LoadFile( "resources/no-such-file.xml" );
1564 XMLTest( "No such file - should fail", true, doc.Error() );
1565
1566 doc.LoadFile( "resources/dream.xml" );
1567 XMLTest( "Error should be cleared", false, doc.Error() );
1568 }
Sarat Addepalli8e85afa2015-05-19 09:07:03 +05301569
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301570 {
1571 // Check that declarations are parsed only as the FirstChild
Lee Thomason85492022015-05-22 11:07:45 -07001572 const char* xml0 = "<?xml version=\"1.0\" ?>"
1573 " <!-- xml version=\"1.1\" -->"
1574 "<first />";
1575 const char* xml1 = "<?xml version=\"1.0\" ?>"
1576 " <?xml version=\"1.1\" ?>"
1577 "<first />";
1578 const char* xml2 = "<first />"
1579 "<?xml version=\"1.0\" ?>";
1580 XMLDocument doc;
1581 doc.Parse(xml0);
1582 XMLTest("Test that the code changes do not affect normal parsing", doc.Error(), false);
1583 doc.Parse(xml1);
1584 XMLTest("Test that the second declaration throws an error", doc.ErrorID(), XML_ERROR_PARSING_DECLARATION);
1585 doc.Parse(xml2);
1586 XMLTest("Test that declaration after a child throws an error", doc.ErrorID(), XML_ERROR_PARSING_DECLARATION);
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301587 }
Dmitry-Med9852a52015-03-25 10:17:49 +03001588
Lee Thomason85492022015-05-22 11:07:45 -07001589 {
1590 // No matter - before or after successfully parsing a text -
1591 // calling XMLDocument::Value() causes an assert in debug.
1592 const char* validXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
1593 "<first />"
1594 "<second />";
1595 XMLDocument* doc = new XMLDocument();
1596 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1597 doc->Parse( validXml );
1598 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1599 delete doc;
1600 }
1601
Dmitry-Mea1beddf2015-05-26 16:19:21 +03001602 {
1603 XMLDocument doc;
1604 for( int i = 0; i < XML_ERROR_COUNT; i++ ) {
1605 doc.SetError( (XMLError)i, 0, 0 );
1606 doc.ErrorName();
1607 }
1608 }
1609
Lee Thomason85492022015-05-22 11:07:45 -07001610 // ----------- Performance tracking --------------
Lee Thomason6f381b72012-03-02 12:59:39 -08001611 {
1612#if defined( _MSC_VER )
1613 __int64 start, end, freq;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001614 QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
Lee Thomason6f381b72012-03-02 12:59:39 -08001615#endif
1616
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001617 FILE* perfFP = fopen("resources/dream.xml", "r");
1618 fseek(perfFP, 0, SEEK_END);
1619 long size = ftell(fp);
1620 fseek(perfFP, 0, SEEK_SET);
Lee Thomason6f381b72012-03-02 12:59:39 -08001621
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001622 char* mem = new char[size + 1];
1623 fread(mem, size, 1, perfFP);
1624 fclose(perfFP);
Lee Thomason6f381b72012-03-02 12:59:39 -08001625 mem[size] = 0;
1626
1627#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001628 QueryPerformanceCounter((LARGE_INTEGER*)&start);
Lee Thomason6f381b72012-03-02 12:59:39 -08001629#else
1630 clock_t cstart = clock();
1631#endif
1632 static const int COUNT = 10;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001633 for (int i = 0; i < COUNT; ++i) {
Lee Thomason6f381b72012-03-02 12:59:39 -08001634 XMLDocument doc;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001635 doc.Parse(mem);
Lee Thomason6f381b72012-03-02 12:59:39 -08001636 }
1637#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001638 QueryPerformanceCounter((LARGE_INTEGER*)&end);
Lee Thomason6f381b72012-03-02 12:59:39 -08001639#else
1640 clock_t cend = clock();
1641#endif
1642
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001643 delete[] mem;
Lee Thomason6f381b72012-03-02 12:59:39 -08001644
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001645 static const char* note =
Lee Thomason6f381b72012-03-02 12:59:39 -08001646#ifdef DEBUG
1647 "DEBUG";
1648#else
1649 "Release";
1650#endif
1651
1652#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001653 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 -08001654#else
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001655 printf("\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart) / (double)COUNT);
Lee Thomason6f381b72012-03-02 12:59:39 -08001656#endif
1657 }
1658
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -08001659 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001660 _CrtMemCheckpoint( &endMemState );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001661
1662 _CrtMemState diffMemState;
1663 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
1664 _CrtMemDumpStatistics( &diffMemState );
1665 #endif
1666
1667 printf ("\nPass %d, Fail %d\n", gPass, gFail);
Lee Thomason (grinliz)db304252013-07-31 12:24:52 -07001668
1669 return gFail;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08001670}