blob: f6b2072b36726e7999d543683d35b563e22a6650 [file] [log] [blame]
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001#include "tinyxml2.h"
2
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -07003#include <cstdlib>
4#include <cstring>
5#include <ctime>
U-Lama\Leee13c3e62011-12-28 14:36:55 -08006
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08007#if defined( _MSC_VER )
Lee Thomasone9699e62012-07-25 12:24:23 -07008 #include <direct.h> // _mkdir
Lee Thomason1ff38e02012-02-14 18:18:16 -08009 #include <crtdbg.h>
Lee Thomason6f381b72012-03-02 12:59:39 -080010 #define WIN32_LEAN_AND_MEAN
11 #include <windows.h>
Lee Thomason1ff38e02012-02-14 18:18:16 -080012 _CrtMemState startMemState;
13 _CrtMemState endMemState;
Lee Thomasone9699e62012-07-25 12:24:23 -070014#else
15 #include <sys/stat.h> // mkdir
Lee Thomason1ff38e02012-02-14 18:18:16 -080016#endif
Lee Thomasone9ecdab2012-02-13 18:11:20 -080017
U-Lama\Leee13c3e62011-12-28 14:36:55 -080018using namespace tinyxml2;
Lee Thomasonec5a7b42012-02-13 18:16:52 -080019int gPass = 0;
20int gFail = 0;
21
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -080022
U-Stream\Lee09a11c52012-02-17 08:31:16 -080023bool XMLTest (const char* testString, const char* expected, const char* found, bool echo=true )
Lee Thomason1ff38e02012-02-14 18:18:16 -080024{
25 bool pass = !strcmp( expected, found );
26 if ( pass )
27 printf ("[pass]");
28 else
29 printf ("[fail]");
30
U-Stream\Lee09a11c52012-02-17 08:31:16 -080031 if ( !echo )
Lee Thomason1ff38e02012-02-14 18:18:16 -080032 printf (" %s\n", testString);
33 else
34 printf (" %s [%s][%s]\n", testString, expected, found);
35
36 if ( pass )
37 ++gPass;
38 else
39 ++gFail;
40 return pass;
41}
42
43
Lee Thomason21be8822012-07-15 17:27:22 -070044template< class T > bool XMLTest( const char* testString, T expected, T found, bool echo=true )
Lee Thomason1ff38e02012-02-14 18:18:16 -080045{
46 bool pass = ( expected == found );
47 if ( pass )
48 printf ("[pass]");
49 else
50 printf ("[fail]");
51
U-Stream\Lee09a11c52012-02-17 08:31:16 -080052 if ( !echo )
Lee Thomason1ff38e02012-02-14 18:18:16 -080053 printf (" %s\n", testString);
54 else
Lee Thomasonc8312792012-07-16 12:44:41 -070055 printf (" %s [%d][%d]\n", testString, static_cast<int>(expected), static_cast<int>(found) );
Lee Thomason1ff38e02012-02-14 18:18:16 -080056
57 if ( pass )
58 ++gPass;
59 else
60 ++gFail;
61 return pass;
62}
Lee Thomasonec5a7b42012-02-13 18:16:52 -080063
U-Lama\Leee13c3e62011-12-28 14:36:55 -080064
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -080065void NullLineEndings( char* p )
66{
67 while( p && *p ) {
68 if ( *p == '\n' || *p == '\r' ) {
69 *p = 0;
70 return;
71 }
72 ++p;
73 }
74}
75
76
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070077// Comments in the header. (Don't know how to get Doxygen to read comments in this file.)
78int example_1()
79{
80 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -030081 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070082
83 return doc.ErrorID();
84}
85
86
87// Comments in the header. (Don't know how to get Doxygen to read comments in this file.)
88int example_2()
89{
90 static const char* xml = "<element/>";
91 XMLDocument doc;
92 doc.Parse( xml );
93
94 return doc.ErrorID();
95}
96
97
98int example_3()
99{
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700100 static const char* xml =
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700101 "<?xml version=\"1.0\"?>"
102 "<!DOCTYPE PLAY SYSTEM \"play.dtd\">"
103 "<PLAY>"
104 "<TITLE>A Midsummer Night's Dream</TITLE>"
105 "</PLAY>";
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700106
107 XMLDocument doc;
108 doc.Parse( xml );
109
110 XMLElement* titleElement = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" );
111 const char* title = titleElement->GetText();
112 printf( "Name of play (1): %s\n", title );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700113
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700114 XMLText* textNode = titleElement->FirstChild()->ToText();
115 title = textNode->Value();
116 printf( "Name of play (2): %s\n", title );
117
118 return doc.ErrorID();
119}
120
121
Lee Thomason21be8822012-07-15 17:27:22 -0700122bool example_4()
123{
124 static const char* xml =
125 "<information>"
126 " <attributeApproach v='2' />"
127 " <textApproach>"
128 " <v>2</v>"
129 " </textApproach>"
130 "</information>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700131
Lee Thomason21be8822012-07-15 17:27:22 -0700132 XMLDocument doc;
133 doc.Parse( xml );
134
135 int v0 = 0;
136 int v1 = 0;
137
138 XMLElement* attributeApproachElement = doc.FirstChildElement()->FirstChildElement( "attributeApproach" );
139 attributeApproachElement->QueryIntAttribute( "v", &v0 );
140
141 XMLElement* textApproachElement = doc.FirstChildElement()->FirstChildElement( "textApproach" );
142 textApproachElement->FirstChildElement( "v" )->QueryIntText( &v1 );
143
144 printf( "Both values are the same: %d and %d\n", v0, v1 );
145
146 return !doc.Error() && ( v0 == v1 );
147}
148
149
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700150int main( int /*argc*/, const char ** /*argv*/ )
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800151{
Lee Thomason (grinliz)0a4df402012-02-27 20:50:52 -0800152 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason1ff38e02012-02-14 18:18:16 -0800153 _CrtMemCheckpoint( &startMemState );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700154 #endif
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800155
Lee Thomason7f7b1622012-03-24 12:49:03 -0700156 #if defined(_MSC_VER)
Lee Thomasone9699e62012-07-25 12:24:23 -0700157 _mkdir( "resources/out/" );
158 #else
159 mkdir( "resources/out/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
160 #endif
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400161
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300162 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason7f7b1622012-03-24 12:49:03 -0700163 if ( !fp ) {
164 printf( "Error opening test file 'dream.xml'.\n"
165 "Is your working directory the same as where \n"
166 "the xmltest.cpp and dream.xml file are?\n\n"
167 #if defined( _MSC_VER )
168 "In windows Visual Studio you may need to set\n"
169 "Properties->Debugging->Working Directory to '..'\n"
170 #endif
171 );
172 exit( 1 );
173 }
174 fclose( fp );
175
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700176 XMLTest( "Example-1", 0, example_1() );
177 XMLTest( "Example-2", 0, example_2() );
178 XMLTest( "Example-3", 0, example_3() );
Lee Thomason21be8822012-07-15 17:27:22 -0700179 XMLTest( "Example-4", true, example_4() );
Lee Thomason87e475a2012-03-20 11:55:29 -0700180
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700181 /* ------ Example 2: Lookup information. ---- */
Lee Thomason87e475a2012-03-20 11:55:29 -0700182
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800183 {
Lee Thomason43f59302012-02-06 18:18:11 -0800184 static const char* test[] = { "<element />",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400185 "<element></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800186 "<element><subelement/></element>",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400187 "<element><subelement></subelement></element>",
188 "<element><subelement><subsub/></subelement></element>",
189 "<!--comment beside elements--><element><subelement></subelement></element>",
190 "<!--comment beside elements, this time with spaces--> \n <element> <subelement> \n </subelement> </element>",
191 "<element attrib1='foo' attrib2=\"bar\" ></element>",
192 "<element attrib1='foo' attrib2=\"bar\" ><subelement attrib3='yeehaa' /></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800193 "<element>Text inside element.</element>",
194 "<element><b></b></element>",
195 "<element>Text inside and <b>bolded</b> in the element.</element>",
196 "<outer><element>Text inside and <b>bolded</b> in the element.</element></outer>",
Lee Thomason8ee79892012-01-25 17:44:30 -0800197 "<element>This &amp; That.</element>",
Lee Thomason18d68bd2012-01-26 18:17:26 -0800198 "<element attrib='This&lt;That' />",
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800199 0
200 };
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800201 for( int i=0; test[i]; ++i ) {
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800202 XMLDocument doc;
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800203 doc.Parse( test[i] );
Lee Thomason5cae8972012-01-24 18:03:07 -0800204 doc.Print();
Lee Thomasonec975ce2012-01-23 11:42:06 -0800205 printf( "----------------------------------------------\n" );
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800206 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800207 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800208#if 1
Lee Thomasond6277762012-02-22 16:00:12 -0800209 {
210 static const char* test = "<!--hello world\n"
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400211 " line 2\r"
212 " line 3\r\n"
213 " line 4\n\r"
214 " line 5\r-->";
Lee Thomasond6277762012-02-22 16:00:12 -0800215
216 XMLDocument doc;
217 doc.Parse( test );
218 doc.Print();
219 }
220
Lee Thomason2c85a712012-01-31 08:24:24 -0800221 {
222 static const char* test = "<element>Text before.</element>";
223 XMLDocument doc;
224 doc.Parse( test );
225 XMLElement* root = doc.FirstChildElement();
226 XMLElement* newElement = doc.NewElement( "Subelement" );
227 root->InsertEndChild( newElement );
228 doc.Print();
229 }
Lee Thomasond1983222012-02-06 08:41:24 -0800230 {
231 XMLDocument* doc = new XMLDocument();
232 static const char* test = "<element><sub/></element>";
233 doc->Parse( test );
234 delete doc;
235 }
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800236 {
Lee Thomason1ff38e02012-02-14 18:18:16 -0800237 // Test: Programmatic DOM
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800238 // Build:
239 // <element>
240 // <!--comment-->
241 // <sub attrib="1" />
242 // <sub attrib="2" />
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800243 // <sub attrib="3" >& Text!</sub>
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800244 // <element>
245
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800246 XMLDocument* doc = new XMLDocument();
Lee Thomason1ff38e02012-02-14 18:18:16 -0800247 XMLNode* element = doc->InsertEndChild( doc->NewElement( "element" ) );
248
249 XMLElement* sub[3] = { doc->NewElement( "sub" ), doc->NewElement( "sub" ), doc->NewElement( "sub" ) };
250 for( int i=0; i<3; ++i ) {
251 sub[i]->SetAttribute( "attrib", i );
252 }
253 element->InsertEndChild( sub[2] );
254 XMLNode* comment = element->InsertFirstChild( doc->NewComment( "comment" ) );
255 element->InsertAfterChild( comment, sub[0] );
256 element->InsertAfterChild( sub[0], sub[1] );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800257 sub[2]->InsertFirstChild( doc->NewText( "& Text!" ));
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800258 doc->Print();
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800259 XMLTest( "Programmatic DOM", "comment", doc->FirstChildElement( "element" )->FirstChild()->Value() );
260 XMLTest( "Programmatic DOM", "0", doc->FirstChildElement( "element" )->FirstChildElement()->Attribute( "attrib" ) );
261 XMLTest( "Programmatic DOM", 2, doc->FirstChildElement()->LastChildElement( "sub" )->IntAttribute( "attrib" ) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700262 XMLTest( "Programmatic DOM", "& Text!",
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800263 doc->FirstChildElement()->LastChildElement( "sub" )->FirstChild()->ToText()->Value() );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800264
265 // And now deletion:
266 element->DeleteChild( sub[2] );
267 doc->DeleteNode( comment );
268
269 element->FirstChildElement()->SetAttribute( "attrib", true );
270 element->LastChildElement()->DeleteAttribute( "attrib" );
271
272 XMLTest( "Programmatic DOM", true, doc->FirstChildElement()->FirstChildElement()->BoolAttribute( "attrib" ) );
273 int value = 10;
274 int result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value );
Lee Thomason21be8822012-07-15 17:27:22 -0700275 XMLTest( "Programmatic DOM", result, (int)XML_NO_ATTRIBUTE );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800276 XMLTest( "Programmatic DOM", value, 10 );
277
278 doc->Print();
279
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700280 {
281 XMLPrinter streamer;
282 doc->Print( &streamer );
283 printf( "%s", streamer.CStr() );
284 }
285 {
286 XMLPrinter streamer( 0, true );
287 doc->Print( &streamer );
288 XMLTest( "Compact mode", "<element><sub attrib=\"1\"/><sub/></element>", streamer.CStr(), false );
289 }
Lee Thomason (grinliz)6b8b0122012-09-08 21:21:00 -0700290 doc->SaveFile( "./resources/out/pretty.xml" );
291 doc->SaveFile( "./resources/out/compact.xml", true );
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800292 delete doc;
293 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800294 {
295 // Test: Dream
296 // XML1 : 1,187,569 bytes in 31,209 allocations
297 // XML2 : 469,073 bytes in 323 allocations
298 //int newStart = gNew;
299 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300300 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800301
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400302 doc.SaveFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800303 doc.PrintError();
304
305 XMLTest( "Dream", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400306 doc.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800307 XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false );
308 XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
309 doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
310 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400311 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800312 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400313 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800314
315 XMLDocument doc2;
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400316 doc2.LoadFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800317 XMLTest( "Dream-out", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400318 doc2.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800319 XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false );
320 XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
321 doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
322 XMLTest( "Dream-out", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400323 doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800324
325 //gNewTotal = gNew - newStart;
326 }
Lee Thomason6f381b72012-03-02 12:59:39 -0800327
328
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800329 {
330 const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
331 "<passages count=\"006\" formatversion=\"20020620\">\n"
332 " <wrong error>\n"
333 "</passages>";
334
335 XMLDocument doc;
336 doc.Parse( error );
Lee Thomason21be8822012-07-15 17:27:22 -0700337 XMLTest( "Bad XML", doc.ErrorID(), (int)XML_ERROR_PARSING_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800338 }
339
340 {
341 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
342
343 XMLDocument doc;
344 doc.Parse( str );
345
346 XMLElement* ele = doc.FirstChildElement();
347
348 int iVal, result;
349 double dVal;
350
351 result = ele->QueryDoubleAttribute( "attr0", &dVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700352 XMLTest( "Query attribute: int as double", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800353 XMLTest( "Query attribute: int as double", (int)dVal, 1 );
354 result = ele->QueryDoubleAttribute( "attr1", &dVal );
355 XMLTest( "Query attribute: double as double", (int)dVal, 2 );
356 result = ele->QueryIntAttribute( "attr1", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700357 XMLTest( "Query attribute: double as int", result, (int)XML_NO_ERROR );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800358 XMLTest( "Query attribute: double as int", iVal, 2 );
359 result = ele->QueryIntAttribute( "attr2", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700360 XMLTest( "Query attribute: not a number", result, (int)XML_WRONG_ATTRIBUTE_TYPE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800361 result = ele->QueryIntAttribute( "bar", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700362 XMLTest( "Query attribute: does not exist", result, (int)XML_NO_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800363 }
364
365 {
366 const char* str = "<doc/>";
367
368 XMLDocument doc;
369 doc.Parse( str );
370
371 XMLElement* ele = doc.FirstChildElement();
372
373 int iVal;
374 double dVal;
375
376 ele->SetAttribute( "str", "strValue" );
377 ele->SetAttribute( "int", 1 );
378 ele->SetAttribute( "double", -1.0 );
379
380 const char* cStr = ele->Attribute( "str" );
381 ele->QueryIntAttribute( "int", &iVal );
382 ele->QueryDoubleAttribute( "double", &dVal );
383
Lee Thomason8ba7f7d2012-03-24 13:04:04 -0700384 XMLTest( "Attribute match test", ele->Attribute( "str", "strValue" ), "strValue" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800385 XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
386 XMLTest( "Attribute round trip. int.", 1, iVal );
387 XMLTest( "Attribute round trip. double.", -1, (int)dVal );
388 }
389
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800390 {
391 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300392 doc.LoadFile( "resources/utf8test.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800393
394 // Get the attribute "value" from the "Russian" element and check it.
395 XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700396 const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800397 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
398
399 XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
400
401 const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U,
402 0xd1U, 0x81U, 0xd1U, 0x81U,
403 0xd0U, 0xbaU, 0xd0U, 0xb8U,
404 0xd0U, 0xb9U, 0 };
405 const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
406
407 XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
408 XMLTest( "UTF-8: Browsing russian element name.",
409 russianText,
410 text->Value() );
411
412 // Now try for a round trip.
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400413 doc.SaveFile( "resources/out/utf8testout.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800414
415 // Check the round trip.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800416 int okay = 0;
417
Thomas Roßa6dd8c62012-07-26 20:42:18 +0200418 FILE* saved = fopen( "resources/out/utf8testout.xml", "r" );
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300419 FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800420
421 if ( saved && verify )
422 {
423 okay = 1;
PKEuSc28ba3a2012-07-16 03:08:47 -0700424 char verifyBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800425 while ( fgets( verifyBuf, 256, verify ) )
426 {
PKEuSc28ba3a2012-07-16 03:08:47 -0700427 char savedBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800428 fgets( savedBuf, 256, saved );
429 NullLineEndings( verifyBuf );
430 NullLineEndings( savedBuf );
431
432 if ( strcmp( verifyBuf, savedBuf ) )
433 {
434 printf( "verify:%s<\n", verifyBuf );
435 printf( "saved :%s<\n", savedBuf );
436 okay = 0;
437 break;
438 }
439 }
440 }
441 if ( saved )
442 fclose( saved );
443 if ( verify )
444 fclose( verify );
445 XMLTest( "UTF-8: Verified multi-language round trip.", 1, okay );
446 }
447
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800448 // --------GetText()-----------
449 {
450 const char* str = "<foo>This is text</foo>";
451 XMLDocument doc;
452 doc.Parse( str );
453 const XMLElement* element = doc.RootElement();
454
455 XMLTest( "GetText() normal use.", "This is text", element->GetText() );
456
457 str = "<foo><b>This is text</b></foo>";
458 doc.Parse( str );
459 element = doc.RootElement();
460
461 XMLTest( "GetText() contained element.", element->GetText() == 0, true );
462 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800463
Lee Thomasond6277762012-02-22 16:00:12 -0800464
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800465 // ---------- CDATA ---------------
466 {
467 const char* str = "<xmlElement>"
468 "<![CDATA["
469 "I am > the rules!\n"
470 "...since I make symbolic puns"
471 "]]>"
472 "</xmlElement>";
473 XMLDocument doc;
474 doc.Parse( str );
475 doc.Print();
Lee Thomasond6277762012-02-22 16:00:12 -0800476
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700477 XMLTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800478 "I am > the rules!\n...since I make symbolic puns",
Lee Thomasond6277762012-02-22 16:00:12 -0800479 false );
480 }
481
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800482 // ----------- CDATA -------------
483 {
484 const char* str = "<xmlElement>"
485 "<![CDATA["
486 "<b>I am > the rules!</b>\n"
487 "...since I make symbolic puns"
488 "]]>"
489 "</xmlElement>";
490 XMLDocument doc;
491 doc.Parse( str );
492 doc.Print();
493
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700494 XMLTest( "CDATA parse. [ tixml1:1480107 ]", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800495 "<b>I am > the rules!</b>\n...since I make symbolic puns",
496 false );
497 }
498
499 // InsertAfterChild causes crash.
500 {
501 // InsertBeforeChild and InsertAfterChild causes crash.
502 XMLDocument doc;
503 XMLElement* parent = doc.NewElement( "Parent" );
504 doc.InsertFirstChild( parent );
505
506 XMLElement* childText0 = doc.NewElement( "childText0" );
507 XMLElement* childText1 = doc.NewElement( "childText1" );
508
509 XMLNode* childNode0 = parent->InsertEndChild( childText0 );
510 XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
511
512 XMLTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent->LastChild() ), true );
513 }
Lee Thomasond6277762012-02-22 16:00:12 -0800514
515 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800516 // Entities not being written correctly.
517 // From Lynn Allen
Lee Thomasond6277762012-02-22 16:00:12 -0800518
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800519 const char* passages =
520 "<?xml version=\"1.0\" standalone=\"no\" ?>"
521 "<passages count=\"006\" formatversion=\"20020620\">"
522 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
523 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
524 "</passages>";
Lee Thomasond6277762012-02-22 16:00:12 -0800525
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800526 XMLDocument doc;
527 doc.Parse( passages );
528 XMLElement* psg = doc.RootElement()->FirstChildElement();
529 const char* context = psg->Attribute( "context" );
530 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 -0800531
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800532 XMLTest( "Entity transformation: read. ", expected, context, true );
Lee Thomasond6277762012-02-22 16:00:12 -0800533
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400534 FILE* textfile = fopen( "resources/out/textfile.txt", "w" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800535 if ( textfile )
536 {
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800537 XMLPrinter streamer( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800538 psg->Accept( &streamer );
539 fclose( textfile );
540 }
Thomas Roß0922b732012-09-23 16:31:22 +0200541
542 textfile = fopen( "resources/out/textfile.txt", "r" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800543 TIXMLASSERT( textfile );
544 if ( textfile )
545 {
546 char buf[ 1024 ];
547 fgets( buf, 1024, textfile );
548 XMLTest( "Entity transformation: write. ",
549 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
550 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
551 buf, false );
PKEuSc28ba3a2012-07-16 03:08:47 -0700552 fclose( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800553 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800554 }
555
556 {
Lee Thomason6f381b72012-03-02 12:59:39 -0800557 // Suppress entities.
558 const char* passages =
559 "<?xml version=\"1.0\" standalone=\"no\" ?>"
560 "<passages count=\"006\" formatversion=\"20020620\">"
561 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
562 "</passages>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700563
Lee Thomason6f381b72012-03-02 12:59:39 -0800564 XMLDocument doc( false );
565 doc.Parse( passages );
566
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700567 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ),
Lee Thomason6f381b72012-03-02 12:59:39 -0800568 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;." );
569 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value(),
570 "Crazy &ttk;" );
571 doc.Print();
572 }
573
574 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400575 const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800576
577 XMLDocument doc;
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400578 doc.Parse( test );
579 XMLTest( "dot in names", doc.Error(), false );
580 XMLTest( "dot in names", doc.FirstChildElement()->Name(), "a.elem" );
581 XMLTest( "dot in names", doc.FirstChildElement()->Attribute( "xmi.version" ), "2.0" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800582 }
583
584 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400585 const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800586
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400587 XMLDocument doc;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800588 doc.Parse( test );
589
590 XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
591 XMLTest( "Entity with one digit.",
592 text->Value(), "1.1 Start easy ignore fin thickness\n",
593 false );
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400594 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800595
596 {
597 // DOCTYPE not preserved (950171)
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700598 //
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800599 const char* doctype =
600 "<?xml version=\"1.0\" ?>"
601 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
602 "<!ELEMENT title (#PCDATA)>"
603 "<!ELEMENT books (title,authors)>"
604 "<element />";
605
606 XMLDocument doc;
607 doc.Parse( doctype );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400608 doc.SaveFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800609 doc.DeleteChild( doc.RootElement() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400610 doc.LoadFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800611 doc.Print();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700612
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800613 const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
614 XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
615
616 }
617
618 {
619 // Comments do not stream out correctly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700620 const char* doctype =
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800621 "<!-- Somewhat<evil> -->";
622 XMLDocument doc;
623 doc.Parse( doctype );
624
625 XMLComment* comment = doc.FirstChild()->ToComment();
626
627 XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
628 }
629 {
630 // Double attributes
631 const char* doctype = "<element attr='red' attr='blue' />";
632
633 XMLDocument doc;
634 doc.Parse( doctype );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700635
Lee Thomason21be8822012-07-15 17:27:22 -0700636 XMLTest( "Parsing repeated attributes.", (int)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 -0800637 doc.PrintError();
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800638 }
639
640 {
641 // Embedded null in stream.
642 const char* doctype = "<element att\0r='red' attr='blue' />";
643
644 XMLDocument doc;
645 doc.Parse( doctype );
646 XMLTest( "Embedded null throws error.", true, doc.Error() );
647 }
648
649 {
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700650 // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800651 const char* str = " ";
652 XMLDocument doc;
653 doc.Parse( str );
Lee Thomason21be8822012-07-15 17:27:22 -0700654 XMLTest( "Empty document error", (int)XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800655 }
656
657 {
658 // Low entities
659 XMLDocument doc;
660 doc.Parse( "<test>&#x0e;</test>" );
661 const char result[] = { 0x0e, 0 };
662 XMLTest( "Low entities.", doc.FirstChildElement()->GetText(), result );
663 doc.Print();
664 }
665
666 {
667 // Attribute values with trailing quotes not handled correctly
668 XMLDocument doc;
669 doc.Parse( "<foo attribute=bar\" />" );
670 XMLTest( "Throw error with bad end quotes.", doc.Error(), true );
671 }
672
673 {
674 // [ 1663758 ] Failure to report error on bad XML
675 XMLDocument xml;
676 xml.Parse("<x>");
677 XMLTest("Missing end tag at end of input", xml.Error(), true);
678 xml.Parse("<x> ");
679 XMLTest("Missing end tag with trailing whitespace", xml.Error(), true);
680 xml.Parse("<x></y>");
Lee Thomason21be8822012-07-15 17:27:22 -0700681 XMLTest("Mismatched tags", xml.ErrorID(), (int)XML_ERROR_MISMATCHED_ELEMENT);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700682 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800683
684
685 {
686 // [ 1475201 ] TinyXML parses entities in comments
687 XMLDocument xml;
688 xml.Parse("<!-- declarations for <head> & <body> -->"
689 "<!-- far &amp; away -->" );
690
691 XMLNode* e0 = xml.FirstChild();
692 XMLNode* e1 = e0->NextSibling();
693 XMLComment* c0 = e0->ToComment();
694 XMLComment* c1 = e1->ToComment();
695
696 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
697 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
698 }
699
700 {
701 XMLDocument xml;
702 xml.Parse( "<Parent>"
703 "<child1 att=''/>"
704 "<!-- With this comment, child2 will not be parsed! -->"
705 "<child2 att=''/>"
706 "</Parent>" );
707 xml.Print();
708
709 int count = 0;
710
711 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
712 ele;
713 ele = ele->NextSibling() )
714 {
715 ++count;
716 }
717
718 XMLTest( "Comments iterate correctly.", 3, count );
719 }
720
721 {
722 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
723 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
724 buf[60] = 239;
725 buf[61] = 0;
726
727 XMLDocument doc;
728 doc.Parse( (const char*)buf);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700729 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800730
731
732 {
733 // bug 1827248 Error while parsing a little bit malformed file
734 // Actually not malformed - should work.
735 XMLDocument xml;
736 xml.Parse( "<attributelist> </attributelist >" );
737 XMLTest( "Handle end tag whitespace", false, xml.Error() );
738 }
739
740 {
741 // This one must not result in an infinite loop
742 XMLDocument xml;
743 xml.Parse( "<infinite>loop" );
744 XMLTest( "Infinite loop test.", true, true );
745 }
746#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800747 {
748 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
749 XMLDocument doc;
750 doc.Parse( pub );
751
752 XMLDocument clone;
753 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
754 XMLNode* copy = node->ShallowClone( &clone );
755 clone.InsertEndChild( copy );
756 }
757
758 clone.Print();
759
760 int count=0;
761 const XMLNode* a=clone.FirstChild();
762 const XMLNode* b=doc.FirstChild();
763 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
764 ++count;
765 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
766 }
767 XMLTest( "Clone and Equal", 4, count );
768 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800769
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700770 {
771 // This shouldn't crash.
772 XMLDocument doc;
773 if(XML_NO_ERROR != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
774 {
775 doc.PrintError();
776 }
777 XMLTest( "Error in snprinf handling.", true, doc.Error() );
778 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700779
Lee Thomason5e3803c2012-04-16 08:57:05 -0700780 {
781 // Attribute ordering.
782 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
783 XMLDocument doc;
784 doc.Parse( xml );
785 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700786
Lee Thomason5e3803c2012-04-16 08:57:05 -0700787 const XMLAttribute* a = ele->FirstAttribute();
788 XMLTest( "Attribute order", "1", a->Value() );
789 a = a->Next();
790 XMLTest( "Attribute order", "2", a->Value() );
791 a = a->Next();
792 XMLTest( "Attribute order", "3", a->Value() );
793 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700794
Lee Thomason5e3803c2012-04-16 08:57:05 -0700795 ele->DeleteAttribute( "attrib2" );
796 a = ele->FirstAttribute();
797 XMLTest( "Attribute order", "1", a->Value() );
798 a = a->Next();
799 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700800
Lee Thomason5e3803c2012-04-16 08:57:05 -0700801 ele->DeleteAttribute( "attrib1" );
802 ele->DeleteAttribute( "attrib3" );
803 XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
804 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700805
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -0700806 {
807 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -0700808 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
809 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
810 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
811 XMLDocument doc0;
812 doc0.Parse( xml0 );
813 XMLDocument doc1;
814 doc1.Parse( xml1 );
815 XMLDocument doc2;
816 doc2.Parse( xml2 );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -0700817
Lee Thomason78a773d2012-07-02 10:10:19 -0700818 XMLElement* ele = 0;
819 ele = doc0.FirstChildElement();
820 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
821 ele = doc1.FirstChildElement();
822 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
823 ele = doc2.FirstChildElement();
824 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -0700825 }
826
827 {
828 // Make sure we don't go into an infinite loop.
829 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
830 XMLDocument doc;
831 doc.Parse( xml );
832 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
833 XMLElement* ele1 = ele0->NextSiblingElement();
834 bool equal = ele0->ShallowEqual( ele1 );
835
836 XMLTest( "Infinite loop in shallow equal.", true, equal );
837 }
838
Lee Thomason5708f812012-03-28 17:46:41 -0700839 // -------- Handles ------------
840 {
841 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
842 XMLDocument doc;
843 doc.Parse( xml );
Lee Thomason5708f812012-03-28 17:46:41 -0700844
845 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
846 XMLTest( "Handle, success, mutable", ele->Value(), "sub" );
847
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -0700848 XMLHandle docH( doc );
849 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -0700850 XMLTest( "Handle, dne, mutable", false, ele != 0 );
Lee Thomason5708f812012-03-28 17:46:41 -0700851 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700852
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -0700853 {
854 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
855 XMLDocument doc;
856 doc.Parse( xml );
857 XMLConstHandle docH( doc );
858
859 const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
860 XMLTest( "Handle, success, const", ele->Value(), "sub" );
861
862 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -0700863 XMLTest( "Handle, dne, const", false, ele != 0 );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -0700864 }
Lee Thomasonf68c4382012-04-28 14:37:11 -0700865 {
866 // Default Declaration & BOM
867 XMLDocument doc;
868 doc.InsertEndChild( doc.NewDeclaration() );
869 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700870
Lee Thomasonf68c4382012-04-28 14:37:11 -0700871 XMLPrinter printer;
872 doc.Print( &printer );
873
874 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
875 XMLTest( "BOM and default declaration", printer.CStr(), result, false );
Lee Thomason (grinliz)48ea0bc2012-05-26 14:41:14 -0700876 XMLTest( "CStrSize", printer.CStrSize(), 42, false );
Lee Thomasonf68c4382012-04-28 14:37:11 -0700877 }
Lee Thomason21be8822012-07-15 17:27:22 -0700878 {
879 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
880 XMLDocument doc;
881 doc.Parse( xml );
882 XMLTest( "Ill formed XML", true, doc.Error() );
883 }
884
885 // QueryXYZText
886 {
887 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
888 XMLDocument doc;
889 doc.Parse( xml );
890
891 const XMLElement* pointElement = doc.RootElement();
892
893 int intValue = 0;
894 unsigned unsignedValue = 0;
895 float floatValue = 0;
896 double doubleValue = 0;
897 bool boolValue = false;
898
899 pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
900 pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
901 pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
902 pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
903 pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
904
905
906 XMLTest( "QueryIntText", intValue, 1, false );
907 XMLTest( "QueryUnsignedText", unsignedValue, (unsigned)1, false );
908 XMLTest( "QueryFloatText", floatValue, 1.2f, false );
909 XMLTest( "QueryDoubleText", doubleValue, 1.2, false );
910 XMLTest( "QueryBoolText", boolValue, true, false );
911 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -0700912
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -0700913 {
914 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
915 XMLDocument doc;
916 doc.Parse( xml );
917 XMLTest( "Non-alpha element lead letter parses.", doc.Error(), false );
918 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -0700919
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -0700920 {
921 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
922 XMLDocument doc;
923 doc.Parse( xml, 10 );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -0700924 XMLTest( "Set length of incoming data", doc.Error(), false );
925 }
926
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -0700927 // ----------- Whitespace ------------
928 {
929 const char* xml = "<element>"
930 "<a> This \nis &apos; text &apos; </a>"
931 "<b> This is &apos; text &apos; \n</b>"
932 "<c>This is &apos; \n\n text &apos;</c>"
933 "</element>";
934 XMLDocument doc( true, COLLAPSE_WHITESPACE );
935 doc.Parse( xml );
936
937 const XMLElement* element = doc.FirstChildElement();
938 for( const XMLElement* parent = element->FirstChildElement();
939 parent;
940 parent = parent->NextSiblingElement() )
941 {
942 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
943 }
944 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -0700945
Lee Thomasonae9ab072012-10-24 10:17:53 -0700946#if 0
947 {
948 // Passes if assert doesn't fire.
949 XMLDocument xmlDoc;
950
951 xmlDoc.NewDeclaration();
952 xmlDoc.NewComment("Configuration file");
953
954 XMLElement *root = xmlDoc.NewElement("settings");
955 root->SetAttribute("version", 2);
956 }
957#endif
958
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -0700959 {
960 const char* xml = "<element> </element>";
961 XMLDocument doc( true, COLLAPSE_WHITESPACE );
962 doc.Parse( xml );
963 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
964 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700965
Lee Thomason (grinliz)fc6320e2012-09-23 20:25:50 -0700966#if 0 // the question being explored is what kind of print to use:
967 // https://github.com/leethomason/tinyxml2/issues/63
968 {
969 const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9'/>";
970 XMLDocument doc;
971 doc.Parse( xml );
972 doc.FirstChildElement()->SetAttribute( "attrA", 123456789.123456789 );
973 doc.FirstChildElement()->SetAttribute( "attrB", 1.001e9 );
974 doc.Print();
975 }
976#endif
977
Lee Thomason6f381b72012-03-02 12:59:39 -0800978 // ----------- Performance tracking --------------
979 {
980#if defined( _MSC_VER )
981 __int64 start, end, freq;
982 QueryPerformanceFrequency( (LARGE_INTEGER*) &freq );
983#endif
984
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300985 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason6f381b72012-03-02 12:59:39 -0800986 fseek( fp, 0, SEEK_END );
987 long size = ftell( fp );
988 fseek( fp, 0, SEEK_SET );
989
990 char* mem = new char[size+1];
991 fread( mem, size, 1, fp );
992 fclose( fp );
993 mem[size] = 0;
994
995#if defined( _MSC_VER )
996 QueryPerformanceCounter( (LARGE_INTEGER*) &start );
997#else
998 clock_t cstart = clock();
999#endif
1000 static const int COUNT = 10;
1001 for( int i=0; i<COUNT; ++i ) {
1002 XMLDocument doc;
1003 doc.Parse( mem );
1004 }
1005#if defined( _MSC_VER )
1006 QueryPerformanceCounter( (LARGE_INTEGER*) &end );
1007#else
1008 clock_t cend = clock();
1009#endif
1010
1011 delete [] mem;
1012
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001013 static const char* note =
Lee Thomason6f381b72012-03-02 12:59:39 -08001014#ifdef DEBUG
1015 "DEBUG";
1016#else
1017 "Release";
1018#endif
1019
1020#if defined( _MSC_VER )
1021 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, 1000.0 * (double)(end-start) / ( (double)freq * (double)COUNT) );
1022#else
1023 printf( "\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart)/(double)COUNT );
1024#endif
1025 }
1026
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -08001027 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001028 _CrtMemCheckpoint( &endMemState );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001029 //_CrtMemDumpStatistics( &endMemState );
1030
1031 _CrtMemState diffMemState;
1032 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
1033 _CrtMemDumpStatistics( &diffMemState );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001034 //printf( "new total=%d\n", gNewTotal );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001035 #endif
1036
1037 printf ("\nPass %d, Fail %d\n", gPass, gFail);
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001038 return 0;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08001039}