blob: 764b4710a190c6669732c5df633f577e4656fee0 [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{
33 bool pass = !strcmp( expected, found );
34 if ( pass )
35 printf ("[pass]");
36 else
37 printf ("[fail]");
38
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070039 if ( !echo ) {
Lee Thomason1ff38e02012-02-14 18:18:16 -080040 printf (" %s\n", testString);
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070041 }
42 else {
43 if ( extraNL ) {
44 printf( " %s\n", testString );
45 printf( "%s\n", expected );
46 printf( "%s\n", found );
47 }
48 else {
49 printf (" %s [%s][%s]\n", testString, expected, found);
50 }
51 }
Lee Thomason1ff38e02012-02-14 18:18:16 -080052
53 if ( pass )
54 ++gPass;
55 else
56 ++gFail;
57 return pass;
58}
59
60
Lee Thomason21be8822012-07-15 17:27:22 -070061template< class T > bool XMLTest( const char* testString, T expected, T found, bool echo=true )
Lee Thomason1ff38e02012-02-14 18:18:16 -080062{
63 bool pass = ( expected == found );
64 if ( pass )
65 printf ("[pass]");
66 else
67 printf ("[fail]");
68
U-Stream\Lee09a11c52012-02-17 08:31:16 -080069 if ( !echo )
Lee Thomason1ff38e02012-02-14 18:18:16 -080070 printf (" %s\n", testString);
71 else
Lee Thomasonc8312792012-07-16 12:44:41 -070072 printf (" %s [%d][%d]\n", testString, static_cast<int>(expected), static_cast<int>(found) );
Lee Thomason1ff38e02012-02-14 18:18:16 -080073
74 if ( pass )
75 ++gPass;
76 else
77 ++gFail;
78 return pass;
79}
Lee Thomasonec5a7b42012-02-13 18:16:52 -080080
U-Lama\Leee13c3e62011-12-28 14:36:55 -080081
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -080082void NullLineEndings( char* p )
83{
84 while( p && *p ) {
85 if ( *p == '\n' || *p == '\r' ) {
86 *p = 0;
87 return;
88 }
89 ++p;
90 }
91}
92
93
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070094int example_1()
95{
96 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -030097 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070098
99 return doc.ErrorID();
100}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200101/** @page Example-1 Load an XML File
102 * @dontinclude ./xmltest.cpp
103 * Basic XML file loading.
104 * The basic syntax to load an XML file from
105 * disk and check for an error. (ErrorID()
106 * will return 0 for no error.)
107 * @skip example_1()
108 * @until }
109 */
110
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700111
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700112int example_2()
113{
114 static const char* xml = "<element/>";
115 XMLDocument doc;
116 doc.Parse( xml );
117
118 return doc.ErrorID();
119}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200120/** @page Example-2 Parse an XML from char buffer
121 * @dontinclude ./xmltest.cpp
122 * Basic XML string parsing.
123 * The basic syntax to parse an XML for
124 * a char* and check for an error. (ErrorID()
125 * will return 0 for no error.)
126 * @skip example_2()
127 * @until }
128 */
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700129
130
131int example_3()
132{
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700133 static const char* xml =
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700134 "<?xml version=\"1.0\"?>"
135 "<!DOCTYPE PLAY SYSTEM \"play.dtd\">"
136 "<PLAY>"
137 "<TITLE>A Midsummer Night's Dream</TITLE>"
138 "</PLAY>";
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700139
140 XMLDocument doc;
141 doc.Parse( xml );
142
143 XMLElement* titleElement = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" );
144 const char* title = titleElement->GetText();
145 printf( "Name of play (1): %s\n", title );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700146
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700147 XMLText* textNode = titleElement->FirstChild()->ToText();
148 title = textNode->Value();
149 printf( "Name of play (2): %s\n", title );
150
151 return doc.ErrorID();
152}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200153/** @page Example-3 Get information out of XML
154 @dontinclude ./xmltest.cpp
155 In this example, we navigate a simple XML
156 file, and read some interesting text. Note
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700157 that this example doesn't use error
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200158 checking; working code should check for null
159 pointers when walking an XML tree, or use
160 XMLHandle.
161
162 (The XML is an excerpt from "dream.xml").
163
164 @skip example_3()
165 @until </PLAY>";
166
167 The structure of the XML file is:
168
169 <ul>
170 <li>(declaration)</li>
171 <li>(dtd stuff)</li>
172 <li>Element "PLAY"</li>
173 <ul>
174 <li>Element "TITLE"</li>
175 <ul>
176 <li>Text "A Midsummer Night's Dream"</li>
177 </ul>
178 </ul>
179 </ul>
180
181 For this example, we want to print out the
182 title of the play. The text of the title (what
183 we want) is child of the "TITLE" element which
184 is a child of the "PLAY" element.
185
186 We want to skip the declaration and dtd, so the
187 method FirstChildElement() is a good choice. The
188 FirstChildElement() of the Document is the "PLAY"
189 Element, the FirstChildElement() of the "PLAY" Element
190 is the "TITLE" Element.
191
192 @until ( "TITLE" );
193
194 We can then use the convenience function GetText()
195 to get the title of the play.
196
197 @until title );
198
199 Text is just another Node in the XML DOM. And in
200 fact you should be a little cautious with it, as
201 text nodes can contain elements.
202
203 @verbatim
204 Consider: A Midsummer Night's <b>Dream</b>
205 @endverbatim
206
207 It is more correct to actually query the Text Node
208 if in doubt:
209
210 @until title );
211
212 Noting that here we use FirstChild() since we are
213 looking for XMLText, not an element, and ToText()
214 is a cast from a Node to a XMLText.
215*/
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700216
217
Lee Thomason21be8822012-07-15 17:27:22 -0700218bool example_4()
219{
220 static const char* xml =
221 "<information>"
222 " <attributeApproach v='2' />"
223 " <textApproach>"
224 " <v>2</v>"
225 " </textApproach>"
226 "</information>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700227
Lee Thomason21be8822012-07-15 17:27:22 -0700228 XMLDocument doc;
229 doc.Parse( xml );
230
231 int v0 = 0;
232 int v1 = 0;
233
234 XMLElement* attributeApproachElement = doc.FirstChildElement()->FirstChildElement( "attributeApproach" );
235 attributeApproachElement->QueryIntAttribute( "v", &v0 );
236
237 XMLElement* textApproachElement = doc.FirstChildElement()->FirstChildElement( "textApproach" );
238 textApproachElement->FirstChildElement( "v" )->QueryIntText( &v1 );
239
240 printf( "Both values are the same: %d and %d\n", v0, v1 );
241
242 return !doc.Error() && ( v0 == v1 );
243}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200244/** @page Example-4 Read attributes and text information.
245 @dontinclude ./xmltest.cpp
246
247 There are fundamentally 2 ways of writing a key-value
248 pair into an XML file. (Something that's always annoyed
249 me about XML.) Either by using attributes, or by writing
250 the key name into an element and the value into
251 the text node wrapped by the element. Both approaches
252 are illustrated in this example, which shows two ways
253 to encode the value "2" into the key "v":
254
255 @skip example_4()
256 @until "</information>";
257
258 TinyXML-2 has accessors for both approaches.
259
260 When using an attribute, you navigate to the XMLElement
261 with that attribute and use the QueryIntAttribute()
262 group of methods. (Also QueryFloatAttribute(), etc.)
263
264 @skip XMLElement* attributeApproachElement
265 @until &v0 );
266
267 When using the text approach, you need to navigate
268 down one more step to the XMLElement that contains
269 the text. Note the extra FirstChildElement( "v" )
270 in the code below. The value of the text can then
271 be safely queried with the QueryIntText() group
272 of methods. (Also QueryFloatText(), etc.)
273
274 @skip XMLElement* textApproachElement
275 @until &v1 );
276*/
Lee Thomason21be8822012-07-15 17:27:22 -0700277
278
Lee Thomason178e4cc2013-01-25 16:19:05 -0800279int main( int argc, const char ** argv )
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800280{
Lee Thomason (grinliz)0a4df402012-02-27 20:50:52 -0800281 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason1ff38e02012-02-14 18:18:16 -0800282 _CrtMemCheckpoint( &startMemState );
Dmitry-Me99916592014-10-23 11:37:03 +0400283 // Enable MS Visual C++ debug heap memory leaks dump on exit
284 _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700285 #endif
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800286
Martinsh Shaiters39ddc262013-01-15 21:53:08 +0200287 #if defined(_MSC_VER) || defined(MINGW32) || defined(__MINGW32__)
ddiproiettoa8ae1f62013-05-05 18:42:52 +0300288 #if defined __MINGW64_VERSION_MAJOR && defined __MINGW64_VERSION_MINOR
289 //MINGW64: both 32 and 64-bit
290 mkdir( "resources/out/" );
291 #else
292 _mkdir( "resources/out/" );
293 #endif
Lee Thomasone9699e62012-07-25 12:24:23 -0700294 #else
295 mkdir( "resources/out/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
296 #endif
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400297
Lee Thomason178e4cc2013-01-25 16:19:05 -0800298 if ( argc > 1 ) {
299 XMLDocument* doc = new XMLDocument();
300 clock_t startTime = clock();
301 doc->LoadFile( argv[1] );
Anton Indrawan8a0006c2014-11-20 18:27:07 +0100302 clock_t loadTime = clock();
Lee Thomason178e4cc2013-01-25 16:19:05 -0800303 int errorID = doc->ErrorID();
304 delete doc; doc = 0;
Anton Indrawan8a0006c2014-11-20 18:27:07 +0100305 clock_t deleteTime = clock();
Lee Thomason178e4cc2013-01-25 16:19:05 -0800306
307 printf( "Test file '%s' loaded. ErrorID=%d\n", argv[1], errorID );
308 if ( !errorID ) {
Lee Thomason (grinliz)d6bd7362013-05-11 20:23:13 -0700309 printf( "Load time=%u\n", (unsigned)(loadTime - startTime) );
310 printf( "Delete time=%u\n", (unsigned)(deleteTime - loadTime) );
311 printf( "Total time=%u\n", (unsigned)(deleteTime - startTime) );
Lee Thomason178e4cc2013-01-25 16:19:05 -0800312 }
313 exit(0);
314 }
315
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300316 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason7f7b1622012-03-24 12:49:03 -0700317 if ( !fp ) {
318 printf( "Error opening test file 'dream.xml'.\n"
319 "Is your working directory the same as where \n"
320 "the xmltest.cpp and dream.xml file are?\n\n"
321 #if defined( _MSC_VER )
322 "In windows Visual Studio you may need to set\n"
323 "Properties->Debugging->Working Directory to '..'\n"
324 #endif
325 );
326 exit( 1 );
327 }
328 fclose( fp );
329
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700330 XMLTest( "Example-1", 0, example_1() );
331 XMLTest( "Example-2", 0, example_2() );
332 XMLTest( "Example-3", 0, example_3() );
Lee Thomason21be8822012-07-15 17:27:22 -0700333 XMLTest( "Example-4", true, example_4() );
Lee Thomason87e475a2012-03-20 11:55:29 -0700334
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700335 /* ------ Example 2: Lookup information. ---- */
Lee Thomason87e475a2012-03-20 11:55:29 -0700336
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800337 {
Lee Thomason43f59302012-02-06 18:18:11 -0800338 static const char* test[] = { "<element />",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400339 "<element></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800340 "<element><subelement/></element>",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400341 "<element><subelement></subelement></element>",
342 "<element><subelement><subsub/></subelement></element>",
343 "<!--comment beside elements--><element><subelement></subelement></element>",
344 "<!--comment beside elements, this time with spaces--> \n <element> <subelement> \n </subelement> </element>",
345 "<element attrib1='foo' attrib2=\"bar\" ></element>",
346 "<element attrib1='foo' attrib2=\"bar\" ><subelement attrib3='yeehaa' /></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800347 "<element>Text inside element.</element>",
348 "<element><b></b></element>",
349 "<element>Text inside and <b>bolded</b> in the element.</element>",
350 "<outer><element>Text inside and <b>bolded</b> in the element.</element></outer>",
Lee Thomason8ee79892012-01-25 17:44:30 -0800351 "<element>This &amp; That.</element>",
Lee Thomason18d68bd2012-01-26 18:17:26 -0800352 "<element attrib='This&lt;That' />",
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800353 0
354 };
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800355 for( int i=0; test[i]; ++i ) {
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800356 XMLDocument doc;
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800357 doc.Parse( test[i] );
Lee Thomason5cae8972012-01-24 18:03:07 -0800358 doc.Print();
Lee Thomasonec975ce2012-01-23 11:42:06 -0800359 printf( "----------------------------------------------\n" );
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800360 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800361 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800362#if 1
Lee Thomasond6277762012-02-22 16:00:12 -0800363 {
364 static const char* test = "<!--hello world\n"
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400365 " line 2\r"
366 " line 3\r\n"
367 " line 4\n\r"
368 " line 5\r-->";
Lee Thomasond6277762012-02-22 16:00:12 -0800369
370 XMLDocument doc;
371 doc.Parse( test );
372 doc.Print();
373 }
374
Lee Thomason2c85a712012-01-31 08:24:24 -0800375 {
376 static const char* test = "<element>Text before.</element>";
377 XMLDocument doc;
378 doc.Parse( test );
379 XMLElement* root = doc.FirstChildElement();
380 XMLElement* newElement = doc.NewElement( "Subelement" );
381 root->InsertEndChild( newElement );
382 doc.Print();
383 }
Lee Thomasond1983222012-02-06 08:41:24 -0800384 {
385 XMLDocument* doc = new XMLDocument();
386 static const char* test = "<element><sub/></element>";
387 doc->Parse( test );
388 delete doc;
389 }
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800390 {
Lee Thomason1ff38e02012-02-14 18:18:16 -0800391 // Test: Programmatic DOM
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800392 // Build:
393 // <element>
394 // <!--comment-->
395 // <sub attrib="1" />
396 // <sub attrib="2" />
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800397 // <sub attrib="3" >& Text!</sub>
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800398 // <element>
399
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800400 XMLDocument* doc = new XMLDocument();
Lee Thomason1ff38e02012-02-14 18:18:16 -0800401 XMLNode* element = doc->InsertEndChild( doc->NewElement( "element" ) );
402
403 XMLElement* sub[3] = { doc->NewElement( "sub" ), doc->NewElement( "sub" ), doc->NewElement( "sub" ) };
404 for( int i=0; i<3; ++i ) {
405 sub[i]->SetAttribute( "attrib", i );
406 }
407 element->InsertEndChild( sub[2] );
408 XMLNode* comment = element->InsertFirstChild( doc->NewComment( "comment" ) );
409 element->InsertAfterChild( comment, sub[0] );
410 element->InsertAfterChild( sub[0], sub[1] );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800411 sub[2]->InsertFirstChild( doc->NewText( "& Text!" ));
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800412 doc->Print();
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800413 XMLTest( "Programmatic DOM", "comment", doc->FirstChildElement( "element" )->FirstChild()->Value() );
414 XMLTest( "Programmatic DOM", "0", doc->FirstChildElement( "element" )->FirstChildElement()->Attribute( "attrib" ) );
415 XMLTest( "Programmatic DOM", 2, doc->FirstChildElement()->LastChildElement( "sub" )->IntAttribute( "attrib" ) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700416 XMLTest( "Programmatic DOM", "& Text!",
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800417 doc->FirstChildElement()->LastChildElement( "sub" )->FirstChild()->ToText()->Value() );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800418
419 // And now deletion:
420 element->DeleteChild( sub[2] );
421 doc->DeleteNode( comment );
422
423 element->FirstChildElement()->SetAttribute( "attrib", true );
424 element->LastChildElement()->DeleteAttribute( "attrib" );
425
426 XMLTest( "Programmatic DOM", true, doc->FirstChildElement()->FirstChildElement()->BoolAttribute( "attrib" ) );
427 int value = 10;
428 int result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value );
Lee Thomason21be8822012-07-15 17:27:22 -0700429 XMLTest( "Programmatic DOM", result, (int)XML_NO_ATTRIBUTE );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800430 XMLTest( "Programmatic DOM", value, 10 );
431
432 doc->Print();
433
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700434 {
435 XMLPrinter streamer;
436 doc->Print( &streamer );
437 printf( "%s", streamer.CStr() );
438 }
439 {
440 XMLPrinter streamer( 0, true );
441 doc->Print( &streamer );
442 XMLTest( "Compact mode", "<element><sub attrib=\"1\"/><sub/></element>", streamer.CStr(), false );
443 }
Lee Thomason (grinliz)6b8b0122012-09-08 21:21:00 -0700444 doc->SaveFile( "./resources/out/pretty.xml" );
445 doc->SaveFile( "./resources/out/compact.xml", true );
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800446 delete doc;
447 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800448 {
449 // Test: Dream
450 // XML1 : 1,187,569 bytes in 31,209 allocations
451 // XML2 : 469,073 bytes in 323 allocations
452 //int newStart = gNew;
453 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300454 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800455
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400456 doc.SaveFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800457 doc.PrintError();
458
459 XMLTest( "Dream", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400460 doc.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800461 XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false );
462 XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
463 doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
464 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400465 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800466 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400467 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800468
469 XMLDocument doc2;
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400470 doc2.LoadFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800471 XMLTest( "Dream-out", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400472 doc2.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800473 XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false );
474 XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
475 doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
476 XMLTest( "Dream-out", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400477 doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800478
479 //gNewTotal = gNew - newStart;
480 }
Lee Thomason6f381b72012-03-02 12:59:39 -0800481
482
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800483 {
484 const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
485 "<passages count=\"006\" formatversion=\"20020620\">\n"
486 " <wrong error>\n"
487 "</passages>";
488
489 XMLDocument doc;
490 doc.Parse( error );
Lee Thomason2fa81722012-11-09 12:37:46 -0800491 XMLTest( "Bad XML", doc.ErrorID(), XML_ERROR_PARSING_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800492 }
493
494 {
495 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
496
497 XMLDocument doc;
498 doc.Parse( str );
499
500 XMLElement* ele = doc.FirstChildElement();
501
502 int iVal, result;
503 double dVal;
504
505 result = ele->QueryDoubleAttribute( "attr0", &dVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700506 XMLTest( "Query attribute: int as double", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800507 XMLTest( "Query attribute: int as double", (int)dVal, 1 );
508 result = ele->QueryDoubleAttribute( "attr1", &dVal );
Thomas Roßa5221862013-05-11 10:22:12 +0200509 XMLTest( "Query attribute: double as double", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800510 XMLTest( "Query attribute: double as double", (int)dVal, 2 );
511 result = ele->QueryIntAttribute( "attr1", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700512 XMLTest( "Query attribute: double as int", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800513 XMLTest( "Query attribute: double as int", iVal, 2 );
514 result = ele->QueryIntAttribute( "attr2", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700515 XMLTest( "Query attribute: not a number", result, (int)XML_WRONG_ATTRIBUTE_TYPE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800516 result = ele->QueryIntAttribute( "bar", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700517 XMLTest( "Query attribute: does not exist", result, (int)XML_NO_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800518 }
519
520 {
521 const char* str = "<doc/>";
522
523 XMLDocument doc;
524 doc.Parse( str );
525
526 XMLElement* ele = doc.FirstChildElement();
527
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800528 int iVal, iVal2;
529 double dVal, dVal2;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800530
531 ele->SetAttribute( "str", "strValue" );
532 ele->SetAttribute( "int", 1 );
533 ele->SetAttribute( "double", -1.0 );
534
535 const char* cStr = ele->Attribute( "str" );
536 ele->QueryIntAttribute( "int", &iVal );
537 ele->QueryDoubleAttribute( "double", &dVal );
538
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800539 ele->QueryAttribute( "int", &iVal2 );
540 ele->QueryAttribute( "double", &dVal2 );
541
Lee Thomason8ba7f7d2012-03-24 13:04:04 -0700542 XMLTest( "Attribute match test", ele->Attribute( "str", "strValue" ), "strValue" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800543 XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
544 XMLTest( "Attribute round trip. int.", 1, iVal );
545 XMLTest( "Attribute round trip. double.", -1, (int)dVal );
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800546 XMLTest( "Alternate query", true, iVal == iVal2 );
547 XMLTest( "Alternate query", true, dVal == dVal2 );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800548 }
549
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800550 {
551 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300552 doc.LoadFile( "resources/utf8test.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800553
554 // Get the attribute "value" from the "Russian" element and check it.
555 XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700556 const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800557 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
558
559 XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
560
561 const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U,
562 0xd1U, 0x81U, 0xd1U, 0x81U,
563 0xd0U, 0xbaU, 0xd0U, 0xb8U,
564 0xd0U, 0xb9U, 0 };
565 const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
566
567 XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
568 XMLTest( "UTF-8: Browsing russian element name.",
569 russianText,
570 text->Value() );
571
572 // Now try for a round trip.
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400573 doc.SaveFile( "resources/out/utf8testout.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800574
575 // Check the round trip.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800576 int okay = 0;
577
Thomas Roßa6dd8c62012-07-26 20:42:18 +0200578 FILE* saved = fopen( "resources/out/utf8testout.xml", "r" );
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300579 FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800580
581 if ( saved && verify )
582 {
583 okay = 1;
PKEuSc28ba3a2012-07-16 03:08:47 -0700584 char verifyBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800585 while ( fgets( verifyBuf, 256, verify ) )
586 {
PKEuSc28ba3a2012-07-16 03:08:47 -0700587 char savedBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800588 fgets( savedBuf, 256, saved );
589 NullLineEndings( verifyBuf );
590 NullLineEndings( savedBuf );
591
592 if ( strcmp( verifyBuf, savedBuf ) )
593 {
594 printf( "verify:%s<\n", verifyBuf );
595 printf( "saved :%s<\n", savedBuf );
596 okay = 0;
597 break;
598 }
599 }
600 }
601 if ( saved )
602 fclose( saved );
603 if ( verify )
604 fclose( verify );
605 XMLTest( "UTF-8: Verified multi-language round trip.", 1, okay );
606 }
607
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800608 // --------GetText()-----------
609 {
610 const char* str = "<foo>This is text</foo>";
611 XMLDocument doc;
612 doc.Parse( str );
613 const XMLElement* element = doc.RootElement();
614
615 XMLTest( "GetText() normal use.", "This is text", element->GetText() );
616
617 str = "<foo><b>This is text</b></foo>";
618 doc.Parse( str );
619 element = doc.RootElement();
620
621 XMLTest( "GetText() contained element.", element->GetText() == 0, true );
622 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800623
Lee Thomasond6277762012-02-22 16:00:12 -0800624
Uli Kusterer321072e2014-01-21 01:57:38 +0100625 // --------SetText()-----------
626 {
627 const char* str = "<foo></foo>";
628 XMLDocument doc;
629 doc.Parse( str );
630 XMLElement* element = doc.RootElement();
631
Lee Thomason9c0678a2014-01-24 10:18:27 -0800632 element->SetText("darkness.");
633 XMLTest( "SetText() normal use (open/close).", "darkness.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100634
Lee Thomason9c0678a2014-01-24 10:18:27 -0800635 element->SetText("blue flame.");
636 XMLTest( "SetText() replace.", "blue flame.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100637
638 str = "<foo/>";
639 doc.Parse( str );
640 element = doc.RootElement();
641
Lee Thomason9c0678a2014-01-24 10:18:27 -0800642 element->SetText("The driver");
643 XMLTest( "SetText() normal use. (self-closing)", "The driver", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100644
Lee Thomason9c0678a2014-01-24 10:18:27 -0800645 element->SetText("<b>horses</b>");
646 XMLTest( "SetText() replace with tag-like text.", "<b>horses</b>", element->GetText() );
647 //doc.Print();
Uli Kusterer321072e2014-01-21 01:57:38 +0100648
649 str = "<foo><bar>Text in nested element</bar></foo>";
650 doc.Parse( str );
651 element = doc.RootElement();
652
Lee Thomason9c0678a2014-01-24 10:18:27 -0800653 element->SetText("wolves");
654 XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800655
656 str = "<foo/>";
657 doc.Parse( str );
658 element = doc.RootElement();
659
660 element->SetText( "str" );
661 XMLTest( "SetText types", "str", element->GetText() );
662
663 element->SetText( 1 );
664 XMLTest( "SetText types", "1", element->GetText() );
665
666 element->SetText( 1U );
667 XMLTest( "SetText types", "1", element->GetText() );
668
669 element->SetText( true );
670 XMLTest( "SetText types", "1", element->GetText() ); // TODO: should be 'true'?
671
672 element->SetText( 1.5f );
673 XMLTest( "SetText types", "1.5", element->GetText() );
674
675 element->SetText( 1.5 );
676 XMLTest( "SetText types", "1.5", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100677 }
678
679
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800680 // ---------- CDATA ---------------
681 {
682 const char* str = "<xmlElement>"
683 "<![CDATA["
684 "I am > the rules!\n"
685 "...since I make symbolic puns"
686 "]]>"
687 "</xmlElement>";
688 XMLDocument doc;
689 doc.Parse( str );
690 doc.Print();
Lee Thomasond6277762012-02-22 16:00:12 -0800691
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700692 XMLTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800693 "I am > the rules!\n...since I make symbolic puns",
Lee Thomasond6277762012-02-22 16:00:12 -0800694 false );
695 }
696
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800697 // ----------- CDATA -------------
698 {
699 const char* str = "<xmlElement>"
700 "<![CDATA["
701 "<b>I am > the rules!</b>\n"
702 "...since I make symbolic puns"
703 "]]>"
704 "</xmlElement>";
705 XMLDocument doc;
706 doc.Parse( str );
707 doc.Print();
708
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700709 XMLTest( "CDATA parse. [ tixml1:1480107 ]", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800710 "<b>I am > the rules!</b>\n...since I make symbolic puns",
711 false );
712 }
713
714 // InsertAfterChild causes crash.
715 {
716 // InsertBeforeChild and InsertAfterChild causes crash.
717 XMLDocument doc;
718 XMLElement* parent = doc.NewElement( "Parent" );
719 doc.InsertFirstChild( parent );
720
721 XMLElement* childText0 = doc.NewElement( "childText0" );
722 XMLElement* childText1 = doc.NewElement( "childText1" );
723
724 XMLNode* childNode0 = parent->InsertEndChild( childText0 );
725 XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
726
727 XMLTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent->LastChild() ), true );
728 }
Lee Thomasond6277762012-02-22 16:00:12 -0800729
730 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800731 // Entities not being written correctly.
732 // From Lynn Allen
Lee Thomasond6277762012-02-22 16:00:12 -0800733
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800734 const char* passages =
735 "<?xml version=\"1.0\" standalone=\"no\" ?>"
736 "<passages count=\"006\" formatversion=\"20020620\">"
737 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
738 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
739 "</passages>";
Lee Thomasond6277762012-02-22 16:00:12 -0800740
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800741 XMLDocument doc;
742 doc.Parse( passages );
743 XMLElement* psg = doc.RootElement()->FirstChildElement();
744 const char* context = psg->Attribute( "context" );
745 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 -0800746
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800747 XMLTest( "Entity transformation: read. ", expected, context, true );
Lee Thomasond6277762012-02-22 16:00:12 -0800748
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400749 FILE* textfile = fopen( "resources/out/textfile.txt", "w" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800750 if ( textfile )
751 {
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800752 XMLPrinter streamer( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800753 psg->Accept( &streamer );
754 fclose( textfile );
755 }
Thomas Roß0922b732012-09-23 16:31:22 +0200756
757 textfile = fopen( "resources/out/textfile.txt", "r" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800758 TIXMLASSERT( textfile );
759 if ( textfile )
760 {
761 char buf[ 1024 ];
762 fgets( buf, 1024, textfile );
763 XMLTest( "Entity transformation: write. ",
764 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
765 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
766 buf, false );
PKEuSc28ba3a2012-07-16 03:08:47 -0700767 fclose( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800768 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800769 }
770
771 {
Lee Thomason6f381b72012-03-02 12:59:39 -0800772 // Suppress entities.
773 const char* passages =
774 "<?xml version=\"1.0\" standalone=\"no\" ?>"
775 "<passages count=\"006\" formatversion=\"20020620\">"
776 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
777 "</passages>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700778
Lee Thomason6f381b72012-03-02 12:59:39 -0800779 XMLDocument doc( false );
780 doc.Parse( passages );
781
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700782 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ),
Lee Thomason6f381b72012-03-02 12:59:39 -0800783 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;." );
784 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value(),
785 "Crazy &ttk;" );
786 doc.Print();
787 }
788
789 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400790 const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800791
792 XMLDocument doc;
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400793 doc.Parse( test );
794 XMLTest( "dot in names", doc.Error(), false );
795 XMLTest( "dot in names", doc.FirstChildElement()->Name(), "a.elem" );
796 XMLTest( "dot in names", doc.FirstChildElement()->Attribute( "xmi.version" ), "2.0" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800797 }
798
799 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400800 const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800801
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400802 XMLDocument doc;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800803 doc.Parse( test );
804
805 XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
806 XMLTest( "Entity with one digit.",
807 text->Value(), "1.1 Start easy ignore fin thickness\n",
808 false );
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400809 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800810
811 {
812 // DOCTYPE not preserved (950171)
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700813 //
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800814 const char* doctype =
815 "<?xml version=\"1.0\" ?>"
816 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
817 "<!ELEMENT title (#PCDATA)>"
818 "<!ELEMENT books (title,authors)>"
819 "<element />";
820
821 XMLDocument doc;
822 doc.Parse( doctype );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400823 doc.SaveFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800824 doc.DeleteChild( doc.RootElement() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400825 doc.LoadFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800826 doc.Print();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700827
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800828 const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
829 XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
830
831 }
832
833 {
834 // Comments do not stream out correctly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700835 const char* doctype =
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800836 "<!-- Somewhat<evil> -->";
837 XMLDocument doc;
838 doc.Parse( doctype );
839
840 XMLComment* comment = doc.FirstChild()->ToComment();
841
842 XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
843 }
844 {
845 // Double attributes
846 const char* doctype = "<element attr='red' attr='blue' />";
847
848 XMLDocument doc;
849 doc.Parse( doctype );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700850
Lee Thomason2fa81722012-11-09 12:37:46 -0800851 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 -0800852 doc.PrintError();
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800853 }
854
855 {
856 // Embedded null in stream.
857 const char* doctype = "<element att\0r='red' attr='blue' />";
858
859 XMLDocument doc;
860 doc.Parse( doctype );
861 XMLTest( "Embedded null throws error.", true, doc.Error() );
862 }
863
864 {
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700865 // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
Dmitry-Me588bb8d2014-12-25 18:59:18 +0300866 const char* str = "";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800867 XMLDocument doc;
868 doc.Parse( str );
Lee Thomason2fa81722012-11-09 12:37:46 -0800869 XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800870 }
871
872 {
Dmitry-Me588bb8d2014-12-25 18:59:18 +0300873 // Documents with all whitespaces should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
874 const char* str = " ";
875 XMLDocument doc;
876 doc.Parse( str );
877 XMLTest( "All whitespaces document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
878 }
879
880 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800881 // Low entities
882 XMLDocument doc;
883 doc.Parse( "<test>&#x0e;</test>" );
884 const char result[] = { 0x0e, 0 };
885 XMLTest( "Low entities.", doc.FirstChildElement()->GetText(), result );
886 doc.Print();
887 }
888
889 {
890 // Attribute values with trailing quotes not handled correctly
891 XMLDocument doc;
892 doc.Parse( "<foo attribute=bar\" />" );
893 XMLTest( "Throw error with bad end quotes.", doc.Error(), true );
894 }
895
896 {
897 // [ 1663758 ] Failure to report error on bad XML
898 XMLDocument xml;
899 xml.Parse("<x>");
900 XMLTest("Missing end tag at end of input", xml.Error(), true);
901 xml.Parse("<x> ");
902 XMLTest("Missing end tag with trailing whitespace", xml.Error(), true);
903 xml.Parse("<x></y>");
Lee Thomason2fa81722012-11-09 12:37:46 -0800904 XMLTest("Mismatched tags", xml.ErrorID(), XML_ERROR_MISMATCHED_ELEMENT);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700905 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800906
907
908 {
909 // [ 1475201 ] TinyXML parses entities in comments
910 XMLDocument xml;
911 xml.Parse("<!-- declarations for <head> & <body> -->"
912 "<!-- far &amp; away -->" );
913
914 XMLNode* e0 = xml.FirstChild();
915 XMLNode* e1 = e0->NextSibling();
916 XMLComment* c0 = e0->ToComment();
917 XMLComment* c1 = e1->ToComment();
918
919 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
920 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
921 }
922
923 {
924 XMLDocument xml;
925 xml.Parse( "<Parent>"
926 "<child1 att=''/>"
927 "<!-- With this comment, child2 will not be parsed! -->"
928 "<child2 att=''/>"
929 "</Parent>" );
930 xml.Print();
931
932 int count = 0;
933
934 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
935 ele;
936 ele = ele->NextSibling() )
937 {
938 ++count;
939 }
940
941 XMLTest( "Comments iterate correctly.", 3, count );
942 }
943
944 {
945 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
946 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
947 buf[60] = 239;
948 buf[61] = 0;
949
950 XMLDocument doc;
951 doc.Parse( (const char*)buf);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700952 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800953
954
955 {
956 // bug 1827248 Error while parsing a little bit malformed file
957 // Actually not malformed - should work.
958 XMLDocument xml;
959 xml.Parse( "<attributelist> </attributelist >" );
960 XMLTest( "Handle end tag whitespace", false, xml.Error() );
961 }
962
963 {
964 // This one must not result in an infinite loop
965 XMLDocument xml;
966 xml.Parse( "<infinite>loop" );
967 XMLTest( "Infinite loop test.", true, true );
968 }
969#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800970 {
971 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
972 XMLDocument doc;
973 doc.Parse( pub );
974
975 XMLDocument clone;
976 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
977 XMLNode* copy = node->ShallowClone( &clone );
978 clone.InsertEndChild( copy );
979 }
980
981 clone.Print();
982
983 int count=0;
984 const XMLNode* a=clone.FirstChild();
985 const XMLNode* b=doc.FirstChild();
986 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
987 ++count;
988 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
989 }
990 XMLTest( "Clone and Equal", 4, count );
991 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800992
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700993 {
994 // This shouldn't crash.
995 XMLDocument doc;
996 if(XML_NO_ERROR != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
997 {
998 doc.PrintError();
999 }
1000 XMLTest( "Error in snprinf handling.", true, doc.Error() );
1001 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001002
Lee Thomason5e3803c2012-04-16 08:57:05 -07001003 {
1004 // Attribute ordering.
1005 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
1006 XMLDocument doc;
1007 doc.Parse( xml );
1008 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001009
Lee Thomason5e3803c2012-04-16 08:57:05 -07001010 const XMLAttribute* a = ele->FirstAttribute();
1011 XMLTest( "Attribute order", "1", a->Value() );
1012 a = a->Next();
1013 XMLTest( "Attribute order", "2", a->Value() );
1014 a = a->Next();
1015 XMLTest( "Attribute order", "3", a->Value() );
1016 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001017
Lee Thomason5e3803c2012-04-16 08:57:05 -07001018 ele->DeleteAttribute( "attrib2" );
1019 a = ele->FirstAttribute();
1020 XMLTest( "Attribute order", "1", a->Value() );
1021 a = a->Next();
1022 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001023
Lee Thomason5e3803c2012-04-16 08:57:05 -07001024 ele->DeleteAttribute( "attrib1" );
1025 ele->DeleteAttribute( "attrib3" );
1026 XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
1027 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001028
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001029 {
1030 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -07001031 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
1032 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
1033 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
1034 XMLDocument doc0;
1035 doc0.Parse( xml0 );
1036 XMLDocument doc1;
1037 doc1.Parse( xml1 );
1038 XMLDocument doc2;
1039 doc2.Parse( xml2 );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001040
Lee Thomason78a773d2012-07-02 10:10:19 -07001041 XMLElement* ele = 0;
1042 ele = doc0.FirstChildElement();
1043 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
1044 ele = doc1.FirstChildElement();
1045 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
1046 ele = doc2.FirstChildElement();
1047 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001048 }
1049
1050 {
1051 // Make sure we don't go into an infinite loop.
1052 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
1053 XMLDocument doc;
1054 doc.Parse( xml );
1055 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
1056 XMLElement* ele1 = ele0->NextSiblingElement();
1057 bool equal = ele0->ShallowEqual( ele1 );
1058
1059 XMLTest( "Infinite loop in shallow equal.", true, equal );
1060 }
1061
Lee Thomason5708f812012-03-28 17:46:41 -07001062 // -------- Handles ------------
1063 {
1064 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1065 XMLDocument doc;
1066 doc.Parse( xml );
Lee Thomason5708f812012-03-28 17:46:41 -07001067
1068 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
1069 XMLTest( "Handle, success, mutable", ele->Value(), "sub" );
1070
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001071 XMLHandle docH( doc );
1072 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001073 XMLTest( "Handle, dne, mutable", false, ele != 0 );
Lee Thomason5708f812012-03-28 17:46:41 -07001074 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001075
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001076 {
1077 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1078 XMLDocument doc;
1079 doc.Parse( xml );
1080 XMLConstHandle docH( doc );
1081
1082 const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
1083 XMLTest( "Handle, success, const", ele->Value(), "sub" );
1084
1085 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001086 XMLTest( "Handle, dne, const", false, ele != 0 );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001087 }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001088 {
1089 // Default Declaration & BOM
1090 XMLDocument doc;
1091 doc.InsertEndChild( doc.NewDeclaration() );
1092 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001093
Lee Thomasonf68c4382012-04-28 14:37:11 -07001094 XMLPrinter printer;
1095 doc.Print( &printer );
1096
1097 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1098 XMLTest( "BOM and default declaration", printer.CStr(), result, false );
Lee Thomason (grinliz)48ea0bc2012-05-26 14:41:14 -07001099 XMLTest( "CStrSize", printer.CStrSize(), 42, false );
Lee Thomasonf68c4382012-04-28 14:37:11 -07001100 }
Lee Thomason21be8822012-07-15 17:27:22 -07001101 {
1102 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1103 XMLDocument doc;
1104 doc.Parse( xml );
1105 XMLTest( "Ill formed XML", true, doc.Error() );
1106 }
1107
1108 // QueryXYZText
1109 {
1110 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1111 XMLDocument doc;
1112 doc.Parse( xml );
1113
1114 const XMLElement* pointElement = doc.RootElement();
1115
1116 int intValue = 0;
1117 unsigned unsignedValue = 0;
1118 float floatValue = 0;
1119 double doubleValue = 0;
1120 bool boolValue = false;
1121
1122 pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1123 pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1124 pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1125 pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1126 pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1127
1128
1129 XMLTest( "QueryIntText", intValue, 1, false );
1130 XMLTest( "QueryUnsignedText", unsignedValue, (unsigned)1, false );
1131 XMLTest( "QueryFloatText", floatValue, 1.2f, false );
1132 XMLTest( "QueryDoubleText", doubleValue, 1.2, false );
1133 XMLTest( "QueryBoolText", boolValue, true, false );
1134 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001135
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001136 {
1137 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1138 XMLDocument doc;
1139 doc.Parse( xml );
1140 XMLTest( "Non-alpha element lead letter parses.", doc.Error(), false );
1141 }
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001142
1143 {
1144 const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1145 XMLDocument doc;
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001146 doc.Parse( xml );
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001147 XMLTest("Non-alpha attribute lead character parses.", doc.Error(), false);
1148 }
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001149
1150 {
1151 const char* xml = "<3lement></3lement>";
1152 XMLDocument doc;
1153 doc.Parse( xml );
1154 XMLTest("Element names with lead digit fail to parse.", doc.Error(), true);
1155 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -07001156
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001157 {
1158 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1159 XMLDocument doc;
1160 doc.Parse( xml, 10 );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001161 XMLTest( "Set length of incoming data", doc.Error(), false );
1162 }
1163
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001164 {
1165 XMLDocument doc;
1166 doc.LoadFile( "resources/dream.xml" );
1167 doc.Clear();
1168 XMLTest( "Document Clear()'s", doc.NoChildren(), true );
1169 }
1170
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001171 // ----------- Whitespace ------------
1172 {
1173 const char* xml = "<element>"
1174 "<a> This \nis &apos; text &apos; </a>"
1175 "<b> This is &apos; text &apos; \n</b>"
1176 "<c>This is &apos; \n\n text &apos;</c>"
1177 "</element>";
1178 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1179 doc.Parse( xml );
1180
1181 const XMLElement* element = doc.FirstChildElement();
1182 for( const XMLElement* parent = element->FirstChildElement();
1183 parent;
1184 parent = parent->NextSiblingElement() )
1185 {
1186 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1187 }
1188 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001189
Lee Thomasonae9ab072012-10-24 10:17:53 -07001190#if 0
1191 {
1192 // Passes if assert doesn't fire.
1193 XMLDocument xmlDoc;
1194
1195 xmlDoc.NewDeclaration();
1196 xmlDoc.NewComment("Configuration file");
1197
1198 XMLElement *root = xmlDoc.NewElement("settings");
1199 root->SetAttribute("version", 2);
1200 }
1201#endif
1202
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001203 {
1204 const char* xml = "<element> </element>";
1205 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1206 doc.Parse( xml );
1207 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1208 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001209
Lee Thomason5b0a6772012-11-19 13:54:42 -08001210 {
1211 // An assert should not fire.
1212 const char* xml = "<element/>";
1213 XMLDocument doc;
1214 doc.Parse( xml );
1215 XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope.
1216 XMLTest( "Tracking unused elements", true, ele != 0, false );
1217 }
1218
Lee Thomasona6412ac2012-12-13 15:39:11 -08001219
1220 {
1221 const char* xml = "<parent><child>abc</child></parent>";
1222 XMLDocument doc;
1223 doc.Parse( xml );
1224 XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
1225
1226 XMLPrinter printer;
1227 ele->Accept( &printer );
1228 XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1229 }
1230
1231
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001232 {
1233 XMLDocument doc;
1234 XMLError error = doc.LoadFile( "resources/empty.xml" );
1235 XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
Lee Thomason331596e2014-09-11 14:56:43 -07001236 XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() );
Lee Thomasonc7556672014-09-14 12:39:42 -07001237 doc.PrintError();
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001238 }
1239
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001240 {
1241 // BOM preservation
1242 static const char* xml_bom_preservation = "\xef\xbb\xbf<element/>\n";
1243 {
1244 XMLDocument doc;
1245 XMLTest( "BOM preservation (parse)", XML_NO_ERROR, doc.Parse( xml_bom_preservation ), false );
1246 XMLPrinter printer;
1247 doc.Print( &printer );
1248
1249 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1250 doc.SaveFile( "resources/bomtest.xml" );
1251 }
1252 {
1253 XMLDocument doc;
1254 doc.LoadFile( "resources/bomtest.xml" );
1255 XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
1256
1257 XMLPrinter printer;
1258 doc.Print( &printer );
1259 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1260 }
1261 }
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001262
Michael Daumlinged523282013-10-23 07:47:29 +02001263 {
1264 // Insertion with Removal
1265 const char* xml = "<?xml version=\"1.0\" ?>"
1266 "<root>"
1267 "<one>"
1268 "<subtree>"
1269 "<elem>element 1</elem>text<!-- comment -->"
1270 "</subtree>"
1271 "</one>"
1272 "<two/>"
1273 "</root>";
1274 const char* xmlInsideTwo = "<?xml version=\"1.0\" ?>"
1275 "<root>"
1276 "<one/>"
1277 "<two>"
1278 "<subtree>"
1279 "<elem>element 1</elem>text<!-- comment -->"
1280 "</subtree>"
1281 "</two>"
1282 "</root>";
1283 const char* xmlAfterOne = "<?xml version=\"1.0\" ?>"
1284 "<root>"
1285 "<one/>"
1286 "<subtree>"
1287 "<elem>element 1</elem>text<!-- comment -->"
1288 "</subtree>"
1289 "<two/>"
1290 "</root>";
1291 const char* xmlAfterTwo = "<?xml version=\"1.0\" ?>"
1292 "<root>"
1293 "<one/>"
1294 "<two/>"
1295 "<subtree>"
1296 "<elem>element 1</elem>text<!-- comment -->"
1297 "</subtree>"
1298 "</root>";
1299
1300 XMLDocument doc;
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001301 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001302 XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1303 XMLElement* two = doc.RootElement()->FirstChildElement("two");
1304 two->InsertFirstChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001305 XMLPrinter printer1(0, true);
1306 doc.Accept(&printer1);
1307 XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
Michael Daumlinged523282013-10-23 07:47:29 +02001308
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001309 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001310 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1311 two = doc.RootElement()->FirstChildElement("two");
1312 doc.RootElement()->InsertAfterChild(two, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001313 XMLPrinter printer2(0, true);
1314 doc.Accept(&printer2);
1315 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001316
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001317 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001318 XMLNode* one = doc.RootElement()->FirstChildElement("one");
1319 subtree = one->FirstChildElement("subtree");
1320 doc.RootElement()->InsertAfterChild(one, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001321 XMLPrinter printer3(0, true);
1322 doc.Accept(&printer3);
1323 XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001324
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001325 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001326 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1327 two = doc.RootElement()->FirstChildElement("two");
1328 doc.RootElement()->InsertEndChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001329 XMLPrinter printer4(0, true);
1330 doc.Accept(&printer4);
1331 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001332 }
1333
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001334 {
1335 const char* xml = "<svg width = \"128\" height = \"128\">"
1336 " <text> </text>"
1337 "</svg>";
1338 XMLDocument doc;
1339 doc.Parse(xml);
1340 doc.Print();
1341 }
1342
Lee Thomason92e521b2014-11-15 17:45:51 -08001343 {
1344 // Test that it doesn't crash.
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001345 const char* xml = "<?xml version=\"1.0\"?><root><sample><field0><1</field0><field1>2</field1></sample></root>";
1346 XMLDocument doc;
1347 doc.Parse(xml);
1348 doc.PrintError();
Lee Thomason92e521b2014-11-15 17:45:51 -08001349 }
1350
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001351#if 1
1352 // the question being explored is what kind of print to use:
1353 // https://github.com/leethomason/tinyxml2/issues/63
1354 {
1355 //const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
1356 const char* xml = "<element/>";
1357 XMLDocument doc;
1358 doc.Parse( xml );
1359 doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
1360 doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
1361 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
1362 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
1363 doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
1364 doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
1365
1366 doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
1367 doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
1368 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
1369 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
1370 doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
1371 doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
1372
1373 doc.Print();
1374
1375 /* The result of this test is platform, compiler, and library version dependent. :("
1376 XMLPrinter printer;
1377 doc.Print( &printer );
1378 XMLTest( "Float and double formatting.",
1379 "<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",
1380 printer.CStr(),
1381 true );
1382 */
1383 }
1384#endif
Lee Thomasonf07b9522014-10-30 13:25:12 -07001385
1386 {
1387 // Issue #184
1388 // If it doesn't assert, it passes. Caused by objects
1389 // getting created during parsing which are then
1390 // inaccessible in the memory pools.
1391 {
1392 XMLDocument doc;
1393 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1394 }
1395 {
1396 XMLDocument doc;
1397 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1398 doc.Clear();
1399 }
1400 }
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001401
1402 {
1403 // If this doesn't assert in DEBUG, all is well.
1404 tinyxml2::XMLDocument doc;
1405 tinyxml2::XMLElement *pRoot = doc.NewElement("Root");
1406 doc.DeleteNode(pRoot);
1407 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001408
Dmitry-Me8b67d742014-12-22 11:35:12 +03001409 {
1410 // Should not assert in DEBUG
1411 XMLPrinter printer;
1412 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001413
Lee Thomason6f381b72012-03-02 12:59:39 -08001414 // ----------- Performance tracking --------------
1415 {
1416#if defined( _MSC_VER )
1417 __int64 start, end, freq;
1418 QueryPerformanceFrequency( (LARGE_INTEGER*) &freq );
1419#endif
1420
Bruno Diasa2d4e6e2012-05-07 04:58:11 -03001421 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason6f381b72012-03-02 12:59:39 -08001422 fseek( fp, 0, SEEK_END );
1423 long size = ftell( fp );
1424 fseek( fp, 0, SEEK_SET );
1425
1426 char* mem = new char[size+1];
1427 fread( mem, size, 1, fp );
1428 fclose( fp );
1429 mem[size] = 0;
1430
1431#if defined( _MSC_VER )
1432 QueryPerformanceCounter( (LARGE_INTEGER*) &start );
1433#else
1434 clock_t cstart = clock();
1435#endif
1436 static const int COUNT = 10;
1437 for( int i=0; i<COUNT; ++i ) {
1438 XMLDocument doc;
1439 doc.Parse( mem );
1440 }
1441#if defined( _MSC_VER )
1442 QueryPerformanceCounter( (LARGE_INTEGER*) &end );
1443#else
1444 clock_t cend = clock();
1445#endif
1446
1447 delete [] mem;
1448
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001449 static const char* note =
Lee Thomason6f381b72012-03-02 12:59:39 -08001450#ifdef DEBUG
1451 "DEBUG";
1452#else
1453 "Release";
1454#endif
1455
1456#if defined( _MSC_VER )
1457 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, 1000.0 * (double)(end-start) / ( (double)freq * (double)COUNT) );
1458#else
1459 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart)/(double)COUNT );
1460#endif
1461 }
1462
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -08001463 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001464 _CrtMemCheckpoint( &endMemState );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001465
1466 _CrtMemState diffMemState;
1467 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
1468 _CrtMemDumpStatistics( &diffMemState );
1469 #endif
1470
1471 printf ("\nPass %d, Fail %d\n", gPass, gFail);
Lee Thomason (grinliz)db304252013-07-31 12:24:52 -07001472
1473 return gFail;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08001474}