blob: 24a68bd1b4a1f3e7882a61a069c6e8d94e0f95b1 [file] [log] [blame]
Lee Thomason5b0a6772012-11-19 13:54:42 -08001#if defined( _MSC_VER )
2 #define _CRT_SECURE_NO_WARNINGS // This test file is not intended to be secure.
3#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08004
Lee Thomason5b0a6772012-11-19 13:54:42 -08005#include "tinyxml2.h"
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -07006#include <cstdlib>
7#include <cstring>
8#include <ctime>
U-Lama\Leee13c3e62011-12-28 14:36:55 -08009
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080010#if defined( _MSC_VER )
Lee Thomasone9699e62012-07-25 12:24:23 -070011 #include <direct.h> // _mkdir
Lee Thomason1ff38e02012-02-14 18:18:16 -080012 #include <crtdbg.h>
Lee Thomason6f381b72012-03-02 12:59:39 -080013 #define WIN32_LEAN_AND_MEAN
14 #include <windows.h>
Lee Thomason1ff38e02012-02-14 18:18:16 -080015 _CrtMemState startMemState;
16 _CrtMemState endMemState;
Martinsh Shaiters39ddc262013-01-15 21:53:08 +020017#elif defined(MINGW32) || defined(__MINGW32__)
18 #include <io.h> // mkdir
Lee Thomasone9699e62012-07-25 12:24:23 -070019#else
20 #include <sys/stat.h> // mkdir
Lee Thomason1ff38e02012-02-14 18:18:16 -080021#endif
Lee Thomasone9ecdab2012-02-13 18:11:20 -080022
U-Lama\Leee13c3e62011-12-28 14:36:55 -080023using namespace tinyxml2;
Lee Thomasonec5a7b42012-02-13 18:16:52 -080024int gPass = 0;
25int gFail = 0;
26
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -080027
U-Stream\Lee09a11c52012-02-17 08:31:16 -080028bool XMLTest (const char* testString, const char* expected, const char* found, bool echo=true )
Lee Thomason1ff38e02012-02-14 18:18:16 -080029{
30 bool pass = !strcmp( expected, found );
31 if ( pass )
32 printf ("[pass]");
33 else
34 printf ("[fail]");
35
U-Stream\Lee09a11c52012-02-17 08:31:16 -080036 if ( !echo )
Lee Thomason1ff38e02012-02-14 18:18:16 -080037 printf (" %s\n", testString);
38 else
39 printf (" %s [%s][%s]\n", testString, expected, found);
40
41 if ( pass )
42 ++gPass;
43 else
44 ++gFail;
45 return pass;
46}
47
48
Lee Thomason21be8822012-07-15 17:27:22 -070049template< class T > bool XMLTest( const char* testString, T expected, T found, bool echo=true )
Lee Thomason1ff38e02012-02-14 18:18:16 -080050{
51 bool pass = ( expected == found );
52 if ( pass )
53 printf ("[pass]");
54 else
55 printf ("[fail]");
56
U-Stream\Lee09a11c52012-02-17 08:31:16 -080057 if ( !echo )
Lee Thomason1ff38e02012-02-14 18:18:16 -080058 printf (" %s\n", testString);
59 else
Lee Thomasonc8312792012-07-16 12:44:41 -070060 printf (" %s [%d][%d]\n", testString, static_cast<int>(expected), static_cast<int>(found) );
Lee Thomason1ff38e02012-02-14 18:18:16 -080061
62 if ( pass )
63 ++gPass;
64 else
65 ++gFail;
66 return pass;
67}
Lee Thomasonec5a7b42012-02-13 18:16:52 -080068
U-Lama\Leee13c3e62011-12-28 14:36:55 -080069
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -080070void NullLineEndings( char* p )
71{
72 while( p && *p ) {
73 if ( *p == '\n' || *p == '\r' ) {
74 *p = 0;
75 return;
76 }
77 ++p;
78 }
79}
80
81
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070082int example_1()
83{
84 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -030085 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070086
87 return doc.ErrorID();
88}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +020089/** @page Example-1 Load an XML File
90 * @dontinclude ./xmltest.cpp
91 * Basic XML file loading.
92 * The basic syntax to load an XML file from
93 * disk and check for an error. (ErrorID()
94 * will return 0 for no error.)
95 * @skip example_1()
96 * @until }
97 */
98
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070099
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700100int example_2()
101{
102 static const char* xml = "<element/>";
103 XMLDocument doc;
104 doc.Parse( xml );
105
106 return doc.ErrorID();
107}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200108/** @page Example-2 Parse an XML from char buffer
109 * @dontinclude ./xmltest.cpp
110 * Basic XML string parsing.
111 * The basic syntax to parse an XML for
112 * a char* and check for an error. (ErrorID()
113 * will return 0 for no error.)
114 * @skip example_2()
115 * @until }
116 */
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700117
118
119int example_3()
120{
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700121 static const char* xml =
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700122 "<?xml version=\"1.0\"?>"
123 "<!DOCTYPE PLAY SYSTEM \"play.dtd\">"
124 "<PLAY>"
125 "<TITLE>A Midsummer Night's Dream</TITLE>"
126 "</PLAY>";
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700127
128 XMLDocument doc;
129 doc.Parse( xml );
130
131 XMLElement* titleElement = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" );
132 const char* title = titleElement->GetText();
133 printf( "Name of play (1): %s\n", title );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700134
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700135 XMLText* textNode = titleElement->FirstChild()->ToText();
136 title = textNode->Value();
137 printf( "Name of play (2): %s\n", title );
138
139 return doc.ErrorID();
140}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200141/** @page Example-3 Get information out of XML
142 @dontinclude ./xmltest.cpp
143 In this example, we navigate a simple XML
144 file, and read some interesting text. Note
145 that this is examlpe doesn't use error
146 checking; working code should check for null
147 pointers when walking an XML tree, or use
148 XMLHandle.
149
150 (The XML is an excerpt from "dream.xml").
151
152 @skip example_3()
153 @until </PLAY>";
154
155 The structure of the XML file is:
156
157 <ul>
158 <li>(declaration)</li>
159 <li>(dtd stuff)</li>
160 <li>Element "PLAY"</li>
161 <ul>
162 <li>Element "TITLE"</li>
163 <ul>
164 <li>Text "A Midsummer Night's Dream"</li>
165 </ul>
166 </ul>
167 </ul>
168
169 For this example, we want to print out the
170 title of the play. The text of the title (what
171 we want) is child of the "TITLE" element which
172 is a child of the "PLAY" element.
173
174 We want to skip the declaration and dtd, so the
175 method FirstChildElement() is a good choice. The
176 FirstChildElement() of the Document is the "PLAY"
177 Element, the FirstChildElement() of the "PLAY" Element
178 is the "TITLE" Element.
179
180 @until ( "TITLE" );
181
182 We can then use the convenience function GetText()
183 to get the title of the play.
184
185 @until title );
186
187 Text is just another Node in the XML DOM. And in
188 fact you should be a little cautious with it, as
189 text nodes can contain elements.
190
191 @verbatim
192 Consider: A Midsummer Night's <b>Dream</b>
193 @endverbatim
194
195 It is more correct to actually query the Text Node
196 if in doubt:
197
198 @until title );
199
200 Noting that here we use FirstChild() since we are
201 looking for XMLText, not an element, and ToText()
202 is a cast from a Node to a XMLText.
203*/
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700204
205
Lee Thomason21be8822012-07-15 17:27:22 -0700206bool example_4()
207{
208 static const char* xml =
209 "<information>"
210 " <attributeApproach v='2' />"
211 " <textApproach>"
212 " <v>2</v>"
213 " </textApproach>"
214 "</information>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700215
Lee Thomason21be8822012-07-15 17:27:22 -0700216 XMLDocument doc;
217 doc.Parse( xml );
218
219 int v0 = 0;
220 int v1 = 0;
221
222 XMLElement* attributeApproachElement = doc.FirstChildElement()->FirstChildElement( "attributeApproach" );
223 attributeApproachElement->QueryIntAttribute( "v", &v0 );
224
225 XMLElement* textApproachElement = doc.FirstChildElement()->FirstChildElement( "textApproach" );
226 textApproachElement->FirstChildElement( "v" )->QueryIntText( &v1 );
227
228 printf( "Both values are the same: %d and %d\n", v0, v1 );
229
230 return !doc.Error() && ( v0 == v1 );
231}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200232/** @page Example-4 Read attributes and text information.
233 @dontinclude ./xmltest.cpp
234
235 There are fundamentally 2 ways of writing a key-value
236 pair into an XML file. (Something that's always annoyed
237 me about XML.) Either by using attributes, or by writing
238 the key name into an element and the value into
239 the text node wrapped by the element. Both approaches
240 are illustrated in this example, which shows two ways
241 to encode the value "2" into the key "v":
242
243 @skip example_4()
244 @until "</information>";
245
246 TinyXML-2 has accessors for both approaches.
247
248 When using an attribute, you navigate to the XMLElement
249 with that attribute and use the QueryIntAttribute()
250 group of methods. (Also QueryFloatAttribute(), etc.)
251
252 @skip XMLElement* attributeApproachElement
253 @until &v0 );
254
255 When using the text approach, you need to navigate
256 down one more step to the XMLElement that contains
257 the text. Note the extra FirstChildElement( "v" )
258 in the code below. The value of the text can then
259 be safely queried with the QueryIntText() group
260 of methods. (Also QueryFloatText(), etc.)
261
262 @skip XMLElement* textApproachElement
263 @until &v1 );
264*/
Lee Thomason21be8822012-07-15 17:27:22 -0700265
266
Lee Thomason178e4cc2013-01-25 16:19:05 -0800267int main( int argc, const char ** argv )
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800268{
Lee Thomason (grinliz)0a4df402012-02-27 20:50:52 -0800269 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason1ff38e02012-02-14 18:18:16 -0800270 _CrtMemCheckpoint( &startMemState );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700271 #endif
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800272
Martinsh Shaiters39ddc262013-01-15 21:53:08 +0200273 #if defined(_MSC_VER) || defined(MINGW32) || defined(__MINGW32__)
Lee Thomasone9699e62012-07-25 12:24:23 -0700274 _mkdir( "resources/out/" );
275 #else
276 mkdir( "resources/out/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
277 #endif
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400278
Lee Thomason178e4cc2013-01-25 16:19:05 -0800279 if ( argc > 1 ) {
280 XMLDocument* doc = new XMLDocument();
281 clock_t startTime = clock();
282 doc->LoadFile( argv[1] );
283 clock_t loadTime = clock();
284 int errorID = doc->ErrorID();
285 delete doc; doc = 0;
286 clock_t deleteTime = clock();
287
288 printf( "Test file '%s' loaded. ErrorID=%d\n", argv[1], errorID );
289 if ( !errorID ) {
290 printf( "Load time=%d\n", loadTime - startTime );
291 printf( "Delete time=%d\n", deleteTime - loadTime );
Lee Thomason (grinliz)ac83b4e2013-02-01 09:02:34 -0800292 printf( "Total time=%d\n", deleteTime - startTime );
Lee Thomason178e4cc2013-01-25 16:19:05 -0800293 }
294 exit(0);
295 }
296
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300297 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason7f7b1622012-03-24 12:49:03 -0700298 if ( !fp ) {
299 printf( "Error opening test file 'dream.xml'.\n"
300 "Is your working directory the same as where \n"
301 "the xmltest.cpp and dream.xml file are?\n\n"
302 #if defined( _MSC_VER )
303 "In windows Visual Studio you may need to set\n"
304 "Properties->Debugging->Working Directory to '..'\n"
305 #endif
306 );
307 exit( 1 );
308 }
309 fclose( fp );
310
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700311 XMLTest( "Example-1", 0, example_1() );
312 XMLTest( "Example-2", 0, example_2() );
313 XMLTest( "Example-3", 0, example_3() );
Lee Thomason21be8822012-07-15 17:27:22 -0700314 XMLTest( "Example-4", true, example_4() );
Lee Thomason87e475a2012-03-20 11:55:29 -0700315
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700316 /* ------ Example 2: Lookup information. ---- */
Lee Thomason87e475a2012-03-20 11:55:29 -0700317
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800318 {
Lee Thomason43f59302012-02-06 18:18:11 -0800319 static const char* test[] = { "<element />",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400320 "<element></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800321 "<element><subelement/></element>",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400322 "<element><subelement></subelement></element>",
323 "<element><subelement><subsub/></subelement></element>",
324 "<!--comment beside elements--><element><subelement></subelement></element>",
325 "<!--comment beside elements, this time with spaces--> \n <element> <subelement> \n </subelement> </element>",
326 "<element attrib1='foo' attrib2=\"bar\" ></element>",
327 "<element attrib1='foo' attrib2=\"bar\" ><subelement attrib3='yeehaa' /></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800328 "<element>Text inside element.</element>",
329 "<element><b></b></element>",
330 "<element>Text inside and <b>bolded</b> in the element.</element>",
331 "<outer><element>Text inside and <b>bolded</b> in the element.</element></outer>",
Lee Thomason8ee79892012-01-25 17:44:30 -0800332 "<element>This &amp; That.</element>",
Lee Thomason18d68bd2012-01-26 18:17:26 -0800333 "<element attrib='This&lt;That' />",
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800334 0
335 };
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800336 for( int i=0; test[i]; ++i ) {
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800337 XMLDocument doc;
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800338 doc.Parse( test[i] );
Lee Thomason5cae8972012-01-24 18:03:07 -0800339 doc.Print();
Lee Thomasonec975ce2012-01-23 11:42:06 -0800340 printf( "----------------------------------------------\n" );
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800341 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800342 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800343#if 1
Lee Thomasond6277762012-02-22 16:00:12 -0800344 {
345 static const char* test = "<!--hello world\n"
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400346 " line 2\r"
347 " line 3\r\n"
348 " line 4\n\r"
349 " line 5\r-->";
Lee Thomasond6277762012-02-22 16:00:12 -0800350
351 XMLDocument doc;
352 doc.Parse( test );
353 doc.Print();
354 }
355
Lee Thomason2c85a712012-01-31 08:24:24 -0800356 {
357 static const char* test = "<element>Text before.</element>";
358 XMLDocument doc;
359 doc.Parse( test );
360 XMLElement* root = doc.FirstChildElement();
361 XMLElement* newElement = doc.NewElement( "Subelement" );
362 root->InsertEndChild( newElement );
363 doc.Print();
364 }
Lee Thomasond1983222012-02-06 08:41:24 -0800365 {
366 XMLDocument* doc = new XMLDocument();
367 static const char* test = "<element><sub/></element>";
368 doc->Parse( test );
369 delete doc;
370 }
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800371 {
Lee Thomason1ff38e02012-02-14 18:18:16 -0800372 // Test: Programmatic DOM
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800373 // Build:
374 // <element>
375 // <!--comment-->
376 // <sub attrib="1" />
377 // <sub attrib="2" />
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800378 // <sub attrib="3" >& Text!</sub>
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800379 // <element>
380
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800381 XMLDocument* doc = new XMLDocument();
Lee Thomason1ff38e02012-02-14 18:18:16 -0800382 XMLNode* element = doc->InsertEndChild( doc->NewElement( "element" ) );
383
384 XMLElement* sub[3] = { doc->NewElement( "sub" ), doc->NewElement( "sub" ), doc->NewElement( "sub" ) };
385 for( int i=0; i<3; ++i ) {
386 sub[i]->SetAttribute( "attrib", i );
387 }
388 element->InsertEndChild( sub[2] );
389 XMLNode* comment = element->InsertFirstChild( doc->NewComment( "comment" ) );
390 element->InsertAfterChild( comment, sub[0] );
391 element->InsertAfterChild( sub[0], sub[1] );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800392 sub[2]->InsertFirstChild( doc->NewText( "& Text!" ));
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800393 doc->Print();
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800394 XMLTest( "Programmatic DOM", "comment", doc->FirstChildElement( "element" )->FirstChild()->Value() );
395 XMLTest( "Programmatic DOM", "0", doc->FirstChildElement( "element" )->FirstChildElement()->Attribute( "attrib" ) );
396 XMLTest( "Programmatic DOM", 2, doc->FirstChildElement()->LastChildElement( "sub" )->IntAttribute( "attrib" ) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700397 XMLTest( "Programmatic DOM", "& Text!",
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800398 doc->FirstChildElement()->LastChildElement( "sub" )->FirstChild()->ToText()->Value() );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800399
400 // And now deletion:
401 element->DeleteChild( sub[2] );
402 doc->DeleteNode( comment );
403
404 element->FirstChildElement()->SetAttribute( "attrib", true );
405 element->LastChildElement()->DeleteAttribute( "attrib" );
406
407 XMLTest( "Programmatic DOM", true, doc->FirstChildElement()->FirstChildElement()->BoolAttribute( "attrib" ) );
408 int value = 10;
409 int result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value );
Lee Thomason21be8822012-07-15 17:27:22 -0700410 XMLTest( "Programmatic DOM", result, (int)XML_NO_ATTRIBUTE );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800411 XMLTest( "Programmatic DOM", value, 10 );
412
413 doc->Print();
414
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700415 {
416 XMLPrinter streamer;
417 doc->Print( &streamer );
418 printf( "%s", streamer.CStr() );
419 }
420 {
421 XMLPrinter streamer( 0, true );
422 doc->Print( &streamer );
423 XMLTest( "Compact mode", "<element><sub attrib=\"1\"/><sub/></element>", streamer.CStr(), false );
424 }
Lee Thomason (grinliz)6b8b0122012-09-08 21:21:00 -0700425 doc->SaveFile( "./resources/out/pretty.xml" );
426 doc->SaveFile( "./resources/out/compact.xml", true );
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800427 delete doc;
428 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800429 {
430 // Test: Dream
431 // XML1 : 1,187,569 bytes in 31,209 allocations
432 // XML2 : 469,073 bytes in 323 allocations
433 //int newStart = gNew;
434 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300435 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800436
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400437 doc.SaveFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800438 doc.PrintError();
439
440 XMLTest( "Dream", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400441 doc.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800442 XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false );
443 XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
444 doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
445 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400446 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800447 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400448 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800449
450 XMLDocument doc2;
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400451 doc2.LoadFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800452 XMLTest( "Dream-out", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400453 doc2.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800454 XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false );
455 XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
456 doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
457 XMLTest( "Dream-out", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400458 doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800459
460 //gNewTotal = gNew - newStart;
461 }
Lee Thomason6f381b72012-03-02 12:59:39 -0800462
463
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800464 {
465 const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
466 "<passages count=\"006\" formatversion=\"20020620\">\n"
467 " <wrong error>\n"
468 "</passages>";
469
470 XMLDocument doc;
471 doc.Parse( error );
Lee Thomason2fa81722012-11-09 12:37:46 -0800472 XMLTest( "Bad XML", doc.ErrorID(), XML_ERROR_PARSING_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800473 }
474
475 {
476 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
477
478 XMLDocument doc;
479 doc.Parse( str );
480
481 XMLElement* ele = doc.FirstChildElement();
482
483 int iVal, result;
484 double dVal;
485
486 result = ele->QueryDoubleAttribute( "attr0", &dVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700487 XMLTest( "Query attribute: int as double", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800488 XMLTest( "Query attribute: int as double", (int)dVal, 1 );
489 result = ele->QueryDoubleAttribute( "attr1", &dVal );
490 XMLTest( "Query attribute: double as double", (int)dVal, 2 );
491 result = ele->QueryIntAttribute( "attr1", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700492 XMLTest( "Query attribute: double as int", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800493 XMLTest( "Query attribute: double as int", iVal, 2 );
494 result = ele->QueryIntAttribute( "attr2", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700495 XMLTest( "Query attribute: not a number", result, (int)XML_WRONG_ATTRIBUTE_TYPE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800496 result = ele->QueryIntAttribute( "bar", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700497 XMLTest( "Query attribute: does not exist", result, (int)XML_NO_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800498 }
499
500 {
501 const char* str = "<doc/>";
502
503 XMLDocument doc;
504 doc.Parse( str );
505
506 XMLElement* ele = doc.FirstChildElement();
507
508 int iVal;
509 double dVal;
510
511 ele->SetAttribute( "str", "strValue" );
512 ele->SetAttribute( "int", 1 );
513 ele->SetAttribute( "double", -1.0 );
514
515 const char* cStr = ele->Attribute( "str" );
516 ele->QueryIntAttribute( "int", &iVal );
517 ele->QueryDoubleAttribute( "double", &dVal );
518
Lee Thomason8ba7f7d2012-03-24 13:04:04 -0700519 XMLTest( "Attribute match test", ele->Attribute( "str", "strValue" ), "strValue" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800520 XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
521 XMLTest( "Attribute round trip. int.", 1, iVal );
522 XMLTest( "Attribute round trip. double.", -1, (int)dVal );
523 }
524
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800525 {
526 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300527 doc.LoadFile( "resources/utf8test.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800528
529 // Get the attribute "value" from the "Russian" element and check it.
530 XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700531 const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800532 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
533
534 XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
535
536 const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U,
537 0xd1U, 0x81U, 0xd1U, 0x81U,
538 0xd0U, 0xbaU, 0xd0U, 0xb8U,
539 0xd0U, 0xb9U, 0 };
540 const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
541
542 XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
543 XMLTest( "UTF-8: Browsing russian element name.",
544 russianText,
545 text->Value() );
546
547 // Now try for a round trip.
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400548 doc.SaveFile( "resources/out/utf8testout.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800549
550 // Check the round trip.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800551 int okay = 0;
552
Thomas Roßa6dd8c62012-07-26 20:42:18 +0200553 FILE* saved = fopen( "resources/out/utf8testout.xml", "r" );
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300554 FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800555
556 if ( saved && verify )
557 {
558 okay = 1;
PKEuSc28ba3a2012-07-16 03:08:47 -0700559 char verifyBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800560 while ( fgets( verifyBuf, 256, verify ) )
561 {
PKEuSc28ba3a2012-07-16 03:08:47 -0700562 char savedBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800563 fgets( savedBuf, 256, saved );
564 NullLineEndings( verifyBuf );
565 NullLineEndings( savedBuf );
566
567 if ( strcmp( verifyBuf, savedBuf ) )
568 {
569 printf( "verify:%s<\n", verifyBuf );
570 printf( "saved :%s<\n", savedBuf );
571 okay = 0;
572 break;
573 }
574 }
575 }
576 if ( saved )
577 fclose( saved );
578 if ( verify )
579 fclose( verify );
580 XMLTest( "UTF-8: Verified multi-language round trip.", 1, okay );
581 }
582
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800583 // --------GetText()-----------
584 {
585 const char* str = "<foo>This is text</foo>";
586 XMLDocument doc;
587 doc.Parse( str );
588 const XMLElement* element = doc.RootElement();
589
590 XMLTest( "GetText() normal use.", "This is text", element->GetText() );
591
592 str = "<foo><b>This is text</b></foo>";
593 doc.Parse( str );
594 element = doc.RootElement();
595
596 XMLTest( "GetText() contained element.", element->GetText() == 0, true );
597 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800598
Lee Thomasond6277762012-02-22 16:00:12 -0800599
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800600 // ---------- CDATA ---------------
601 {
602 const char* str = "<xmlElement>"
603 "<![CDATA["
604 "I am > the rules!\n"
605 "...since I make symbolic puns"
606 "]]>"
607 "</xmlElement>";
608 XMLDocument doc;
609 doc.Parse( str );
610 doc.Print();
Lee Thomasond6277762012-02-22 16:00:12 -0800611
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700612 XMLTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800613 "I am > the rules!\n...since I make symbolic puns",
Lee Thomasond6277762012-02-22 16:00:12 -0800614 false );
615 }
616
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800617 // ----------- CDATA -------------
618 {
619 const char* str = "<xmlElement>"
620 "<![CDATA["
621 "<b>I am > the rules!</b>\n"
622 "...since I make symbolic puns"
623 "]]>"
624 "</xmlElement>";
625 XMLDocument doc;
626 doc.Parse( str );
627 doc.Print();
628
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700629 XMLTest( "CDATA parse. [ tixml1:1480107 ]", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800630 "<b>I am > the rules!</b>\n...since I make symbolic puns",
631 false );
632 }
633
634 // InsertAfterChild causes crash.
635 {
636 // InsertBeforeChild and InsertAfterChild causes crash.
637 XMLDocument doc;
638 XMLElement* parent = doc.NewElement( "Parent" );
639 doc.InsertFirstChild( parent );
640
641 XMLElement* childText0 = doc.NewElement( "childText0" );
642 XMLElement* childText1 = doc.NewElement( "childText1" );
643
644 XMLNode* childNode0 = parent->InsertEndChild( childText0 );
645 XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
646
647 XMLTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent->LastChild() ), true );
648 }
Lee Thomasond6277762012-02-22 16:00:12 -0800649
650 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800651 // Entities not being written correctly.
652 // From Lynn Allen
Lee Thomasond6277762012-02-22 16:00:12 -0800653
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800654 const char* passages =
655 "<?xml version=\"1.0\" standalone=\"no\" ?>"
656 "<passages count=\"006\" formatversion=\"20020620\">"
657 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
658 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
659 "</passages>";
Lee Thomasond6277762012-02-22 16:00:12 -0800660
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800661 XMLDocument doc;
662 doc.Parse( passages );
663 XMLElement* psg = doc.RootElement()->FirstChildElement();
664 const char* context = psg->Attribute( "context" );
665 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 -0800666
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800667 XMLTest( "Entity transformation: read. ", expected, context, true );
Lee Thomasond6277762012-02-22 16:00:12 -0800668
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400669 FILE* textfile = fopen( "resources/out/textfile.txt", "w" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800670 if ( textfile )
671 {
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800672 XMLPrinter streamer( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800673 psg->Accept( &streamer );
674 fclose( textfile );
675 }
Thomas Roß0922b732012-09-23 16:31:22 +0200676
677 textfile = fopen( "resources/out/textfile.txt", "r" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800678 TIXMLASSERT( textfile );
679 if ( textfile )
680 {
681 char buf[ 1024 ];
682 fgets( buf, 1024, textfile );
683 XMLTest( "Entity transformation: write. ",
684 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
685 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
686 buf, false );
PKEuSc28ba3a2012-07-16 03:08:47 -0700687 fclose( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800688 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800689 }
690
691 {
Lee Thomason6f381b72012-03-02 12:59:39 -0800692 // Suppress entities.
693 const char* passages =
694 "<?xml version=\"1.0\" standalone=\"no\" ?>"
695 "<passages count=\"006\" formatversion=\"20020620\">"
696 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
697 "</passages>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700698
Lee Thomason6f381b72012-03-02 12:59:39 -0800699 XMLDocument doc( false );
700 doc.Parse( passages );
701
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700702 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ),
Lee Thomason6f381b72012-03-02 12:59:39 -0800703 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;." );
704 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value(),
705 "Crazy &ttk;" );
706 doc.Print();
707 }
708
709 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400710 const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800711
712 XMLDocument doc;
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400713 doc.Parse( test );
714 XMLTest( "dot in names", doc.Error(), false );
715 XMLTest( "dot in names", doc.FirstChildElement()->Name(), "a.elem" );
716 XMLTest( "dot in names", doc.FirstChildElement()->Attribute( "xmi.version" ), "2.0" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800717 }
718
719 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400720 const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800721
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400722 XMLDocument doc;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800723 doc.Parse( test );
724
725 XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
726 XMLTest( "Entity with one digit.",
727 text->Value(), "1.1 Start easy ignore fin thickness\n",
728 false );
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400729 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800730
731 {
732 // DOCTYPE not preserved (950171)
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700733 //
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800734 const char* doctype =
735 "<?xml version=\"1.0\" ?>"
736 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
737 "<!ELEMENT title (#PCDATA)>"
738 "<!ELEMENT books (title,authors)>"
739 "<element />";
740
741 XMLDocument doc;
742 doc.Parse( doctype );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400743 doc.SaveFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800744 doc.DeleteChild( doc.RootElement() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400745 doc.LoadFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800746 doc.Print();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700747
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800748 const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
749 XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
750
751 }
752
753 {
754 // Comments do not stream out correctly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700755 const char* doctype =
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800756 "<!-- Somewhat<evil> -->";
757 XMLDocument doc;
758 doc.Parse( doctype );
759
760 XMLComment* comment = doc.FirstChild()->ToComment();
761
762 XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
763 }
764 {
765 // Double attributes
766 const char* doctype = "<element attr='red' attr='blue' />";
767
768 XMLDocument doc;
769 doc.Parse( doctype );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700770
Lee Thomason2fa81722012-11-09 12:37:46 -0800771 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 -0800772 doc.PrintError();
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800773 }
774
775 {
776 // Embedded null in stream.
777 const char* doctype = "<element att\0r='red' attr='blue' />";
778
779 XMLDocument doc;
780 doc.Parse( doctype );
781 XMLTest( "Embedded null throws error.", true, doc.Error() );
782 }
783
784 {
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700785 // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800786 const char* str = " ";
787 XMLDocument doc;
788 doc.Parse( str );
Lee Thomason2fa81722012-11-09 12:37:46 -0800789 XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800790 }
791
792 {
793 // Low entities
794 XMLDocument doc;
795 doc.Parse( "<test>&#x0e;</test>" );
796 const char result[] = { 0x0e, 0 };
797 XMLTest( "Low entities.", doc.FirstChildElement()->GetText(), result );
798 doc.Print();
799 }
800
801 {
802 // Attribute values with trailing quotes not handled correctly
803 XMLDocument doc;
804 doc.Parse( "<foo attribute=bar\" />" );
805 XMLTest( "Throw error with bad end quotes.", doc.Error(), true );
806 }
807
808 {
809 // [ 1663758 ] Failure to report error on bad XML
810 XMLDocument xml;
811 xml.Parse("<x>");
812 XMLTest("Missing end tag at end of input", xml.Error(), true);
813 xml.Parse("<x> ");
814 XMLTest("Missing end tag with trailing whitespace", xml.Error(), true);
815 xml.Parse("<x></y>");
Lee Thomason2fa81722012-11-09 12:37:46 -0800816 XMLTest("Mismatched tags", xml.ErrorID(), XML_ERROR_MISMATCHED_ELEMENT);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700817 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800818
819
820 {
821 // [ 1475201 ] TinyXML parses entities in comments
822 XMLDocument xml;
823 xml.Parse("<!-- declarations for <head> & <body> -->"
824 "<!-- far &amp; away -->" );
825
826 XMLNode* e0 = xml.FirstChild();
827 XMLNode* e1 = e0->NextSibling();
828 XMLComment* c0 = e0->ToComment();
829 XMLComment* c1 = e1->ToComment();
830
831 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
832 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
833 }
834
835 {
836 XMLDocument xml;
837 xml.Parse( "<Parent>"
838 "<child1 att=''/>"
839 "<!-- With this comment, child2 will not be parsed! -->"
840 "<child2 att=''/>"
841 "</Parent>" );
842 xml.Print();
843
844 int count = 0;
845
846 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
847 ele;
848 ele = ele->NextSibling() )
849 {
850 ++count;
851 }
852
853 XMLTest( "Comments iterate correctly.", 3, count );
854 }
855
856 {
857 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
858 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
859 buf[60] = 239;
860 buf[61] = 0;
861
862 XMLDocument doc;
863 doc.Parse( (const char*)buf);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700864 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800865
866
867 {
868 // bug 1827248 Error while parsing a little bit malformed file
869 // Actually not malformed - should work.
870 XMLDocument xml;
871 xml.Parse( "<attributelist> </attributelist >" );
872 XMLTest( "Handle end tag whitespace", false, xml.Error() );
873 }
874
875 {
876 // This one must not result in an infinite loop
877 XMLDocument xml;
878 xml.Parse( "<infinite>loop" );
879 XMLTest( "Infinite loop test.", true, true );
880 }
881#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800882 {
883 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
884 XMLDocument doc;
885 doc.Parse( pub );
886
887 XMLDocument clone;
888 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
889 XMLNode* copy = node->ShallowClone( &clone );
890 clone.InsertEndChild( copy );
891 }
892
893 clone.Print();
894
895 int count=0;
896 const XMLNode* a=clone.FirstChild();
897 const XMLNode* b=doc.FirstChild();
898 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
899 ++count;
900 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
901 }
902 XMLTest( "Clone and Equal", 4, count );
903 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800904
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700905 {
906 // This shouldn't crash.
907 XMLDocument doc;
908 if(XML_NO_ERROR != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
909 {
910 doc.PrintError();
911 }
912 XMLTest( "Error in snprinf handling.", true, doc.Error() );
913 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700914
Lee Thomason5e3803c2012-04-16 08:57:05 -0700915 {
916 // Attribute ordering.
917 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
918 XMLDocument doc;
919 doc.Parse( xml );
920 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700921
Lee Thomason5e3803c2012-04-16 08:57:05 -0700922 const XMLAttribute* a = ele->FirstAttribute();
923 XMLTest( "Attribute order", "1", a->Value() );
924 a = a->Next();
925 XMLTest( "Attribute order", "2", a->Value() );
926 a = a->Next();
927 XMLTest( "Attribute order", "3", a->Value() );
928 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700929
Lee Thomason5e3803c2012-04-16 08:57:05 -0700930 ele->DeleteAttribute( "attrib2" );
931 a = ele->FirstAttribute();
932 XMLTest( "Attribute order", "1", a->Value() );
933 a = a->Next();
934 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700935
Lee Thomason5e3803c2012-04-16 08:57:05 -0700936 ele->DeleteAttribute( "attrib1" );
937 ele->DeleteAttribute( "attrib3" );
938 XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
939 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700940
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -0700941 {
942 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -0700943 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
944 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
945 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
946 XMLDocument doc0;
947 doc0.Parse( xml0 );
948 XMLDocument doc1;
949 doc1.Parse( xml1 );
950 XMLDocument doc2;
951 doc2.Parse( xml2 );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -0700952
Lee Thomason78a773d2012-07-02 10:10:19 -0700953 XMLElement* ele = 0;
954 ele = doc0.FirstChildElement();
955 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
956 ele = doc1.FirstChildElement();
957 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
958 ele = doc2.FirstChildElement();
959 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -0700960 }
961
962 {
963 // Make sure we don't go into an infinite loop.
964 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
965 XMLDocument doc;
966 doc.Parse( xml );
967 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
968 XMLElement* ele1 = ele0->NextSiblingElement();
969 bool equal = ele0->ShallowEqual( ele1 );
970
971 XMLTest( "Infinite loop in shallow equal.", true, equal );
972 }
973
Lee Thomason5708f812012-03-28 17:46:41 -0700974 // -------- Handles ------------
975 {
976 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
977 XMLDocument doc;
978 doc.Parse( xml );
Lee Thomason5708f812012-03-28 17:46:41 -0700979
980 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
981 XMLTest( "Handle, success, mutable", ele->Value(), "sub" );
982
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -0700983 XMLHandle docH( doc );
984 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -0700985 XMLTest( "Handle, dne, mutable", false, ele != 0 );
Lee Thomason5708f812012-03-28 17:46:41 -0700986 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700987
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -0700988 {
989 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
990 XMLDocument doc;
991 doc.Parse( xml );
992 XMLConstHandle docH( doc );
993
994 const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
995 XMLTest( "Handle, success, const", ele->Value(), "sub" );
996
997 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -0700998 XMLTest( "Handle, dne, const", false, ele != 0 );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -0700999 }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001000 {
1001 // Default Declaration & BOM
1002 XMLDocument doc;
1003 doc.InsertEndChild( doc.NewDeclaration() );
1004 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001005
Lee Thomasonf68c4382012-04-28 14:37:11 -07001006 XMLPrinter printer;
1007 doc.Print( &printer );
1008
1009 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1010 XMLTest( "BOM and default declaration", printer.CStr(), result, false );
Lee Thomason (grinliz)48ea0bc2012-05-26 14:41:14 -07001011 XMLTest( "CStrSize", printer.CStrSize(), 42, false );
Lee Thomasonf68c4382012-04-28 14:37:11 -07001012 }
Lee Thomason21be8822012-07-15 17:27:22 -07001013 {
1014 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1015 XMLDocument doc;
1016 doc.Parse( xml );
1017 XMLTest( "Ill formed XML", true, doc.Error() );
1018 }
1019
1020 // QueryXYZText
1021 {
1022 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1023 XMLDocument doc;
1024 doc.Parse( xml );
1025
1026 const XMLElement* pointElement = doc.RootElement();
1027
1028 int intValue = 0;
1029 unsigned unsignedValue = 0;
1030 float floatValue = 0;
1031 double doubleValue = 0;
1032 bool boolValue = false;
1033
1034 pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1035 pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1036 pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1037 pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1038 pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1039
1040
1041 XMLTest( "QueryIntText", intValue, 1, false );
1042 XMLTest( "QueryUnsignedText", unsignedValue, (unsigned)1, false );
1043 XMLTest( "QueryFloatText", floatValue, 1.2f, false );
1044 XMLTest( "QueryDoubleText", doubleValue, 1.2, false );
1045 XMLTest( "QueryBoolText", boolValue, true, false );
1046 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001047
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001048 {
1049 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1050 XMLDocument doc;
1051 doc.Parse( xml );
1052 XMLTest( "Non-alpha element lead letter parses.", doc.Error(), false );
1053 }
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001054
1055 {
1056 const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1057 XMLDocument doc;
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001058 doc.Parse( xml );
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001059 XMLTest("Non-alpha attribute lead character parses.", doc.Error(), false);
1060 }
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001061
1062 {
1063 const char* xml = "<3lement></3lement>";
1064 XMLDocument doc;
1065 doc.Parse( xml );
1066 XMLTest("Element names with lead digit fail to parse.", doc.Error(), true);
1067 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -07001068
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001069 {
1070 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1071 XMLDocument doc;
1072 doc.Parse( xml, 10 );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001073 XMLTest( "Set length of incoming data", doc.Error(), false );
1074 }
1075
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001076 {
1077 XMLDocument doc;
1078 doc.LoadFile( "resources/dream.xml" );
1079 doc.Clear();
1080 XMLTest( "Document Clear()'s", doc.NoChildren(), true );
1081 }
1082
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001083 // ----------- Whitespace ------------
1084 {
1085 const char* xml = "<element>"
1086 "<a> This \nis &apos; text &apos; </a>"
1087 "<b> This is &apos; text &apos; \n</b>"
1088 "<c>This is &apos; \n\n text &apos;</c>"
1089 "</element>";
1090 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1091 doc.Parse( xml );
1092
1093 const XMLElement* element = doc.FirstChildElement();
1094 for( const XMLElement* parent = element->FirstChildElement();
1095 parent;
1096 parent = parent->NextSiblingElement() )
1097 {
1098 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1099 }
1100 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001101
Lee Thomasonae9ab072012-10-24 10:17:53 -07001102#if 0
1103 {
1104 // Passes if assert doesn't fire.
1105 XMLDocument xmlDoc;
1106
1107 xmlDoc.NewDeclaration();
1108 xmlDoc.NewComment("Configuration file");
1109
1110 XMLElement *root = xmlDoc.NewElement("settings");
1111 root->SetAttribute("version", 2);
1112 }
1113#endif
1114
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001115 {
1116 const char* xml = "<element> </element>";
1117 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1118 doc.Parse( xml );
1119 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1120 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001121
Lee Thomason (grinliz)fc6320e2012-09-23 20:25:50 -07001122#if 0 // the question being explored is what kind of print to use:
1123 // https://github.com/leethomason/tinyxml2/issues/63
1124 {
1125 const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9'/>";
1126 XMLDocument doc;
1127 doc.Parse( xml );
1128 doc.FirstChildElement()->SetAttribute( "attrA", 123456789.123456789 );
1129 doc.FirstChildElement()->SetAttribute( "attrB", 1.001e9 );
1130 doc.Print();
1131 }
1132#endif
1133
Lee Thomason5b0a6772012-11-19 13:54:42 -08001134 {
1135 // An assert should not fire.
1136 const char* xml = "<element/>";
1137 XMLDocument doc;
1138 doc.Parse( xml );
1139 XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope.
1140 XMLTest( "Tracking unused elements", true, ele != 0, false );
1141 }
1142
Lee Thomasona6412ac2012-12-13 15:39:11 -08001143
1144 {
1145 const char* xml = "<parent><child>abc</child></parent>";
1146 XMLDocument doc;
1147 doc.Parse( xml );
1148 XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
1149
1150 XMLPrinter printer;
1151 ele->Accept( &printer );
1152 XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1153 }
1154
1155
Lee Thomason6f381b72012-03-02 12:59:39 -08001156 // ----------- Performance tracking --------------
1157 {
1158#if defined( _MSC_VER )
1159 __int64 start, end, freq;
1160 QueryPerformanceFrequency( (LARGE_INTEGER*) &freq );
1161#endif
1162
Bruno Diasa2d4e6e2012-05-07 04:58:11 -03001163 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason6f381b72012-03-02 12:59:39 -08001164 fseek( fp, 0, SEEK_END );
1165 long size = ftell( fp );
1166 fseek( fp, 0, SEEK_SET );
1167
1168 char* mem = new char[size+1];
1169 fread( mem, size, 1, fp );
1170 fclose( fp );
1171 mem[size] = 0;
1172
1173#if defined( _MSC_VER )
1174 QueryPerformanceCounter( (LARGE_INTEGER*) &start );
1175#else
1176 clock_t cstart = clock();
1177#endif
1178 static const int COUNT = 10;
1179 for( int i=0; i<COUNT; ++i ) {
1180 XMLDocument doc;
1181 doc.Parse( mem );
1182 }
1183#if defined( _MSC_VER )
1184 QueryPerformanceCounter( (LARGE_INTEGER*) &end );
1185#else
1186 clock_t cend = clock();
1187#endif
1188
1189 delete [] mem;
1190
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001191 static const char* note =
Lee Thomason6f381b72012-03-02 12:59:39 -08001192#ifdef DEBUG
1193 "DEBUG";
1194#else
1195 "Release";
1196#endif
1197
1198#if defined( _MSC_VER )
1199 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, 1000.0 * (double)(end-start) / ( (double)freq * (double)COUNT) );
1200#else
1201 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart)/(double)COUNT );
1202#endif
1203 }
1204
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -08001205 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001206 _CrtMemCheckpoint( &endMemState );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001207 //_CrtMemDumpStatistics( &endMemState );
1208
1209 _CrtMemState diffMemState;
1210 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
1211 _CrtMemDumpStatistics( &diffMemState );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001212 //printf( "new total=%d\n", gNewTotal );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001213 #endif
1214
1215 printf ("\nPass %d, Fail %d\n", gPass, gFail);
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001216 return 0;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08001217}