blob: 31e11870c40d27038601410dd6ac04f8f167414c [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
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800866 const char* str = " ";
867 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 {
873 // Low entities
874 XMLDocument doc;
875 doc.Parse( "<test>&#x0e;</test>" );
876 const char result[] = { 0x0e, 0 };
877 XMLTest( "Low entities.", doc.FirstChildElement()->GetText(), result );
878 doc.Print();
879 }
880
881 {
882 // Attribute values with trailing quotes not handled correctly
883 XMLDocument doc;
884 doc.Parse( "<foo attribute=bar\" />" );
885 XMLTest( "Throw error with bad end quotes.", doc.Error(), true );
886 }
887
888 {
889 // [ 1663758 ] Failure to report error on bad XML
890 XMLDocument xml;
891 xml.Parse("<x>");
892 XMLTest("Missing end tag at end of input", xml.Error(), true);
893 xml.Parse("<x> ");
894 XMLTest("Missing end tag with trailing whitespace", xml.Error(), true);
895 xml.Parse("<x></y>");
Lee Thomason2fa81722012-11-09 12:37:46 -0800896 XMLTest("Mismatched tags", xml.ErrorID(), XML_ERROR_MISMATCHED_ELEMENT);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700897 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800898
899
900 {
901 // [ 1475201 ] TinyXML parses entities in comments
902 XMLDocument xml;
903 xml.Parse("<!-- declarations for <head> & <body> -->"
904 "<!-- far &amp; away -->" );
905
906 XMLNode* e0 = xml.FirstChild();
907 XMLNode* e1 = e0->NextSibling();
908 XMLComment* c0 = e0->ToComment();
909 XMLComment* c1 = e1->ToComment();
910
911 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
912 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
913 }
914
915 {
916 XMLDocument xml;
917 xml.Parse( "<Parent>"
918 "<child1 att=''/>"
919 "<!-- With this comment, child2 will not be parsed! -->"
920 "<child2 att=''/>"
921 "</Parent>" );
922 xml.Print();
923
924 int count = 0;
925
926 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
927 ele;
928 ele = ele->NextSibling() )
929 {
930 ++count;
931 }
932
933 XMLTest( "Comments iterate correctly.", 3, count );
934 }
935
936 {
937 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
938 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
939 buf[60] = 239;
940 buf[61] = 0;
941
942 XMLDocument doc;
943 doc.Parse( (const char*)buf);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700944 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800945
946
947 {
948 // bug 1827248 Error while parsing a little bit malformed file
949 // Actually not malformed - should work.
950 XMLDocument xml;
951 xml.Parse( "<attributelist> </attributelist >" );
952 XMLTest( "Handle end tag whitespace", false, xml.Error() );
953 }
954
955 {
956 // This one must not result in an infinite loop
957 XMLDocument xml;
958 xml.Parse( "<infinite>loop" );
959 XMLTest( "Infinite loop test.", true, true );
960 }
961#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800962 {
963 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
964 XMLDocument doc;
965 doc.Parse( pub );
966
967 XMLDocument clone;
968 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
969 XMLNode* copy = node->ShallowClone( &clone );
970 clone.InsertEndChild( copy );
971 }
972
973 clone.Print();
974
975 int count=0;
976 const XMLNode* a=clone.FirstChild();
977 const XMLNode* b=doc.FirstChild();
978 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
979 ++count;
980 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
981 }
982 XMLTest( "Clone and Equal", 4, count );
983 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800984
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700985 {
986 // This shouldn't crash.
987 XMLDocument doc;
988 if(XML_NO_ERROR != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
989 {
990 doc.PrintError();
991 }
992 XMLTest( "Error in snprinf handling.", true, doc.Error() );
993 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700994
Lee Thomason5e3803c2012-04-16 08:57:05 -0700995 {
996 // Attribute ordering.
997 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
998 XMLDocument doc;
999 doc.Parse( xml );
1000 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001001
Lee Thomason5e3803c2012-04-16 08:57:05 -07001002 const XMLAttribute* a = ele->FirstAttribute();
1003 XMLTest( "Attribute order", "1", a->Value() );
1004 a = a->Next();
1005 XMLTest( "Attribute order", "2", a->Value() );
1006 a = a->Next();
1007 XMLTest( "Attribute order", "3", a->Value() );
1008 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001009
Lee Thomason5e3803c2012-04-16 08:57:05 -07001010 ele->DeleteAttribute( "attrib2" );
1011 a = ele->FirstAttribute();
1012 XMLTest( "Attribute order", "1", a->Value() );
1013 a = a->Next();
1014 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001015
Lee Thomason5e3803c2012-04-16 08:57:05 -07001016 ele->DeleteAttribute( "attrib1" );
1017 ele->DeleteAttribute( "attrib3" );
1018 XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
1019 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001020
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001021 {
1022 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -07001023 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
1024 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
1025 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
1026 XMLDocument doc0;
1027 doc0.Parse( xml0 );
1028 XMLDocument doc1;
1029 doc1.Parse( xml1 );
1030 XMLDocument doc2;
1031 doc2.Parse( xml2 );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001032
Lee Thomason78a773d2012-07-02 10:10:19 -07001033 XMLElement* ele = 0;
1034 ele = doc0.FirstChildElement();
1035 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
1036 ele = doc1.FirstChildElement();
1037 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
1038 ele = doc2.FirstChildElement();
1039 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001040 }
1041
1042 {
1043 // Make sure we don't go into an infinite loop.
1044 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
1045 XMLDocument doc;
1046 doc.Parse( xml );
1047 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
1048 XMLElement* ele1 = ele0->NextSiblingElement();
1049 bool equal = ele0->ShallowEqual( ele1 );
1050
1051 XMLTest( "Infinite loop in shallow equal.", true, equal );
1052 }
1053
Lee Thomason5708f812012-03-28 17:46:41 -07001054 // -------- Handles ------------
1055 {
1056 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1057 XMLDocument doc;
1058 doc.Parse( xml );
Lee Thomason5708f812012-03-28 17:46:41 -07001059
1060 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
1061 XMLTest( "Handle, success, mutable", ele->Value(), "sub" );
1062
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001063 XMLHandle docH( doc );
1064 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001065 XMLTest( "Handle, dne, mutable", false, ele != 0 );
Lee Thomason5708f812012-03-28 17:46:41 -07001066 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001067
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001068 {
1069 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1070 XMLDocument doc;
1071 doc.Parse( xml );
1072 XMLConstHandle docH( doc );
1073
1074 const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
1075 XMLTest( "Handle, success, const", ele->Value(), "sub" );
1076
1077 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001078 XMLTest( "Handle, dne, const", false, ele != 0 );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001079 }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001080 {
1081 // Default Declaration & BOM
1082 XMLDocument doc;
1083 doc.InsertEndChild( doc.NewDeclaration() );
1084 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001085
Lee Thomasonf68c4382012-04-28 14:37:11 -07001086 XMLPrinter printer;
1087 doc.Print( &printer );
1088
1089 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1090 XMLTest( "BOM and default declaration", printer.CStr(), result, false );
Lee Thomason (grinliz)48ea0bc2012-05-26 14:41:14 -07001091 XMLTest( "CStrSize", printer.CStrSize(), 42, false );
Lee Thomasonf68c4382012-04-28 14:37:11 -07001092 }
Lee Thomason21be8822012-07-15 17:27:22 -07001093 {
1094 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1095 XMLDocument doc;
1096 doc.Parse( xml );
1097 XMLTest( "Ill formed XML", true, doc.Error() );
1098 }
1099
1100 // QueryXYZText
1101 {
1102 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1103 XMLDocument doc;
1104 doc.Parse( xml );
1105
1106 const XMLElement* pointElement = doc.RootElement();
1107
1108 int intValue = 0;
1109 unsigned unsignedValue = 0;
1110 float floatValue = 0;
1111 double doubleValue = 0;
1112 bool boolValue = false;
1113
1114 pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1115 pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1116 pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1117 pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1118 pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1119
1120
1121 XMLTest( "QueryIntText", intValue, 1, false );
1122 XMLTest( "QueryUnsignedText", unsignedValue, (unsigned)1, false );
1123 XMLTest( "QueryFloatText", floatValue, 1.2f, false );
1124 XMLTest( "QueryDoubleText", doubleValue, 1.2, false );
1125 XMLTest( "QueryBoolText", boolValue, true, false );
1126 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001127
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001128 {
1129 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1130 XMLDocument doc;
1131 doc.Parse( xml );
1132 XMLTest( "Non-alpha element lead letter parses.", doc.Error(), false );
1133 }
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001134
1135 {
1136 const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1137 XMLDocument doc;
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001138 doc.Parse( xml );
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001139 XMLTest("Non-alpha attribute lead character parses.", doc.Error(), false);
1140 }
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001141
1142 {
1143 const char* xml = "<3lement></3lement>";
1144 XMLDocument doc;
1145 doc.Parse( xml );
1146 XMLTest("Element names with lead digit fail to parse.", doc.Error(), true);
1147 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -07001148
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001149 {
1150 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1151 XMLDocument doc;
1152 doc.Parse( xml, 10 );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001153 XMLTest( "Set length of incoming data", doc.Error(), false );
1154 }
1155
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001156 {
1157 XMLDocument doc;
1158 doc.LoadFile( "resources/dream.xml" );
1159 doc.Clear();
1160 XMLTest( "Document Clear()'s", doc.NoChildren(), true );
1161 }
1162
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001163 // ----------- Whitespace ------------
1164 {
1165 const char* xml = "<element>"
1166 "<a> This \nis &apos; text &apos; </a>"
1167 "<b> This is &apos; text &apos; \n</b>"
1168 "<c>This is &apos; \n\n text &apos;</c>"
1169 "</element>";
1170 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1171 doc.Parse( xml );
1172
1173 const XMLElement* element = doc.FirstChildElement();
1174 for( const XMLElement* parent = element->FirstChildElement();
1175 parent;
1176 parent = parent->NextSiblingElement() )
1177 {
1178 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1179 }
1180 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001181
Lee Thomasonae9ab072012-10-24 10:17:53 -07001182#if 0
1183 {
1184 // Passes if assert doesn't fire.
1185 XMLDocument xmlDoc;
1186
1187 xmlDoc.NewDeclaration();
1188 xmlDoc.NewComment("Configuration file");
1189
1190 XMLElement *root = xmlDoc.NewElement("settings");
1191 root->SetAttribute("version", 2);
1192 }
1193#endif
1194
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001195 {
1196 const char* xml = "<element> </element>";
1197 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1198 doc.Parse( xml );
1199 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1200 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001201
Lee Thomason5b0a6772012-11-19 13:54:42 -08001202 {
1203 // An assert should not fire.
1204 const char* xml = "<element/>";
1205 XMLDocument doc;
1206 doc.Parse( xml );
1207 XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope.
1208 XMLTest( "Tracking unused elements", true, ele != 0, false );
1209 }
1210
Lee Thomasona6412ac2012-12-13 15:39:11 -08001211
1212 {
1213 const char* xml = "<parent><child>abc</child></parent>";
1214 XMLDocument doc;
1215 doc.Parse( xml );
1216 XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
1217
1218 XMLPrinter printer;
1219 ele->Accept( &printer );
1220 XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1221 }
1222
1223
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001224 {
1225 XMLDocument doc;
1226 XMLError error = doc.LoadFile( "resources/empty.xml" );
1227 XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
Lee Thomason331596e2014-09-11 14:56:43 -07001228 XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() );
Lee Thomasonc7556672014-09-14 12:39:42 -07001229 doc.PrintError();
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001230 }
1231
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001232 {
1233 // BOM preservation
1234 static const char* xml_bom_preservation = "\xef\xbb\xbf<element/>\n";
1235 {
1236 XMLDocument doc;
1237 XMLTest( "BOM preservation (parse)", XML_NO_ERROR, doc.Parse( xml_bom_preservation ), false );
1238 XMLPrinter printer;
1239 doc.Print( &printer );
1240
1241 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1242 doc.SaveFile( "resources/bomtest.xml" );
1243 }
1244 {
1245 XMLDocument doc;
1246 doc.LoadFile( "resources/bomtest.xml" );
1247 XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
1248
1249 XMLPrinter printer;
1250 doc.Print( &printer );
1251 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1252 }
1253 }
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001254
Michael Daumlinged523282013-10-23 07:47:29 +02001255 {
1256 // Insertion with Removal
1257 const char* xml = "<?xml version=\"1.0\" ?>"
1258 "<root>"
1259 "<one>"
1260 "<subtree>"
1261 "<elem>element 1</elem>text<!-- comment -->"
1262 "</subtree>"
1263 "</one>"
1264 "<two/>"
1265 "</root>";
1266 const char* xmlInsideTwo = "<?xml version=\"1.0\" ?>"
1267 "<root>"
1268 "<one/>"
1269 "<two>"
1270 "<subtree>"
1271 "<elem>element 1</elem>text<!-- comment -->"
1272 "</subtree>"
1273 "</two>"
1274 "</root>";
1275 const char* xmlAfterOne = "<?xml version=\"1.0\" ?>"
1276 "<root>"
1277 "<one/>"
1278 "<subtree>"
1279 "<elem>element 1</elem>text<!-- comment -->"
1280 "</subtree>"
1281 "<two/>"
1282 "</root>";
1283 const char* xmlAfterTwo = "<?xml version=\"1.0\" ?>"
1284 "<root>"
1285 "<one/>"
1286 "<two/>"
1287 "<subtree>"
1288 "<elem>element 1</elem>text<!-- comment -->"
1289 "</subtree>"
1290 "</root>";
1291
1292 XMLDocument doc;
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001293 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001294 XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1295 XMLElement* two = doc.RootElement()->FirstChildElement("two");
1296 two->InsertFirstChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001297 XMLPrinter printer1(0, true);
1298 doc.Accept(&printer1);
1299 XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
Michael Daumlinged523282013-10-23 07:47:29 +02001300
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001301 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001302 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1303 two = doc.RootElement()->FirstChildElement("two");
1304 doc.RootElement()->InsertAfterChild(two, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001305 XMLPrinter printer2(0, true);
1306 doc.Accept(&printer2);
1307 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
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 XMLNode* one = doc.RootElement()->FirstChildElement("one");
1311 subtree = one->FirstChildElement("subtree");
1312 doc.RootElement()->InsertAfterChild(one, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001313 XMLPrinter printer3(0, true);
1314 doc.Accept(&printer3);
1315 XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.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 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1319 two = doc.RootElement()->FirstChildElement("two");
1320 doc.RootElement()->InsertEndChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001321 XMLPrinter printer4(0, true);
1322 doc.Accept(&printer4);
1323 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001324 }
1325
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001326 {
1327 const char* xml = "<svg width = \"128\" height = \"128\">"
1328 " <text> </text>"
1329 "</svg>";
1330 XMLDocument doc;
1331 doc.Parse(xml);
1332 doc.Print();
1333 }
1334
Lee Thomason92e521b2014-11-15 17:45:51 -08001335 {
1336 // Test that it doesn't crash.
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001337 const char* xml = "<?xml version=\"1.0\"?><root><sample><field0><1</field0><field1>2</field1></sample></root>";
1338 XMLDocument doc;
1339 doc.Parse(xml);
1340 doc.PrintError();
Lee Thomason92e521b2014-11-15 17:45:51 -08001341 }
1342
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001343#if 1
1344 // the question being explored is what kind of print to use:
1345 // https://github.com/leethomason/tinyxml2/issues/63
1346 {
1347 //const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
1348 const char* xml = "<element/>";
1349 XMLDocument doc;
1350 doc.Parse( xml );
1351 doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
1352 doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
1353 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
1354 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
1355 doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
1356 doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
1357
1358 doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
1359 doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
1360 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
1361 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
1362 doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
1363 doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
1364
1365 doc.Print();
1366
1367 /* The result of this test is platform, compiler, and library version dependent. :("
1368 XMLPrinter printer;
1369 doc.Print( &printer );
1370 XMLTest( "Float and double formatting.",
1371 "<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",
1372 printer.CStr(),
1373 true );
1374 */
1375 }
1376#endif
Lee Thomasonf07b9522014-10-30 13:25:12 -07001377
1378 {
1379 // Issue #184
1380 // If it doesn't assert, it passes. Caused by objects
1381 // getting created during parsing which are then
1382 // inaccessible in the memory pools.
1383 {
1384 XMLDocument doc;
1385 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1386 }
1387 {
1388 XMLDocument doc;
1389 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1390 doc.Clear();
1391 }
1392 }
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001393
1394 {
1395 // If this doesn't assert in DEBUG, all is well.
1396 tinyxml2::XMLDocument doc;
1397 tinyxml2::XMLElement *pRoot = doc.NewElement("Root");
1398 doc.DeleteNode(pRoot);
1399 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001400
Dmitry-Me8b67d742014-12-22 11:35:12 +03001401 {
1402 // Should not assert in DEBUG
1403 XMLPrinter printer;
1404 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001405
Lee Thomason6f381b72012-03-02 12:59:39 -08001406 // ----------- Performance tracking --------------
1407 {
1408#if defined( _MSC_VER )
1409 __int64 start, end, freq;
1410 QueryPerformanceFrequency( (LARGE_INTEGER*) &freq );
1411#endif
1412
Bruno Diasa2d4e6e2012-05-07 04:58:11 -03001413 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason6f381b72012-03-02 12:59:39 -08001414 fseek( fp, 0, SEEK_END );
1415 long size = ftell( fp );
1416 fseek( fp, 0, SEEK_SET );
1417
1418 char* mem = new char[size+1];
1419 fread( mem, size, 1, fp );
1420 fclose( fp );
1421 mem[size] = 0;
1422
1423#if defined( _MSC_VER )
1424 QueryPerformanceCounter( (LARGE_INTEGER*) &start );
1425#else
1426 clock_t cstart = clock();
1427#endif
1428 static const int COUNT = 10;
1429 for( int i=0; i<COUNT; ++i ) {
1430 XMLDocument doc;
1431 doc.Parse( mem );
1432 }
1433#if defined( _MSC_VER )
1434 QueryPerformanceCounter( (LARGE_INTEGER*) &end );
1435#else
1436 clock_t cend = clock();
1437#endif
1438
1439 delete [] mem;
1440
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001441 static const char* note =
Lee Thomason6f381b72012-03-02 12:59:39 -08001442#ifdef DEBUG
1443 "DEBUG";
1444#else
1445 "Release";
1446#endif
1447
1448#if defined( _MSC_VER )
1449 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, 1000.0 * (double)(end-start) / ( (double)freq * (double)COUNT) );
1450#else
1451 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart)/(double)COUNT );
1452#endif
1453 }
1454
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -08001455 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001456 _CrtMemCheckpoint( &endMemState );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001457
1458 _CrtMemState diffMemState;
1459 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
1460 _CrtMemDumpStatistics( &diffMemState );
1461 #endif
1462
1463 printf ("\nPass %d, Fail %d\n", gPass, gFail);
Lee Thomason (grinliz)db304252013-07-31 12:24:52 -07001464
1465 return gFail;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08001466}