blob: 6944ca2c7f3b7a62cf83dced078c085cf2f95b5b [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 -070082// Comments in the header. (Don't know how to get Doxygen to read comments in this file.)
83int example_1()
84{
85 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -030086 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070087
88 return doc.ErrorID();
89}
90
91
92// Comments in the header. (Don't know how to get Doxygen to read comments in this file.)
93int example_2()
94{
95 static const char* xml = "<element/>";
96 XMLDocument doc;
97 doc.Parse( xml );
98
99 return doc.ErrorID();
100}
101
102
103int example_3()
104{
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700105 static const char* xml =
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700106 "<?xml version=\"1.0\"?>"
107 "<!DOCTYPE PLAY SYSTEM \"play.dtd\">"
108 "<PLAY>"
109 "<TITLE>A Midsummer Night's Dream</TITLE>"
110 "</PLAY>";
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700111
112 XMLDocument doc;
113 doc.Parse( xml );
114
115 XMLElement* titleElement = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" );
116 const char* title = titleElement->GetText();
117 printf( "Name of play (1): %s\n", title );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700118
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700119 XMLText* textNode = titleElement->FirstChild()->ToText();
120 title = textNode->Value();
121 printf( "Name of play (2): %s\n", title );
122
123 return doc.ErrorID();
124}
125
126
Lee Thomason21be8822012-07-15 17:27:22 -0700127bool example_4()
128{
129 static const char* xml =
130 "<information>"
131 " <attributeApproach v='2' />"
132 " <textApproach>"
133 " <v>2</v>"
134 " </textApproach>"
135 "</information>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700136
Lee Thomason21be8822012-07-15 17:27:22 -0700137 XMLDocument doc;
138 doc.Parse( xml );
139
140 int v0 = 0;
141 int v1 = 0;
142
143 XMLElement* attributeApproachElement = doc.FirstChildElement()->FirstChildElement( "attributeApproach" );
144 attributeApproachElement->QueryIntAttribute( "v", &v0 );
145
146 XMLElement* textApproachElement = doc.FirstChildElement()->FirstChildElement( "textApproach" );
147 textApproachElement->FirstChildElement( "v" )->QueryIntText( &v1 );
148
149 printf( "Both values are the same: %d and %d\n", v0, v1 );
150
151 return !doc.Error() && ( v0 == v1 );
152}
153
154
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700155int main( int /*argc*/, const char ** /*argv*/ )
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800156{
Lee Thomason (grinliz)0a4df402012-02-27 20:50:52 -0800157 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason1ff38e02012-02-14 18:18:16 -0800158 _CrtMemCheckpoint( &startMemState );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700159 #endif
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800160
Martinsh Shaiters39ddc262013-01-15 21:53:08 +0200161 #if defined(_MSC_VER) || defined(MINGW32) || defined(__MINGW32__)
Lee Thomasone9699e62012-07-25 12:24:23 -0700162 _mkdir( "resources/out/" );
163 #else
164 mkdir( "resources/out/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
165 #endif
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400166
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300167 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason7f7b1622012-03-24 12:49:03 -0700168 if ( !fp ) {
169 printf( "Error opening test file 'dream.xml'.\n"
170 "Is your working directory the same as where \n"
171 "the xmltest.cpp and dream.xml file are?\n\n"
172 #if defined( _MSC_VER )
173 "In windows Visual Studio you may need to set\n"
174 "Properties->Debugging->Working Directory to '..'\n"
175 #endif
176 );
177 exit( 1 );
178 }
179 fclose( fp );
180
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700181 XMLTest( "Example-1", 0, example_1() );
182 XMLTest( "Example-2", 0, example_2() );
183 XMLTest( "Example-3", 0, example_3() );
Lee Thomason21be8822012-07-15 17:27:22 -0700184 XMLTest( "Example-4", true, example_4() );
Lee Thomason87e475a2012-03-20 11:55:29 -0700185
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700186 /* ------ Example 2: Lookup information. ---- */
Lee Thomason87e475a2012-03-20 11:55:29 -0700187
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800188 {
Lee Thomason43f59302012-02-06 18:18:11 -0800189 static const char* test[] = { "<element />",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400190 "<element></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800191 "<element><subelement/></element>",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400192 "<element><subelement></subelement></element>",
193 "<element><subelement><subsub/></subelement></element>",
194 "<!--comment beside elements--><element><subelement></subelement></element>",
195 "<!--comment beside elements, this time with spaces--> \n <element> <subelement> \n </subelement> </element>",
196 "<element attrib1='foo' attrib2=\"bar\" ></element>",
197 "<element attrib1='foo' attrib2=\"bar\" ><subelement attrib3='yeehaa' /></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800198 "<element>Text inside element.</element>",
199 "<element><b></b></element>",
200 "<element>Text inside and <b>bolded</b> in the element.</element>",
201 "<outer><element>Text inside and <b>bolded</b> in the element.</element></outer>",
Lee Thomason8ee79892012-01-25 17:44:30 -0800202 "<element>This &amp; That.</element>",
Lee Thomason18d68bd2012-01-26 18:17:26 -0800203 "<element attrib='This&lt;That' />",
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800204 0
205 };
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800206 for( int i=0; test[i]; ++i ) {
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800207 XMLDocument doc;
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800208 doc.Parse( test[i] );
Lee Thomason5cae8972012-01-24 18:03:07 -0800209 doc.Print();
Lee Thomasonec975ce2012-01-23 11:42:06 -0800210 printf( "----------------------------------------------\n" );
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800211 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800212 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800213#if 1
Lee Thomasond6277762012-02-22 16:00:12 -0800214 {
215 static const char* test = "<!--hello world\n"
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400216 " line 2\r"
217 " line 3\r\n"
218 " line 4\n\r"
219 " line 5\r-->";
Lee Thomasond6277762012-02-22 16:00:12 -0800220
221 XMLDocument doc;
222 doc.Parse( test );
223 doc.Print();
224 }
225
Lee Thomason2c85a712012-01-31 08:24:24 -0800226 {
227 static const char* test = "<element>Text before.</element>";
228 XMLDocument doc;
229 doc.Parse( test );
230 XMLElement* root = doc.FirstChildElement();
231 XMLElement* newElement = doc.NewElement( "Subelement" );
232 root->InsertEndChild( newElement );
233 doc.Print();
234 }
Lee Thomasond1983222012-02-06 08:41:24 -0800235 {
236 XMLDocument* doc = new XMLDocument();
237 static const char* test = "<element><sub/></element>";
238 doc->Parse( test );
239 delete doc;
240 }
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800241 {
Lee Thomason1ff38e02012-02-14 18:18:16 -0800242 // Test: Programmatic DOM
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800243 // Build:
244 // <element>
245 // <!--comment-->
246 // <sub attrib="1" />
247 // <sub attrib="2" />
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800248 // <sub attrib="3" >& Text!</sub>
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800249 // <element>
250
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800251 XMLDocument* doc = new XMLDocument();
Lee Thomason1ff38e02012-02-14 18:18:16 -0800252 XMLNode* element = doc->InsertEndChild( doc->NewElement( "element" ) );
253
254 XMLElement* sub[3] = { doc->NewElement( "sub" ), doc->NewElement( "sub" ), doc->NewElement( "sub" ) };
255 for( int i=0; i<3; ++i ) {
256 sub[i]->SetAttribute( "attrib", i );
257 }
258 element->InsertEndChild( sub[2] );
259 XMLNode* comment = element->InsertFirstChild( doc->NewComment( "comment" ) );
260 element->InsertAfterChild( comment, sub[0] );
261 element->InsertAfterChild( sub[0], sub[1] );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800262 sub[2]->InsertFirstChild( doc->NewText( "& Text!" ));
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800263 doc->Print();
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800264 XMLTest( "Programmatic DOM", "comment", doc->FirstChildElement( "element" )->FirstChild()->Value() );
265 XMLTest( "Programmatic DOM", "0", doc->FirstChildElement( "element" )->FirstChildElement()->Attribute( "attrib" ) );
266 XMLTest( "Programmatic DOM", 2, doc->FirstChildElement()->LastChildElement( "sub" )->IntAttribute( "attrib" ) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700267 XMLTest( "Programmatic DOM", "& Text!",
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800268 doc->FirstChildElement()->LastChildElement( "sub" )->FirstChild()->ToText()->Value() );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800269
270 // And now deletion:
271 element->DeleteChild( sub[2] );
272 doc->DeleteNode( comment );
273
274 element->FirstChildElement()->SetAttribute( "attrib", true );
275 element->LastChildElement()->DeleteAttribute( "attrib" );
276
277 XMLTest( "Programmatic DOM", true, doc->FirstChildElement()->FirstChildElement()->BoolAttribute( "attrib" ) );
278 int value = 10;
279 int result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value );
Lee Thomason21be8822012-07-15 17:27:22 -0700280 XMLTest( "Programmatic DOM", result, (int)XML_NO_ATTRIBUTE );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800281 XMLTest( "Programmatic DOM", value, 10 );
282
283 doc->Print();
284
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700285 {
286 XMLPrinter streamer;
287 doc->Print( &streamer );
288 printf( "%s", streamer.CStr() );
289 }
290 {
291 XMLPrinter streamer( 0, true );
292 doc->Print( &streamer );
293 XMLTest( "Compact mode", "<element><sub attrib=\"1\"/><sub/></element>", streamer.CStr(), false );
294 }
Lee Thomason (grinliz)6b8b0122012-09-08 21:21:00 -0700295 doc->SaveFile( "./resources/out/pretty.xml" );
296 doc->SaveFile( "./resources/out/compact.xml", true );
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800297 delete doc;
298 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800299 {
300 // Test: Dream
301 // XML1 : 1,187,569 bytes in 31,209 allocations
302 // XML2 : 469,073 bytes in 323 allocations
303 //int newStart = gNew;
304 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300305 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800306
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400307 doc.SaveFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800308 doc.PrintError();
309
310 XMLTest( "Dream", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400311 doc.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800312 XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false );
313 XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
314 doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
315 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400316 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800317 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400318 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800319
320 XMLDocument doc2;
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400321 doc2.LoadFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800322 XMLTest( "Dream-out", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400323 doc2.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800324 XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false );
325 XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
326 doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
327 XMLTest( "Dream-out", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400328 doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800329
330 //gNewTotal = gNew - newStart;
331 }
Lee Thomason6f381b72012-03-02 12:59:39 -0800332
333
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800334 {
335 const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
336 "<passages count=\"006\" formatversion=\"20020620\">\n"
337 " <wrong error>\n"
338 "</passages>";
339
340 XMLDocument doc;
341 doc.Parse( error );
Lee Thomason2fa81722012-11-09 12:37:46 -0800342 XMLTest( "Bad XML", doc.ErrorID(), XML_ERROR_PARSING_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800343 }
344
345 {
346 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
347
348 XMLDocument doc;
349 doc.Parse( str );
350
351 XMLElement* ele = doc.FirstChildElement();
352
353 int iVal, result;
354 double dVal;
355
356 result = ele->QueryDoubleAttribute( "attr0", &dVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700357 XMLTest( "Query attribute: int as double", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800358 XMLTest( "Query attribute: int as double", (int)dVal, 1 );
359 result = ele->QueryDoubleAttribute( "attr1", &dVal );
360 XMLTest( "Query attribute: double as double", (int)dVal, 2 );
361 result = ele->QueryIntAttribute( "attr1", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700362 XMLTest( "Query attribute: double as int", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800363 XMLTest( "Query attribute: double as int", iVal, 2 );
364 result = ele->QueryIntAttribute( "attr2", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700365 XMLTest( "Query attribute: not a number", result, (int)XML_WRONG_ATTRIBUTE_TYPE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800366 result = ele->QueryIntAttribute( "bar", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700367 XMLTest( "Query attribute: does not exist", result, (int)XML_NO_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800368 }
369
370 {
371 const char* str = "<doc/>";
372
373 XMLDocument doc;
374 doc.Parse( str );
375
376 XMLElement* ele = doc.FirstChildElement();
377
378 int iVal;
379 double dVal;
380
381 ele->SetAttribute( "str", "strValue" );
382 ele->SetAttribute( "int", 1 );
383 ele->SetAttribute( "double", -1.0 );
384
385 const char* cStr = ele->Attribute( "str" );
386 ele->QueryIntAttribute( "int", &iVal );
387 ele->QueryDoubleAttribute( "double", &dVal );
388
Lee Thomason8ba7f7d2012-03-24 13:04:04 -0700389 XMLTest( "Attribute match test", ele->Attribute( "str", "strValue" ), "strValue" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800390 XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
391 XMLTest( "Attribute round trip. int.", 1, iVal );
392 XMLTest( "Attribute round trip. double.", -1, (int)dVal );
393 }
394
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800395 {
396 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300397 doc.LoadFile( "resources/utf8test.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800398
399 // Get the attribute "value" from the "Russian" element and check it.
400 XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700401 const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800402 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
403
404 XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
405
406 const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U,
407 0xd1U, 0x81U, 0xd1U, 0x81U,
408 0xd0U, 0xbaU, 0xd0U, 0xb8U,
409 0xd0U, 0xb9U, 0 };
410 const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
411
412 XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
413 XMLTest( "UTF-8: Browsing russian element name.",
414 russianText,
415 text->Value() );
416
417 // Now try for a round trip.
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400418 doc.SaveFile( "resources/out/utf8testout.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800419
420 // Check the round trip.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800421 int okay = 0;
422
Thomas Roßa6dd8c62012-07-26 20:42:18 +0200423 FILE* saved = fopen( "resources/out/utf8testout.xml", "r" );
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300424 FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800425
426 if ( saved && verify )
427 {
428 okay = 1;
PKEuSc28ba3a2012-07-16 03:08:47 -0700429 char verifyBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800430 while ( fgets( verifyBuf, 256, verify ) )
431 {
PKEuSc28ba3a2012-07-16 03:08:47 -0700432 char savedBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800433 fgets( savedBuf, 256, saved );
434 NullLineEndings( verifyBuf );
435 NullLineEndings( savedBuf );
436
437 if ( strcmp( verifyBuf, savedBuf ) )
438 {
439 printf( "verify:%s<\n", verifyBuf );
440 printf( "saved :%s<\n", savedBuf );
441 okay = 0;
442 break;
443 }
444 }
445 }
446 if ( saved )
447 fclose( saved );
448 if ( verify )
449 fclose( verify );
450 XMLTest( "UTF-8: Verified multi-language round trip.", 1, okay );
451 }
452
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800453 // --------GetText()-----------
454 {
455 const char* str = "<foo>This is text</foo>";
456 XMLDocument doc;
457 doc.Parse( str );
458 const XMLElement* element = doc.RootElement();
459
460 XMLTest( "GetText() normal use.", "This is text", element->GetText() );
461
462 str = "<foo><b>This is text</b></foo>";
463 doc.Parse( str );
464 element = doc.RootElement();
465
466 XMLTest( "GetText() contained element.", element->GetText() == 0, true );
467 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800468
Lee Thomasond6277762012-02-22 16:00:12 -0800469
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800470 // ---------- CDATA ---------------
471 {
472 const char* str = "<xmlElement>"
473 "<![CDATA["
474 "I am > the rules!\n"
475 "...since I make symbolic puns"
476 "]]>"
477 "</xmlElement>";
478 XMLDocument doc;
479 doc.Parse( str );
480 doc.Print();
Lee Thomasond6277762012-02-22 16:00:12 -0800481
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700482 XMLTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800483 "I am > the rules!\n...since I make symbolic puns",
Lee Thomasond6277762012-02-22 16:00:12 -0800484 false );
485 }
486
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800487 // ----------- CDATA -------------
488 {
489 const char* str = "<xmlElement>"
490 "<![CDATA["
491 "<b>I am > the rules!</b>\n"
492 "...since I make symbolic puns"
493 "]]>"
494 "</xmlElement>";
495 XMLDocument doc;
496 doc.Parse( str );
497 doc.Print();
498
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700499 XMLTest( "CDATA parse. [ tixml1:1480107 ]", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800500 "<b>I am > the rules!</b>\n...since I make symbolic puns",
501 false );
502 }
503
504 // InsertAfterChild causes crash.
505 {
506 // InsertBeforeChild and InsertAfterChild causes crash.
507 XMLDocument doc;
508 XMLElement* parent = doc.NewElement( "Parent" );
509 doc.InsertFirstChild( parent );
510
511 XMLElement* childText0 = doc.NewElement( "childText0" );
512 XMLElement* childText1 = doc.NewElement( "childText1" );
513
514 XMLNode* childNode0 = parent->InsertEndChild( childText0 );
515 XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
516
517 XMLTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent->LastChild() ), true );
518 }
Lee Thomasond6277762012-02-22 16:00:12 -0800519
520 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800521 // Entities not being written correctly.
522 // From Lynn Allen
Lee Thomasond6277762012-02-22 16:00:12 -0800523
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800524 const char* passages =
525 "<?xml version=\"1.0\" standalone=\"no\" ?>"
526 "<passages count=\"006\" formatversion=\"20020620\">"
527 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
528 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
529 "</passages>";
Lee Thomasond6277762012-02-22 16:00:12 -0800530
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800531 XMLDocument doc;
532 doc.Parse( passages );
533 XMLElement* psg = doc.RootElement()->FirstChildElement();
534 const char* context = psg->Attribute( "context" );
535 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 -0800536
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800537 XMLTest( "Entity transformation: read. ", expected, context, true );
Lee Thomasond6277762012-02-22 16:00:12 -0800538
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400539 FILE* textfile = fopen( "resources/out/textfile.txt", "w" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800540 if ( textfile )
541 {
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800542 XMLPrinter streamer( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800543 psg->Accept( &streamer );
544 fclose( textfile );
545 }
Thomas Roß0922b732012-09-23 16:31:22 +0200546
547 textfile = fopen( "resources/out/textfile.txt", "r" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800548 TIXMLASSERT( textfile );
549 if ( textfile )
550 {
551 char buf[ 1024 ];
552 fgets( buf, 1024, textfile );
553 XMLTest( "Entity transformation: write. ",
554 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
555 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
556 buf, false );
PKEuSc28ba3a2012-07-16 03:08:47 -0700557 fclose( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800558 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800559 }
560
561 {
Lee Thomason6f381b72012-03-02 12:59:39 -0800562 // Suppress entities.
563 const char* passages =
564 "<?xml version=\"1.0\" standalone=\"no\" ?>"
565 "<passages count=\"006\" formatversion=\"20020620\">"
566 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
567 "</passages>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700568
Lee Thomason6f381b72012-03-02 12:59:39 -0800569 XMLDocument doc( false );
570 doc.Parse( passages );
571
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700572 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ),
Lee Thomason6f381b72012-03-02 12:59:39 -0800573 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;." );
574 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value(),
575 "Crazy &ttk;" );
576 doc.Print();
577 }
578
579 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400580 const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800581
582 XMLDocument doc;
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400583 doc.Parse( test );
584 XMLTest( "dot in names", doc.Error(), false );
585 XMLTest( "dot in names", doc.FirstChildElement()->Name(), "a.elem" );
586 XMLTest( "dot in names", doc.FirstChildElement()->Attribute( "xmi.version" ), "2.0" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800587 }
588
589 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400590 const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800591
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400592 XMLDocument doc;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800593 doc.Parse( test );
594
595 XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
596 XMLTest( "Entity with one digit.",
597 text->Value(), "1.1 Start easy ignore fin thickness\n",
598 false );
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400599 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800600
601 {
602 // DOCTYPE not preserved (950171)
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700603 //
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800604 const char* doctype =
605 "<?xml version=\"1.0\" ?>"
606 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
607 "<!ELEMENT title (#PCDATA)>"
608 "<!ELEMENT books (title,authors)>"
609 "<element />";
610
611 XMLDocument doc;
612 doc.Parse( doctype );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400613 doc.SaveFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800614 doc.DeleteChild( doc.RootElement() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400615 doc.LoadFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800616 doc.Print();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700617
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800618 const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
619 XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
620
621 }
622
623 {
624 // Comments do not stream out correctly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700625 const char* doctype =
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800626 "<!-- Somewhat<evil> -->";
627 XMLDocument doc;
628 doc.Parse( doctype );
629
630 XMLComment* comment = doc.FirstChild()->ToComment();
631
632 XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
633 }
634 {
635 // Double attributes
636 const char* doctype = "<element attr='red' attr='blue' />";
637
638 XMLDocument doc;
639 doc.Parse( doctype );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700640
Lee Thomason2fa81722012-11-09 12:37:46 -0800641 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 -0800642 doc.PrintError();
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800643 }
644
645 {
646 // Embedded null in stream.
647 const char* doctype = "<element att\0r='red' attr='blue' />";
648
649 XMLDocument doc;
650 doc.Parse( doctype );
651 XMLTest( "Embedded null throws error.", true, doc.Error() );
652 }
653
654 {
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700655 // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800656 const char* str = " ";
657 XMLDocument doc;
658 doc.Parse( str );
Lee Thomason2fa81722012-11-09 12:37:46 -0800659 XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800660 }
661
662 {
663 // Low entities
664 XMLDocument doc;
665 doc.Parse( "<test>&#x0e;</test>" );
666 const char result[] = { 0x0e, 0 };
667 XMLTest( "Low entities.", doc.FirstChildElement()->GetText(), result );
668 doc.Print();
669 }
670
671 {
672 // Attribute values with trailing quotes not handled correctly
673 XMLDocument doc;
674 doc.Parse( "<foo attribute=bar\" />" );
675 XMLTest( "Throw error with bad end quotes.", doc.Error(), true );
676 }
677
678 {
679 // [ 1663758 ] Failure to report error on bad XML
680 XMLDocument xml;
681 xml.Parse("<x>");
682 XMLTest("Missing end tag at end of input", xml.Error(), true);
683 xml.Parse("<x> ");
684 XMLTest("Missing end tag with trailing whitespace", xml.Error(), true);
685 xml.Parse("<x></y>");
Lee Thomason2fa81722012-11-09 12:37:46 -0800686 XMLTest("Mismatched tags", xml.ErrorID(), XML_ERROR_MISMATCHED_ELEMENT);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700687 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800688
689
690 {
691 // [ 1475201 ] TinyXML parses entities in comments
692 XMLDocument xml;
693 xml.Parse("<!-- declarations for <head> & <body> -->"
694 "<!-- far &amp; away -->" );
695
696 XMLNode* e0 = xml.FirstChild();
697 XMLNode* e1 = e0->NextSibling();
698 XMLComment* c0 = e0->ToComment();
699 XMLComment* c1 = e1->ToComment();
700
701 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
702 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
703 }
704
705 {
706 XMLDocument xml;
707 xml.Parse( "<Parent>"
708 "<child1 att=''/>"
709 "<!-- With this comment, child2 will not be parsed! -->"
710 "<child2 att=''/>"
711 "</Parent>" );
712 xml.Print();
713
714 int count = 0;
715
716 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
717 ele;
718 ele = ele->NextSibling() )
719 {
720 ++count;
721 }
722
723 XMLTest( "Comments iterate correctly.", 3, count );
724 }
725
726 {
727 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
728 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
729 buf[60] = 239;
730 buf[61] = 0;
731
732 XMLDocument doc;
733 doc.Parse( (const char*)buf);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700734 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800735
736
737 {
738 // bug 1827248 Error while parsing a little bit malformed file
739 // Actually not malformed - should work.
740 XMLDocument xml;
741 xml.Parse( "<attributelist> </attributelist >" );
742 XMLTest( "Handle end tag whitespace", false, xml.Error() );
743 }
744
745 {
746 // This one must not result in an infinite loop
747 XMLDocument xml;
748 xml.Parse( "<infinite>loop" );
749 XMLTest( "Infinite loop test.", true, true );
750 }
751#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800752 {
753 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
754 XMLDocument doc;
755 doc.Parse( pub );
756
757 XMLDocument clone;
758 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
759 XMLNode* copy = node->ShallowClone( &clone );
760 clone.InsertEndChild( copy );
761 }
762
763 clone.Print();
764
765 int count=0;
766 const XMLNode* a=clone.FirstChild();
767 const XMLNode* b=doc.FirstChild();
768 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
769 ++count;
770 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
771 }
772 XMLTest( "Clone and Equal", 4, count );
773 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800774
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700775 {
776 // This shouldn't crash.
777 XMLDocument doc;
778 if(XML_NO_ERROR != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
779 {
780 doc.PrintError();
781 }
782 XMLTest( "Error in snprinf handling.", true, doc.Error() );
783 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700784
Lee Thomason5e3803c2012-04-16 08:57:05 -0700785 {
786 // Attribute ordering.
787 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
788 XMLDocument doc;
789 doc.Parse( xml );
790 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700791
Lee Thomason5e3803c2012-04-16 08:57:05 -0700792 const XMLAttribute* a = ele->FirstAttribute();
793 XMLTest( "Attribute order", "1", a->Value() );
794 a = a->Next();
795 XMLTest( "Attribute order", "2", a->Value() );
796 a = a->Next();
797 XMLTest( "Attribute order", "3", a->Value() );
798 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700799
Lee Thomason5e3803c2012-04-16 08:57:05 -0700800 ele->DeleteAttribute( "attrib2" );
801 a = ele->FirstAttribute();
802 XMLTest( "Attribute order", "1", a->Value() );
803 a = a->Next();
804 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700805
Lee Thomason5e3803c2012-04-16 08:57:05 -0700806 ele->DeleteAttribute( "attrib1" );
807 ele->DeleteAttribute( "attrib3" );
808 XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
809 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700810
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -0700811 {
812 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -0700813 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
814 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
815 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
816 XMLDocument doc0;
817 doc0.Parse( xml0 );
818 XMLDocument doc1;
819 doc1.Parse( xml1 );
820 XMLDocument doc2;
821 doc2.Parse( xml2 );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -0700822
Lee Thomason78a773d2012-07-02 10:10:19 -0700823 XMLElement* ele = 0;
824 ele = doc0.FirstChildElement();
825 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
826 ele = doc1.FirstChildElement();
827 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
828 ele = doc2.FirstChildElement();
829 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -0700830 }
831
832 {
833 // Make sure we don't go into an infinite loop.
834 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
835 XMLDocument doc;
836 doc.Parse( xml );
837 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
838 XMLElement* ele1 = ele0->NextSiblingElement();
839 bool equal = ele0->ShallowEqual( ele1 );
840
841 XMLTest( "Infinite loop in shallow equal.", true, equal );
842 }
843
Lee Thomason5708f812012-03-28 17:46:41 -0700844 // -------- Handles ------------
845 {
846 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
847 XMLDocument doc;
848 doc.Parse( xml );
Lee Thomason5708f812012-03-28 17:46:41 -0700849
850 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
851 XMLTest( "Handle, success, mutable", ele->Value(), "sub" );
852
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -0700853 XMLHandle docH( doc );
854 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -0700855 XMLTest( "Handle, dne, mutable", false, ele != 0 );
Lee Thomason5708f812012-03-28 17:46:41 -0700856 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700857
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -0700858 {
859 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
860 XMLDocument doc;
861 doc.Parse( xml );
862 XMLConstHandle docH( doc );
863
864 const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
865 XMLTest( "Handle, success, const", ele->Value(), "sub" );
866
867 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -0700868 XMLTest( "Handle, dne, const", false, ele != 0 );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -0700869 }
Lee Thomasonf68c4382012-04-28 14:37:11 -0700870 {
871 // Default Declaration & BOM
872 XMLDocument doc;
873 doc.InsertEndChild( doc.NewDeclaration() );
874 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700875
Lee Thomasonf68c4382012-04-28 14:37:11 -0700876 XMLPrinter printer;
877 doc.Print( &printer );
878
879 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
880 XMLTest( "BOM and default declaration", printer.CStr(), result, false );
Lee Thomason (grinliz)48ea0bc2012-05-26 14:41:14 -0700881 XMLTest( "CStrSize", printer.CStrSize(), 42, false );
Lee Thomasonf68c4382012-04-28 14:37:11 -0700882 }
Lee Thomason21be8822012-07-15 17:27:22 -0700883 {
884 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
885 XMLDocument doc;
886 doc.Parse( xml );
887 XMLTest( "Ill formed XML", true, doc.Error() );
888 }
889
890 // QueryXYZText
891 {
892 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
893 XMLDocument doc;
894 doc.Parse( xml );
895
896 const XMLElement* pointElement = doc.RootElement();
897
898 int intValue = 0;
899 unsigned unsignedValue = 0;
900 float floatValue = 0;
901 double doubleValue = 0;
902 bool boolValue = false;
903
904 pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
905 pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
906 pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
907 pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
908 pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
909
910
911 XMLTest( "QueryIntText", intValue, 1, false );
912 XMLTest( "QueryUnsignedText", unsignedValue, (unsigned)1, false );
913 XMLTest( "QueryFloatText", floatValue, 1.2f, false );
914 XMLTest( "QueryDoubleText", doubleValue, 1.2, false );
915 XMLTest( "QueryBoolText", boolValue, true, false );
916 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -0700917
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -0700918 {
919 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
920 XMLDocument doc;
921 doc.Parse( xml );
922 XMLTest( "Non-alpha element lead letter parses.", doc.Error(), false );
923 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -0700924
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -0700925 {
926 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
927 XMLDocument doc;
928 doc.Parse( xml, 10 );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -0700929 XMLTest( "Set length of incoming data", doc.Error(), false );
930 }
931
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -0700932 // ----------- Whitespace ------------
933 {
934 const char* xml = "<element>"
935 "<a> This \nis &apos; text &apos; </a>"
936 "<b> This is &apos; text &apos; \n</b>"
937 "<c>This is &apos; \n\n text &apos;</c>"
938 "</element>";
939 XMLDocument doc( true, COLLAPSE_WHITESPACE );
940 doc.Parse( xml );
941
942 const XMLElement* element = doc.FirstChildElement();
943 for( const XMLElement* parent = element->FirstChildElement();
944 parent;
945 parent = parent->NextSiblingElement() )
946 {
947 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
948 }
949 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -0700950
Lee Thomasonae9ab072012-10-24 10:17:53 -0700951#if 0
952 {
953 // Passes if assert doesn't fire.
954 XMLDocument xmlDoc;
955
956 xmlDoc.NewDeclaration();
957 xmlDoc.NewComment("Configuration file");
958
959 XMLElement *root = xmlDoc.NewElement("settings");
960 root->SetAttribute("version", 2);
961 }
962#endif
963
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -0700964 {
965 const char* xml = "<element> </element>";
966 XMLDocument doc( true, COLLAPSE_WHITESPACE );
967 doc.Parse( xml );
968 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
969 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700970
Lee Thomason (grinliz)fc6320e2012-09-23 20:25:50 -0700971#if 0 // the question being explored is what kind of print to use:
972 // https://github.com/leethomason/tinyxml2/issues/63
973 {
974 const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9'/>";
975 XMLDocument doc;
976 doc.Parse( xml );
977 doc.FirstChildElement()->SetAttribute( "attrA", 123456789.123456789 );
978 doc.FirstChildElement()->SetAttribute( "attrB", 1.001e9 );
979 doc.Print();
980 }
981#endif
982
Lee Thomason5b0a6772012-11-19 13:54:42 -0800983 {
984 // An assert should not fire.
985 const char* xml = "<element/>";
986 XMLDocument doc;
987 doc.Parse( xml );
988 XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope.
989 XMLTest( "Tracking unused elements", true, ele != 0, false );
990 }
991
Lee Thomasona6412ac2012-12-13 15:39:11 -0800992
993 {
994 const char* xml = "<parent><child>abc</child></parent>";
995 XMLDocument doc;
996 doc.Parse( xml );
997 XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
998
999 XMLPrinter printer;
1000 ele->Accept( &printer );
1001 XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1002 }
1003
1004
Lee Thomason6f381b72012-03-02 12:59:39 -08001005 // ----------- Performance tracking --------------
1006 {
1007#if defined( _MSC_VER )
1008 __int64 start, end, freq;
1009 QueryPerformanceFrequency( (LARGE_INTEGER*) &freq );
1010#endif
1011
Bruno Diasa2d4e6e2012-05-07 04:58:11 -03001012 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason6f381b72012-03-02 12:59:39 -08001013 fseek( fp, 0, SEEK_END );
1014 long size = ftell( fp );
1015 fseek( fp, 0, SEEK_SET );
1016
1017 char* mem = new char[size+1];
1018 fread( mem, size, 1, fp );
1019 fclose( fp );
1020 mem[size] = 0;
1021
1022#if defined( _MSC_VER )
1023 QueryPerformanceCounter( (LARGE_INTEGER*) &start );
1024#else
1025 clock_t cstart = clock();
1026#endif
1027 static const int COUNT = 10;
1028 for( int i=0; i<COUNT; ++i ) {
1029 XMLDocument doc;
1030 doc.Parse( mem );
1031 }
1032#if defined( _MSC_VER )
1033 QueryPerformanceCounter( (LARGE_INTEGER*) &end );
1034#else
1035 clock_t cend = clock();
1036#endif
1037
1038 delete [] mem;
1039
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001040 static const char* note =
Lee Thomason6f381b72012-03-02 12:59:39 -08001041#ifdef DEBUG
1042 "DEBUG";
1043#else
1044 "Release";
1045#endif
1046
1047#if defined( _MSC_VER )
1048 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, 1000.0 * (double)(end-start) / ( (double)freq * (double)COUNT) );
1049#else
1050 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart)/(double)COUNT );
1051#endif
1052 }
1053
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -08001054 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001055 _CrtMemCheckpoint( &endMemState );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001056 //_CrtMemDumpStatistics( &endMemState );
1057
1058 _CrtMemState diffMemState;
1059 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
1060 _CrtMemDumpStatistics( &diffMemState );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001061 //printf( "new total=%d\n", gNewTotal );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001062 #endif
1063
1064 printf ("\nPass %d, Fail %d\n", gPass, gFail);
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001065 return 0;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08001066}