blob: 5e0eb3aecb56b73134f65c7b2cdaf3ea196ae83a [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 Thomason21be8822012-07-15 17:27:22 -0700516 XMLTest( "Query attribute: int as double", result, (int)XML_NO_ERROR );
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 );
Thomas Roßa5221862013-05-11 10:22:12 +0200519 XMLTest( "Query attribute: double as double", result, (int)XML_NO_ERROR );
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 Thomason21be8822012-07-15 17:27:22 -0700522 XMLTest( "Query attribute: double as int", result, (int)XML_NO_ERROR );
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
689
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800690 // ---------- CDATA ---------------
691 {
692 const char* str = "<xmlElement>"
693 "<![CDATA["
694 "I am > the rules!\n"
695 "...since I make symbolic puns"
696 "]]>"
697 "</xmlElement>";
698 XMLDocument doc;
699 doc.Parse( str );
700 doc.Print();
Lee Thomasond6277762012-02-22 16:00:12 -0800701
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700702 XMLTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800703 "I am > the rules!\n...since I make symbolic puns",
Lee Thomasond6277762012-02-22 16:00:12 -0800704 false );
705 }
706
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800707 // ----------- CDATA -------------
708 {
709 const char* str = "<xmlElement>"
710 "<![CDATA["
711 "<b>I am > the rules!</b>\n"
712 "...since I make symbolic puns"
713 "]]>"
714 "</xmlElement>";
715 XMLDocument doc;
716 doc.Parse( str );
717 doc.Print();
718
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700719 XMLTest( "CDATA parse. [ tixml1:1480107 ]", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800720 "<b>I am > the rules!</b>\n...since I make symbolic puns",
721 false );
722 }
723
724 // InsertAfterChild causes crash.
725 {
726 // InsertBeforeChild and InsertAfterChild causes crash.
727 XMLDocument doc;
728 XMLElement* parent = doc.NewElement( "Parent" );
729 doc.InsertFirstChild( parent );
730
731 XMLElement* childText0 = doc.NewElement( "childText0" );
732 XMLElement* childText1 = doc.NewElement( "childText1" );
733
734 XMLNode* childNode0 = parent->InsertEndChild( childText0 );
735 XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
736
737 XMLTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent->LastChild() ), true );
738 }
Lee Thomasond6277762012-02-22 16:00:12 -0800739
740 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800741 // Entities not being written correctly.
742 // From Lynn Allen
Lee Thomasond6277762012-02-22 16:00:12 -0800743
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800744 const char* passages =
745 "<?xml version=\"1.0\" standalone=\"no\" ?>"
746 "<passages count=\"006\" formatversion=\"20020620\">"
747 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
748 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
749 "</passages>";
Lee Thomasond6277762012-02-22 16:00:12 -0800750
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800751 XMLDocument doc;
752 doc.Parse( passages );
753 XMLElement* psg = doc.RootElement()->FirstChildElement();
754 const char* context = psg->Attribute( "context" );
755 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 -0800756
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800757 XMLTest( "Entity transformation: read. ", expected, context, true );
Lee Thomasond6277762012-02-22 16:00:12 -0800758
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400759 FILE* textfile = fopen( "resources/out/textfile.txt", "w" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800760 if ( textfile )
761 {
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800762 XMLPrinter streamer( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800763 psg->Accept( &streamer );
764 fclose( textfile );
765 }
Thomas Roß0922b732012-09-23 16:31:22 +0200766
767 textfile = fopen( "resources/out/textfile.txt", "r" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800768 TIXMLASSERT( textfile );
769 if ( textfile )
770 {
771 char buf[ 1024 ];
772 fgets( buf, 1024, textfile );
773 XMLTest( "Entity transformation: write. ",
774 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
775 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
776 buf, false );
PKEuSc28ba3a2012-07-16 03:08:47 -0700777 fclose( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800778 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800779 }
780
781 {
Lee Thomason6f381b72012-03-02 12:59:39 -0800782 // Suppress entities.
783 const char* passages =
784 "<?xml version=\"1.0\" standalone=\"no\" ?>"
785 "<passages count=\"006\" formatversion=\"20020620\">"
786 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
787 "</passages>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700788
Lee Thomason6f381b72012-03-02 12:59:39 -0800789 XMLDocument doc( false );
790 doc.Parse( passages );
791
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700792 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ),
Lee Thomason6f381b72012-03-02 12:59:39 -0800793 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;." );
794 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value(),
795 "Crazy &ttk;" );
796 doc.Print();
797 }
798
799 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400800 const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800801
802 XMLDocument doc;
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400803 doc.Parse( test );
804 XMLTest( "dot in names", doc.Error(), false );
805 XMLTest( "dot in names", doc.FirstChildElement()->Name(), "a.elem" );
806 XMLTest( "dot in names", doc.FirstChildElement()->Attribute( "xmi.version" ), "2.0" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800807 }
808
809 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400810 const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800811
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400812 XMLDocument doc;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800813 doc.Parse( test );
814
815 XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
816 XMLTest( "Entity with one digit.",
817 text->Value(), "1.1 Start easy ignore fin thickness\n",
818 false );
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400819 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800820
821 {
822 // DOCTYPE not preserved (950171)
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700823 //
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800824 const char* doctype =
825 "<?xml version=\"1.0\" ?>"
826 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
827 "<!ELEMENT title (#PCDATA)>"
828 "<!ELEMENT books (title,authors)>"
829 "<element />";
830
831 XMLDocument doc;
832 doc.Parse( doctype );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400833 doc.SaveFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800834 doc.DeleteChild( doc.RootElement() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400835 doc.LoadFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800836 doc.Print();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700837
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800838 const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
839 XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
840
841 }
842
843 {
844 // Comments do not stream out correctly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700845 const char* doctype =
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800846 "<!-- Somewhat<evil> -->";
847 XMLDocument doc;
848 doc.Parse( doctype );
849
850 XMLComment* comment = doc.FirstChild()->ToComment();
851
852 XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
853 }
854 {
855 // Double attributes
856 const char* doctype = "<element attr='red' attr='blue' />";
857
858 XMLDocument doc;
859 doc.Parse( doctype );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700860
Lee Thomason2fa81722012-11-09 12:37:46 -0800861 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 -0800862 doc.PrintError();
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800863 }
864
865 {
866 // Embedded null in stream.
867 const char* doctype = "<element att\0r='red' attr='blue' />";
868
869 XMLDocument doc;
870 doc.Parse( doctype );
871 XMLTest( "Embedded null throws error.", true, doc.Error() );
872 }
873
874 {
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700875 // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
Dmitry-Me588bb8d2014-12-25 18:59:18 +0300876 const char* str = "";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800877 XMLDocument doc;
878 doc.Parse( str );
Lee Thomason2fa81722012-11-09 12:37:46 -0800879 XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800880 }
881
882 {
Dmitry-Me588bb8d2014-12-25 18:59:18 +0300883 // Documents with all whitespaces should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
884 const char* str = " ";
885 XMLDocument doc;
886 doc.Parse( str );
887 XMLTest( "All whitespaces document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
888 }
889
890 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800891 // Low entities
892 XMLDocument doc;
893 doc.Parse( "<test>&#x0e;</test>" );
894 const char result[] = { 0x0e, 0 };
895 XMLTest( "Low entities.", doc.FirstChildElement()->GetText(), result );
896 doc.Print();
897 }
898
899 {
900 // Attribute values with trailing quotes not handled correctly
901 XMLDocument doc;
902 doc.Parse( "<foo attribute=bar\" />" );
903 XMLTest( "Throw error with bad end quotes.", doc.Error(), true );
904 }
905
906 {
907 // [ 1663758 ] Failure to report error on bad XML
908 XMLDocument xml;
909 xml.Parse("<x>");
910 XMLTest("Missing end tag at end of input", xml.Error(), true);
911 xml.Parse("<x> ");
912 XMLTest("Missing end tag with trailing whitespace", xml.Error(), true);
913 xml.Parse("<x></y>");
Lee Thomason2fa81722012-11-09 12:37:46 -0800914 XMLTest("Mismatched tags", xml.ErrorID(), XML_ERROR_MISMATCHED_ELEMENT);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700915 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800916
917
918 {
919 // [ 1475201 ] TinyXML parses entities in comments
920 XMLDocument xml;
921 xml.Parse("<!-- declarations for <head> & <body> -->"
922 "<!-- far &amp; away -->" );
923
924 XMLNode* e0 = xml.FirstChild();
925 XMLNode* e1 = e0->NextSibling();
926 XMLComment* c0 = e0->ToComment();
927 XMLComment* c1 = e1->ToComment();
928
929 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
930 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
931 }
932
933 {
934 XMLDocument xml;
935 xml.Parse( "<Parent>"
936 "<child1 att=''/>"
937 "<!-- With this comment, child2 will not be parsed! -->"
938 "<child2 att=''/>"
939 "</Parent>" );
940 xml.Print();
941
942 int count = 0;
943
944 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
945 ele;
946 ele = ele->NextSibling() )
947 {
948 ++count;
949 }
950
951 XMLTest( "Comments iterate correctly.", 3, count );
952 }
953
954 {
955 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
956 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
957 buf[60] = 239;
958 buf[61] = 0;
959
960 XMLDocument doc;
961 doc.Parse( (const char*)buf);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700962 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800963
964
965 {
966 // bug 1827248 Error while parsing a little bit malformed file
967 // Actually not malformed - should work.
968 XMLDocument xml;
969 xml.Parse( "<attributelist> </attributelist >" );
970 XMLTest( "Handle end tag whitespace", false, xml.Error() );
971 }
972
973 {
974 // This one must not result in an infinite loop
975 XMLDocument xml;
976 xml.Parse( "<infinite>loop" );
977 XMLTest( "Infinite loop test.", true, true );
978 }
979#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800980 {
981 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
982 XMLDocument doc;
983 doc.Parse( pub );
984
985 XMLDocument clone;
986 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
987 XMLNode* copy = node->ShallowClone( &clone );
988 clone.InsertEndChild( copy );
989 }
990
991 clone.Print();
992
993 int count=0;
994 const XMLNode* a=clone.FirstChild();
995 const XMLNode* b=doc.FirstChild();
996 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
997 ++count;
998 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
999 }
1000 XMLTest( "Clone and Equal", 4, count );
1001 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001002
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001003 {
1004 // This shouldn't crash.
1005 XMLDocument doc;
1006 if(XML_NO_ERROR != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
1007 {
1008 doc.PrintError();
1009 }
1010 XMLTest( "Error in snprinf handling.", true, doc.Error() );
1011 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001012
Lee Thomason5e3803c2012-04-16 08:57:05 -07001013 {
1014 // Attribute ordering.
1015 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
1016 XMLDocument doc;
1017 doc.Parse( xml );
1018 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001019
Lee Thomason5e3803c2012-04-16 08:57:05 -07001020 const XMLAttribute* a = ele->FirstAttribute();
1021 XMLTest( "Attribute order", "1", a->Value() );
1022 a = a->Next();
1023 XMLTest( "Attribute order", "2", a->Value() );
1024 a = a->Next();
1025 XMLTest( "Attribute order", "3", a->Value() );
1026 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001027
Lee Thomason5e3803c2012-04-16 08:57:05 -07001028 ele->DeleteAttribute( "attrib2" );
1029 a = ele->FirstAttribute();
1030 XMLTest( "Attribute order", "1", a->Value() );
1031 a = a->Next();
1032 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001033
Lee Thomason5e3803c2012-04-16 08:57:05 -07001034 ele->DeleteAttribute( "attrib1" );
1035 ele->DeleteAttribute( "attrib3" );
1036 XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
1037 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001038
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001039 {
1040 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -07001041 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
1042 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
1043 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
1044 XMLDocument doc0;
1045 doc0.Parse( xml0 );
1046 XMLDocument doc1;
1047 doc1.Parse( xml1 );
1048 XMLDocument doc2;
1049 doc2.Parse( xml2 );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001050
Lee Thomason78a773d2012-07-02 10:10:19 -07001051 XMLElement* ele = 0;
1052 ele = doc0.FirstChildElement();
1053 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
1054 ele = doc1.FirstChildElement();
1055 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
1056 ele = doc2.FirstChildElement();
1057 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001058 }
1059
1060 {
1061 // Make sure we don't go into an infinite loop.
1062 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
1063 XMLDocument doc;
1064 doc.Parse( xml );
1065 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
1066 XMLElement* ele1 = ele0->NextSiblingElement();
1067 bool equal = ele0->ShallowEqual( ele1 );
1068
1069 XMLTest( "Infinite loop in shallow equal.", true, equal );
1070 }
1071
Lee Thomason5708f812012-03-28 17:46:41 -07001072 // -------- Handles ------------
1073 {
1074 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1075 XMLDocument doc;
1076 doc.Parse( xml );
Lee Thomason5708f812012-03-28 17:46:41 -07001077
1078 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
1079 XMLTest( "Handle, success, mutable", ele->Value(), "sub" );
1080
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001081 XMLHandle docH( doc );
1082 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001083 XMLTest( "Handle, dne, mutable", false, ele != 0 );
Lee Thomason5708f812012-03-28 17:46:41 -07001084 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001085
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001086 {
1087 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1088 XMLDocument doc;
1089 doc.Parse( xml );
1090 XMLConstHandle docH( doc );
1091
1092 const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
1093 XMLTest( "Handle, success, const", ele->Value(), "sub" );
1094
1095 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001096 XMLTest( "Handle, dne, const", false, ele != 0 );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001097 }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001098 {
1099 // Default Declaration & BOM
1100 XMLDocument doc;
1101 doc.InsertEndChild( doc.NewDeclaration() );
1102 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001103
Lee Thomasonf68c4382012-04-28 14:37:11 -07001104 XMLPrinter printer;
1105 doc.Print( &printer );
1106
1107 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1108 XMLTest( "BOM and default declaration", printer.CStr(), result, false );
Lee Thomason (grinliz)48ea0bc2012-05-26 14:41:14 -07001109 XMLTest( "CStrSize", printer.CStrSize(), 42, false );
Lee Thomasonf68c4382012-04-28 14:37:11 -07001110 }
Lee Thomason21be8822012-07-15 17:27:22 -07001111 {
1112 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1113 XMLDocument doc;
1114 doc.Parse( xml );
1115 XMLTest( "Ill formed XML", true, doc.Error() );
1116 }
1117
1118 // QueryXYZText
1119 {
1120 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1121 XMLDocument doc;
1122 doc.Parse( xml );
1123
1124 const XMLElement* pointElement = doc.RootElement();
1125
1126 int intValue = 0;
1127 unsigned unsignedValue = 0;
1128 float floatValue = 0;
1129 double doubleValue = 0;
1130 bool boolValue = false;
1131
1132 pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1133 pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1134 pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1135 pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1136 pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1137
1138
1139 XMLTest( "QueryIntText", intValue, 1, false );
1140 XMLTest( "QueryUnsignedText", unsignedValue, (unsigned)1, false );
1141 XMLTest( "QueryFloatText", floatValue, 1.2f, false );
1142 XMLTest( "QueryDoubleText", doubleValue, 1.2, false );
1143 XMLTest( "QueryBoolText", boolValue, true, false );
1144 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001145
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001146 {
1147 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1148 XMLDocument doc;
1149 doc.Parse( xml );
1150 XMLTest( "Non-alpha element lead letter parses.", doc.Error(), false );
1151 }
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001152
1153 {
1154 const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1155 XMLDocument doc;
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001156 doc.Parse( xml );
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001157 XMLTest("Non-alpha attribute lead character parses.", doc.Error(), false);
1158 }
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001159
1160 {
1161 const char* xml = "<3lement></3lement>";
1162 XMLDocument doc;
1163 doc.Parse( xml );
1164 XMLTest("Element names with lead digit fail to parse.", doc.Error(), true);
1165 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -07001166
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001167 {
1168 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1169 XMLDocument doc;
1170 doc.Parse( xml, 10 );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001171 XMLTest( "Set length of incoming data", doc.Error(), false );
1172 }
1173
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001174 {
1175 XMLDocument doc;
Dmitry-Me48b5df02015-04-06 18:20:25 +03001176 XMLTest( "Document is initially empty", doc.NoChildren(), true );
1177 doc.Clear();
1178 XMLTest( "Empty is empty after Clear()", doc.NoChildren(), true );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001179 doc.LoadFile( "resources/dream.xml" );
Dmitry-Meaaa4cea2015-02-06 16:00:46 +03001180 XMLTest( "Document has something to Clear()", doc.NoChildren(), false );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001181 doc.Clear();
1182 XMLTest( "Document Clear()'s", doc.NoChildren(), true );
1183 }
1184
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001185 // ----------- Whitespace ------------
1186 {
1187 const char* xml = "<element>"
1188 "<a> This \nis &apos; text &apos; </a>"
1189 "<b> This is &apos; text &apos; \n</b>"
1190 "<c>This is &apos; \n\n text &apos;</c>"
1191 "</element>";
1192 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1193 doc.Parse( xml );
1194
1195 const XMLElement* element = doc.FirstChildElement();
1196 for( const XMLElement* parent = element->FirstChildElement();
1197 parent;
1198 parent = parent->NextSiblingElement() )
1199 {
1200 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1201 }
1202 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001203
Lee Thomasonae9ab072012-10-24 10:17:53 -07001204#if 0
1205 {
1206 // Passes if assert doesn't fire.
1207 XMLDocument xmlDoc;
1208
1209 xmlDoc.NewDeclaration();
1210 xmlDoc.NewComment("Configuration file");
1211
1212 XMLElement *root = xmlDoc.NewElement("settings");
1213 root->SetAttribute("version", 2);
1214 }
1215#endif
1216
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001217 {
1218 const char* xml = "<element> </element>";
1219 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1220 doc.Parse( xml );
1221 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1222 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001223
Lee Thomason5b0a6772012-11-19 13:54:42 -08001224 {
1225 // An assert should not fire.
1226 const char* xml = "<element/>";
1227 XMLDocument doc;
1228 doc.Parse( xml );
1229 XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope.
1230 XMLTest( "Tracking unused elements", true, ele != 0, false );
1231 }
1232
Lee Thomasona6412ac2012-12-13 15:39:11 -08001233
1234 {
1235 const char* xml = "<parent><child>abc</child></parent>";
1236 XMLDocument doc;
1237 doc.Parse( xml );
1238 XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
1239
1240 XMLPrinter printer;
1241 ele->Accept( &printer );
1242 XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1243 }
1244
1245
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001246 {
1247 XMLDocument doc;
1248 XMLError error = doc.LoadFile( "resources/empty.xml" );
1249 XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
Lee Thomason331596e2014-09-11 14:56:43 -07001250 XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() );
Lee Thomasonc7556672014-09-14 12:39:42 -07001251 doc.PrintError();
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001252 }
1253
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001254 {
1255 // BOM preservation
1256 static const char* xml_bom_preservation = "\xef\xbb\xbf<element/>\n";
1257 {
1258 XMLDocument doc;
1259 XMLTest( "BOM preservation (parse)", XML_NO_ERROR, doc.Parse( xml_bom_preservation ), false );
1260 XMLPrinter printer;
1261 doc.Print( &printer );
1262
1263 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1264 doc.SaveFile( "resources/bomtest.xml" );
1265 }
1266 {
1267 XMLDocument doc;
1268 doc.LoadFile( "resources/bomtest.xml" );
1269 XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
1270
1271 XMLPrinter printer;
1272 doc.Print( &printer );
1273 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1274 }
1275 }
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001276
Michael Daumlinged523282013-10-23 07:47:29 +02001277 {
1278 // Insertion with Removal
1279 const char* xml = "<?xml version=\"1.0\" ?>"
1280 "<root>"
1281 "<one>"
1282 "<subtree>"
1283 "<elem>element 1</elem>text<!-- comment -->"
1284 "</subtree>"
1285 "</one>"
1286 "<two/>"
1287 "</root>";
1288 const char* xmlInsideTwo = "<?xml version=\"1.0\" ?>"
1289 "<root>"
1290 "<one/>"
1291 "<two>"
1292 "<subtree>"
1293 "<elem>element 1</elem>text<!-- comment -->"
1294 "</subtree>"
1295 "</two>"
1296 "</root>";
1297 const char* xmlAfterOne = "<?xml version=\"1.0\" ?>"
1298 "<root>"
1299 "<one/>"
1300 "<subtree>"
1301 "<elem>element 1</elem>text<!-- comment -->"
1302 "</subtree>"
1303 "<two/>"
1304 "</root>";
1305 const char* xmlAfterTwo = "<?xml version=\"1.0\" ?>"
1306 "<root>"
1307 "<one/>"
1308 "<two/>"
1309 "<subtree>"
1310 "<elem>element 1</elem>text<!-- comment -->"
1311 "</subtree>"
1312 "</root>";
1313
1314 XMLDocument doc;
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001315 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001316 XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1317 XMLElement* two = doc.RootElement()->FirstChildElement("two");
1318 two->InsertFirstChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001319 XMLPrinter printer1(0, true);
1320 doc.Accept(&printer1);
1321 XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
Michael Daumlinged523282013-10-23 07:47:29 +02001322
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001323 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001324 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1325 two = doc.RootElement()->FirstChildElement("two");
1326 doc.RootElement()->InsertAfterChild(two, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001327 XMLPrinter printer2(0, true);
1328 doc.Accept(&printer2);
1329 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001330
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001331 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001332 XMLNode* one = doc.RootElement()->FirstChildElement("one");
1333 subtree = one->FirstChildElement("subtree");
1334 doc.RootElement()->InsertAfterChild(one, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001335 XMLPrinter printer3(0, true);
1336 doc.Accept(&printer3);
1337 XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001338
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001339 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001340 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1341 two = doc.RootElement()->FirstChildElement("two");
1342 doc.RootElement()->InsertEndChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001343 XMLPrinter printer4(0, true);
1344 doc.Accept(&printer4);
1345 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001346 }
1347
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001348 {
1349 const char* xml = "<svg width = \"128\" height = \"128\">"
1350 " <text> </text>"
1351 "</svg>";
1352 XMLDocument doc;
1353 doc.Parse(xml);
1354 doc.Print();
1355 }
1356
Lee Thomason92e521b2014-11-15 17:45:51 -08001357 {
1358 // Test that it doesn't crash.
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001359 const char* xml = "<?xml version=\"1.0\"?><root><sample><field0><1</field0><field1>2</field1></sample></root>";
1360 XMLDocument doc;
1361 doc.Parse(xml);
1362 doc.PrintError();
Lee Thomason92e521b2014-11-15 17:45:51 -08001363 }
1364
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001365#if 1
1366 // the question being explored is what kind of print to use:
1367 // https://github.com/leethomason/tinyxml2/issues/63
1368 {
1369 //const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
1370 const char* xml = "<element/>";
1371 XMLDocument doc;
1372 doc.Parse( xml );
1373 doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
1374 doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
1375 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
1376 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
1377 doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
1378 doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
1379
1380 doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
1381 doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
1382 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
1383 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
1384 doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
1385 doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
1386
1387 doc.Print();
1388
1389 /* The result of this test is platform, compiler, and library version dependent. :("
1390 XMLPrinter printer;
1391 doc.Print( &printer );
1392 XMLTest( "Float and double formatting.",
1393 "<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",
1394 printer.CStr(),
1395 true );
1396 */
1397 }
1398#endif
Lee Thomasonf07b9522014-10-30 13:25:12 -07001399
1400 {
1401 // Issue #184
1402 // If it doesn't assert, it passes. Caused by objects
1403 // getting created during parsing which are then
1404 // inaccessible in the memory pools.
1405 {
1406 XMLDocument doc;
1407 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1408 }
1409 {
1410 XMLDocument doc;
1411 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1412 doc.Clear();
1413 }
1414 }
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001415
1416 {
1417 // If this doesn't assert in DEBUG, all is well.
1418 tinyxml2::XMLDocument doc;
1419 tinyxml2::XMLElement *pRoot = doc.NewElement("Root");
1420 doc.DeleteNode(pRoot);
1421 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001422
Dmitry-Me8b67d742014-12-22 11:35:12 +03001423 {
1424 // Should not assert in DEBUG
1425 XMLPrinter printer;
1426 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001427
Dmitry-Me6f51c802015-03-14 13:25:03 +03001428 {
1429 // Issue 291. Should not crash
1430 const char* xml = "&#0</a>";
1431 XMLDocument doc;
1432 doc.Parse( xml );
1433
1434 XMLPrinter printer;
1435 doc.Print( &printer );
1436 }
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001437 {
1438 // Issue 299. Can print elements that are not linked in.
1439 // Will crash if issue not fixed.
1440 XMLDocument doc;
1441 XMLElement* newElement = doc.NewElement( "printme" );
1442 XMLPrinter printer;
1443 newElement->Accept( &printer );
Dmitry-Me5daa54c2015-04-08 17:45:07 +03001444 // Delete the node to avoid possible memory leak report in debug output
1445 doc.DeleteNode( newElement );
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001446 }
Lee Thomasonf6577832015-03-26 11:18:21 -07001447 {
Ant Mitchell189198f2015-03-24 16:20:36 +00001448 // Issue 302. Clear errors from LoadFile/SaveFile
1449 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001450 XMLTest( "Issue 302. Should be no error initially", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001451 doc.SaveFile( "./no/such/path/pretty.xml" );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001452 XMLTest( "Issue 302. Fail to save", "XML_ERROR_FILE_COULD_NOT_BE_OPENED", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001453 doc.SaveFile( "./resources/out/compact.xml", true );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001454 XMLTest( "Issue 302. Subsequent success in saving", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001455 }
Dmitry-Me6f51c802015-03-14 13:25:03 +03001456
Dmitry-Med9852a52015-03-25 10:17:49 +03001457 {
1458 // If a document fails to load then subsequent
1459 // successful loads should clear the error
1460 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001461 XMLTest( "Should be no error initially", false, doc.Error() );
Dmitry-Med9852a52015-03-25 10:17:49 +03001462 doc.LoadFile( "resources/no-such-file.xml" );
1463 XMLTest( "No such file - should fail", true, doc.Error() );
1464
1465 doc.LoadFile( "resources/dream.xml" );
1466 XMLTest( "Error should be cleared", false, doc.Error() );
1467 }
Sarat Addepalli8e85afa2015-05-19 09:07:03 +05301468
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301469 {
1470 // Check that declarations are parsed only as the FirstChild
Lee Thomason85492022015-05-22 11:07:45 -07001471 const char* xml0 = "<?xml version=\"1.0\" ?>"
1472 " <!-- xml version=\"1.1\" -->"
1473 "<first />";
1474 const char* xml1 = "<?xml version=\"1.0\" ?>"
1475 " <?xml version=\"1.1\" ?>"
1476 "<first />";
1477 const char* xml2 = "<first />"
1478 "<?xml version=\"1.0\" ?>";
1479 XMLDocument doc;
1480 doc.Parse(xml0);
1481 XMLTest("Test that the code changes do not affect normal parsing", doc.Error(), false);
1482 doc.Parse(xml1);
1483 XMLTest("Test that the second declaration throws an error", doc.ErrorID(), XML_ERROR_PARSING_DECLARATION);
1484 doc.Parse(xml2);
1485 XMLTest("Test that declaration after a child throws an error", doc.ErrorID(), XML_ERROR_PARSING_DECLARATION);
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301486 }
Dmitry-Med9852a52015-03-25 10:17:49 +03001487
Lee Thomason85492022015-05-22 11:07:45 -07001488 {
1489 // No matter - before or after successfully parsing a text -
1490 // calling XMLDocument::Value() causes an assert in debug.
1491 const char* validXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
1492 "<first />"
1493 "<second />";
1494 XMLDocument* doc = new XMLDocument();
1495 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1496 doc->Parse( validXml );
1497 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1498 delete doc;
1499 }
1500
1501 // ----------- Performance tracking --------------
Lee Thomason6f381b72012-03-02 12:59:39 -08001502 {
1503#if defined( _MSC_VER )
1504 __int64 start, end, freq;
1505 QueryPerformanceFrequency( (LARGE_INTEGER*) &freq );
1506#endif
1507
Bruno Diasa2d4e6e2012-05-07 04:58:11 -03001508 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason6f381b72012-03-02 12:59:39 -08001509 fseek( fp, 0, SEEK_END );
1510 long size = ftell( fp );
1511 fseek( fp, 0, SEEK_SET );
1512
1513 char* mem = new char[size+1];
1514 fread( mem, size, 1, fp );
1515 fclose( fp );
1516 mem[size] = 0;
1517
1518#if defined( _MSC_VER )
1519 QueryPerformanceCounter( (LARGE_INTEGER*) &start );
1520#else
1521 clock_t cstart = clock();
1522#endif
1523 static const int COUNT = 10;
1524 for( int i=0; i<COUNT; ++i ) {
1525 XMLDocument doc;
1526 doc.Parse( mem );
1527 }
1528#if defined( _MSC_VER )
1529 QueryPerformanceCounter( (LARGE_INTEGER*) &end );
1530#else
1531 clock_t cend = clock();
1532#endif
1533
1534 delete [] mem;
1535
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001536 static const char* note =
Lee Thomason6f381b72012-03-02 12:59:39 -08001537#ifdef DEBUG
1538 "DEBUG";
1539#else
1540 "Release";
1541#endif
1542
1543#if defined( _MSC_VER )
1544 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, 1000.0 * (double)(end-start) / ( (double)freq * (double)COUNT) );
1545#else
1546 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart)/(double)COUNT );
1547#endif
1548 }
1549
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -08001550 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001551 _CrtMemCheckpoint( &endMemState );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001552
1553 _CrtMemState diffMemState;
1554 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
1555 _CrtMemDumpStatistics( &diffMemState );
1556 #endif
1557
1558 printf ("\nPass %d, Fail %d\n", gPass, gFail);
Lee Thomason (grinliz)db304252013-07-31 12:24:52 -07001559
1560 return gFail;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08001561}