blob: b6bb76f537a33974b339ecb624b5b0b6f6bfadd0 [file] [log] [blame]
Lee Thomason5b0a6772012-11-19 13:54:42 -08001#if defined( _MSC_VER )
Serhat Eser Erdemca5d6842014-04-17 14:06:15 +02002 #if !defined( _CRT_SECURE_NO_WARNINGS )
3 #define _CRT_SECURE_NO_WARNINGS // This test file is not intended to be secure.
4 #endif
Lee Thomason5b0a6772012-11-19 13:54:42 -08005#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08006
Lee Thomason5b0a6772012-11-19 13:54:42 -08007#include "tinyxml2.h"
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -07008#include <cstdlib>
9#include <cstring>
10#include <ctime>
U-Lama\Leee13c3e62011-12-28 14:36:55 -080011
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080012#if defined( _MSC_VER )
Lee Thomasone9699e62012-07-25 12:24:23 -070013 #include <direct.h> // _mkdir
Lee Thomason1ff38e02012-02-14 18:18:16 -080014 #include <crtdbg.h>
Lee Thomason6f381b72012-03-02 12:59:39 -080015 #define WIN32_LEAN_AND_MEAN
16 #include <windows.h>
Lee Thomason1ff38e02012-02-14 18:18:16 -080017 _CrtMemState startMemState;
18 _CrtMemState endMemState;
Martinsh Shaiters39ddc262013-01-15 21:53:08 +020019#elif defined(MINGW32) || defined(__MINGW32__)
20 #include <io.h> // mkdir
Lee Thomasone9699e62012-07-25 12:24:23 -070021#else
22 #include <sys/stat.h> // mkdir
Lee Thomason1ff38e02012-02-14 18:18:16 -080023#endif
Lee Thomasone9ecdab2012-02-13 18:11:20 -080024
U-Lama\Leee13c3e62011-12-28 14:36:55 -080025using namespace tinyxml2;
Anton Indrawan8a0006c2014-11-20 18:27:07 +010026using namespace std;
Lee Thomasonec5a7b42012-02-13 18:16:52 -080027int gPass = 0;
28int gFail = 0;
29
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -080030
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070031bool XMLTest (const char* testString, const char* expected, const char* found, bool echo=true, bool extraNL=false )
Lee Thomason1ff38e02012-02-14 18:18:16 -080032{
Sarat Addepalli13b2d732015-05-19 12:44:57 +053033 bool pass;
34 if ( !expected && !found )
35 pass = true;
36 else if ( !expected || !found )
37 pass = false;
Sarat Addepallid608c562015-05-20 10:19:00 +053038 else
39 pass = !strcmp( expected, found );
Lee Thomason1ff38e02012-02-14 18:18:16 -080040 if ( pass )
41 printf ("[pass]");
42 else
43 printf ("[fail]");
44
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070045 if ( !echo ) {
Lee Thomason1ff38e02012-02-14 18:18:16 -080046 printf (" %s\n", testString);
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070047 }
48 else {
49 if ( extraNL ) {
50 printf( " %s\n", testString );
51 printf( "%s\n", expected );
52 printf( "%s\n", found );
53 }
54 else {
55 printf (" %s [%s][%s]\n", testString, expected, found);
56 }
57 }
Lee Thomason1ff38e02012-02-14 18:18:16 -080058
59 if ( pass )
60 ++gPass;
61 else
62 ++gFail;
63 return pass;
64}
65
kezenator5a700712016-11-26 13:54:42 +100066bool XMLTest(const char* testString, XMLError expected, XMLError found, bool echo = true, bool extraNL = false)
67{
Lee Thomasone90e9012016-12-24 07:34:39 -080068 return XMLTest(testString, XMLDocument::ErrorIDToName(expected), XMLDocument::ErrorIDToName(found), echo, extraNL);
kezenator5a700712016-11-26 13:54:42 +100069}
70
71bool XMLTest(const char* testString, bool expected, bool found, bool echo = true, bool extraNL = false)
72{
73 return XMLTest(testString, expected ? "true" : "false", found ? "true" : "false", echo, extraNL);
74}
Lee Thomason1ff38e02012-02-14 18:18:16 -080075
Lee Thomason21be8822012-07-15 17:27:22 -070076template< class T > bool XMLTest( const char* testString, T expected, T found, bool echo=true )
Lee Thomason1ff38e02012-02-14 18:18:16 -080077{
78 bool pass = ( expected == found );
79 if ( pass )
80 printf ("[pass]");
81 else
82 printf ("[fail]");
83
U-Stream\Lee09a11c52012-02-17 08:31:16 -080084 if ( !echo )
Lee Thomason1ff38e02012-02-14 18:18:16 -080085 printf (" %s\n", testString);
86 else
Lee Thomasonc8312792012-07-16 12:44:41 -070087 printf (" %s [%d][%d]\n", testString, static_cast<int>(expected), static_cast<int>(found) );
Lee Thomason1ff38e02012-02-14 18:18:16 -080088
89 if ( pass )
90 ++gPass;
91 else
92 ++gFail;
93 return pass;
94}
Lee Thomasonec5a7b42012-02-13 18:16:52 -080095
U-Lama\Leee13c3e62011-12-28 14:36:55 -080096
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -080097void NullLineEndings( char* p )
98{
99 while( p && *p ) {
100 if ( *p == '\n' || *p == '\r' ) {
101 *p = 0;
102 return;
103 }
104 ++p;
105 }
106}
107
108
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700109int example_1()
110{
111 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300112 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700113
114 return doc.ErrorID();
115}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200116/** @page Example-1 Load an XML File
117 * @dontinclude ./xmltest.cpp
118 * Basic XML file loading.
119 * The basic syntax to load an XML file from
120 * disk and check for an error. (ErrorID()
121 * will return 0 for no error.)
122 * @skip example_1()
123 * @until }
124 */
125
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700126
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700127int example_2()
128{
129 static const char* xml = "<element/>";
130 XMLDocument doc;
131 doc.Parse( xml );
132
133 return doc.ErrorID();
134}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200135/** @page Example-2 Parse an XML from char buffer
136 * @dontinclude ./xmltest.cpp
137 * Basic XML string parsing.
138 * The basic syntax to parse an XML for
139 * a char* and check for an error. (ErrorID()
140 * will return 0 for no error.)
141 * @skip example_2()
142 * @until }
143 */
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700144
145
146int example_3()
147{
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700148 static const char* xml =
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700149 "<?xml version=\"1.0\"?>"
150 "<!DOCTYPE PLAY SYSTEM \"play.dtd\">"
151 "<PLAY>"
152 "<TITLE>A Midsummer Night's Dream</TITLE>"
153 "</PLAY>";
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700154
155 XMLDocument doc;
156 doc.Parse( xml );
157
158 XMLElement* titleElement = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" );
159 const char* title = titleElement->GetText();
160 printf( "Name of play (1): %s\n", title );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700161
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700162 XMLText* textNode = titleElement->FirstChild()->ToText();
163 title = textNode->Value();
164 printf( "Name of play (2): %s\n", title );
165
166 return doc.ErrorID();
167}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200168/** @page Example-3 Get information out of XML
169 @dontinclude ./xmltest.cpp
170 In this example, we navigate a simple XML
171 file, and read some interesting text. Note
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700172 that this example doesn't use error
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200173 checking; working code should check for null
174 pointers when walking an XML tree, or use
175 XMLHandle.
176
177 (The XML is an excerpt from "dream.xml").
178
179 @skip example_3()
180 @until </PLAY>";
181
182 The structure of the XML file is:
183
184 <ul>
185 <li>(declaration)</li>
186 <li>(dtd stuff)</li>
187 <li>Element "PLAY"</li>
188 <ul>
189 <li>Element "TITLE"</li>
190 <ul>
191 <li>Text "A Midsummer Night's Dream"</li>
192 </ul>
193 </ul>
194 </ul>
195
196 For this example, we want to print out the
197 title of the play. The text of the title (what
198 we want) is child of the "TITLE" element which
199 is a child of the "PLAY" element.
200
201 We want to skip the declaration and dtd, so the
202 method FirstChildElement() is a good choice. The
203 FirstChildElement() of the Document is the "PLAY"
204 Element, the FirstChildElement() of the "PLAY" Element
205 is the "TITLE" Element.
206
207 @until ( "TITLE" );
208
209 We can then use the convenience function GetText()
210 to get the title of the play.
211
212 @until title );
213
214 Text is just another Node in the XML DOM. And in
215 fact you should be a little cautious with it, as
216 text nodes can contain elements.
217
218 @verbatim
219 Consider: A Midsummer Night's <b>Dream</b>
220 @endverbatim
221
222 It is more correct to actually query the Text Node
223 if in doubt:
224
225 @until title );
226
227 Noting that here we use FirstChild() since we are
228 looking for XMLText, not an element, and ToText()
229 is a cast from a Node to a XMLText.
230*/
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700231
232
Lee Thomason21be8822012-07-15 17:27:22 -0700233bool example_4()
234{
235 static const char* xml =
236 "<information>"
237 " <attributeApproach v='2' />"
238 " <textApproach>"
239 " <v>2</v>"
240 " </textApproach>"
241 "</information>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700242
Lee Thomason21be8822012-07-15 17:27:22 -0700243 XMLDocument doc;
244 doc.Parse( xml );
245
246 int v0 = 0;
247 int v1 = 0;
248
249 XMLElement* attributeApproachElement = doc.FirstChildElement()->FirstChildElement( "attributeApproach" );
250 attributeApproachElement->QueryIntAttribute( "v", &v0 );
251
252 XMLElement* textApproachElement = doc.FirstChildElement()->FirstChildElement( "textApproach" );
253 textApproachElement->FirstChildElement( "v" )->QueryIntText( &v1 );
254
255 printf( "Both values are the same: %d and %d\n", v0, v1 );
256
257 return !doc.Error() && ( v0 == v1 );
258}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200259/** @page Example-4 Read attributes and text information.
260 @dontinclude ./xmltest.cpp
261
262 There are fundamentally 2 ways of writing a key-value
263 pair into an XML file. (Something that's always annoyed
264 me about XML.) Either by using attributes, or by writing
265 the key name into an element and the value into
266 the text node wrapped by the element. Both approaches
267 are illustrated in this example, which shows two ways
268 to encode the value "2" into the key "v":
269
270 @skip example_4()
271 @until "</information>";
272
273 TinyXML-2 has accessors for both approaches.
274
275 When using an attribute, you navigate to the XMLElement
276 with that attribute and use the QueryIntAttribute()
277 group of methods. (Also QueryFloatAttribute(), etc.)
278
279 @skip XMLElement* attributeApproachElement
280 @until &v0 );
281
282 When using the text approach, you need to navigate
283 down one more step to the XMLElement that contains
284 the text. Note the extra FirstChildElement( "v" )
285 in the code below. The value of the text can then
286 be safely queried with the QueryIntText() group
287 of methods. (Also QueryFloatText(), etc.)
288
289 @skip XMLElement* textApproachElement
290 @until &v1 );
291*/
Lee Thomason21be8822012-07-15 17:27:22 -0700292
293
Lee Thomason178e4cc2013-01-25 16:19:05 -0800294int main( int argc, const char ** argv )
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800295{
Lee Thomason (grinliz)0a4df402012-02-27 20:50:52 -0800296 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason1ff38e02012-02-14 18:18:16 -0800297 _CrtMemCheckpoint( &startMemState );
Dmitry-Me99916592014-10-23 11:37:03 +0400298 // Enable MS Visual C++ debug heap memory leaks dump on exit
299 _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700300 #endif
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800301
Martinsh Shaiters39ddc262013-01-15 21:53:08 +0200302 #if defined(_MSC_VER) || defined(MINGW32) || defined(__MINGW32__)
ddiproiettoa8ae1f62013-05-05 18:42:52 +0300303 #if defined __MINGW64_VERSION_MAJOR && defined __MINGW64_VERSION_MINOR
304 //MINGW64: both 32 and 64-bit
305 mkdir( "resources/out/" );
306 #else
307 _mkdir( "resources/out/" );
308 #endif
Lee Thomasone9699e62012-07-25 12:24:23 -0700309 #else
310 mkdir( "resources/out/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
311 #endif
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400312
Dmitry-Me4bcbf142014-12-25 19:05:18 +0300313 {
314 TIXMLASSERT( true );
315 }
316
Lee Thomason178e4cc2013-01-25 16:19:05 -0800317 if ( argc > 1 ) {
318 XMLDocument* doc = new XMLDocument();
319 clock_t startTime = clock();
320 doc->LoadFile( argv[1] );
Anton Indrawan8a0006c2014-11-20 18:27:07 +0100321 clock_t loadTime = clock();
Lee Thomason178e4cc2013-01-25 16:19:05 -0800322 int errorID = doc->ErrorID();
323 delete doc; doc = 0;
Anton Indrawan8a0006c2014-11-20 18:27:07 +0100324 clock_t deleteTime = clock();
Lee Thomason178e4cc2013-01-25 16:19:05 -0800325
326 printf( "Test file '%s' loaded. ErrorID=%d\n", argv[1], errorID );
327 if ( !errorID ) {
Lee Thomason (grinliz)d6bd7362013-05-11 20:23:13 -0700328 printf( "Load time=%u\n", (unsigned)(loadTime - startTime) );
329 printf( "Delete time=%u\n", (unsigned)(deleteTime - loadTime) );
330 printf( "Total time=%u\n", (unsigned)(deleteTime - startTime) );
Lee Thomason178e4cc2013-01-25 16:19:05 -0800331 }
332 exit(0);
333 }
334
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300335 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason7f7b1622012-03-24 12:49:03 -0700336 if ( !fp ) {
337 printf( "Error opening test file 'dream.xml'.\n"
338 "Is your working directory the same as where \n"
339 "the xmltest.cpp and dream.xml file are?\n\n"
340 #if defined( _MSC_VER )
341 "In windows Visual Studio you may need to set\n"
342 "Properties->Debugging->Working Directory to '..'\n"
343 #endif
344 );
345 exit( 1 );
346 }
347 fclose( fp );
348
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700349 XMLTest( "Example-1", 0, example_1() );
350 XMLTest( "Example-2", 0, example_2() );
351 XMLTest( "Example-3", 0, example_3() );
Lee Thomason21be8822012-07-15 17:27:22 -0700352 XMLTest( "Example-4", true, example_4() );
Lee Thomason87e475a2012-03-20 11:55:29 -0700353
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700354 /* ------ Example 2: Lookup information. ---- */
Lee Thomason87e475a2012-03-20 11:55:29 -0700355
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800356 {
Lee Thomason43f59302012-02-06 18:18:11 -0800357 static const char* test[] = { "<element />",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400358 "<element></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800359 "<element><subelement/></element>",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400360 "<element><subelement></subelement></element>",
361 "<element><subelement><subsub/></subelement></element>",
362 "<!--comment beside elements--><element><subelement></subelement></element>",
363 "<!--comment beside elements, this time with spaces--> \n <element> <subelement> \n </subelement> </element>",
364 "<element attrib1='foo' attrib2=\"bar\" ></element>",
365 "<element attrib1='foo' attrib2=\"bar\" ><subelement attrib3='yeehaa' /></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800366 "<element>Text inside element.</element>",
367 "<element><b></b></element>",
368 "<element>Text inside and <b>bolded</b> in the element.</element>",
369 "<outer><element>Text inside and <b>bolded</b> in the element.</element></outer>",
Lee Thomason8ee79892012-01-25 17:44:30 -0800370 "<element>This &amp; That.</element>",
Lee Thomason18d68bd2012-01-26 18:17:26 -0800371 "<element attrib='This&lt;That' />",
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800372 0
373 };
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800374 for( int i=0; test[i]; ++i ) {
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800375 XMLDocument doc;
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800376 doc.Parse( test[i] );
Lee Thomason5cae8972012-01-24 18:03:07 -0800377 doc.Print();
Lee Thomasonec975ce2012-01-23 11:42:06 -0800378 printf( "----------------------------------------------\n" );
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800379 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800380 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800381#if 1
Lee Thomasond6277762012-02-22 16:00:12 -0800382 {
383 static const char* test = "<!--hello world\n"
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400384 " line 2\r"
385 " line 3\r\n"
386 " line 4\n\r"
387 " line 5\r-->";
Lee Thomasond6277762012-02-22 16:00:12 -0800388
389 XMLDocument doc;
390 doc.Parse( test );
391 doc.Print();
392 }
393
Lee Thomason2c85a712012-01-31 08:24:24 -0800394 {
395 static const char* test = "<element>Text before.</element>";
396 XMLDocument doc;
397 doc.Parse( test );
398 XMLElement* root = doc.FirstChildElement();
399 XMLElement* newElement = doc.NewElement( "Subelement" );
400 root->InsertEndChild( newElement );
401 doc.Print();
402 }
Lee Thomasond1983222012-02-06 08:41:24 -0800403 {
404 XMLDocument* doc = new XMLDocument();
405 static const char* test = "<element><sub/></element>";
406 doc->Parse( test );
407 delete doc;
408 }
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800409 {
Lee Thomason1ff38e02012-02-14 18:18:16 -0800410 // Test: Programmatic DOM
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800411 // Build:
412 // <element>
413 // <!--comment-->
414 // <sub attrib="1" />
415 // <sub attrib="2" />
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800416 // <sub attrib="3" >& Text!</sub>
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800417 // <element>
418
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800419 XMLDocument* doc = new XMLDocument();
Lee Thomason1ff38e02012-02-14 18:18:16 -0800420 XMLNode* element = doc->InsertEndChild( doc->NewElement( "element" ) );
421
422 XMLElement* sub[3] = { doc->NewElement( "sub" ), doc->NewElement( "sub" ), doc->NewElement( "sub" ) };
423 for( int i=0; i<3; ++i ) {
424 sub[i]->SetAttribute( "attrib", i );
425 }
426 element->InsertEndChild( sub[2] );
427 XMLNode* comment = element->InsertFirstChild( doc->NewComment( "comment" ) );
Lee Thomasonaf9bce12016-07-17 22:35:52 -0700428 comment->SetUserData((void*)2);
Lee Thomason1ff38e02012-02-14 18:18:16 -0800429 element->InsertAfterChild( comment, sub[0] );
430 element->InsertAfterChild( sub[0], sub[1] );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800431 sub[2]->InsertFirstChild( doc->NewText( "& Text!" ));
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800432 doc->Print();
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800433 XMLTest( "Programmatic DOM", "comment", doc->FirstChildElement( "element" )->FirstChild()->Value() );
434 XMLTest( "Programmatic DOM", "0", doc->FirstChildElement( "element" )->FirstChildElement()->Attribute( "attrib" ) );
435 XMLTest( "Programmatic DOM", 2, doc->FirstChildElement()->LastChildElement( "sub" )->IntAttribute( "attrib" ) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700436 XMLTest( "Programmatic DOM", "& Text!",
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800437 doc->FirstChildElement()->LastChildElement( "sub" )->FirstChild()->ToText()->Value() );
Lee Thomasonc9445462016-07-17 22:53:48 -0700438 XMLTest("User data", (void*)2 == comment->GetUserData(), true, false);
U-Stream\Leeae25a442012-02-17 17:48:16 -0800439
440 // And now deletion:
441 element->DeleteChild( sub[2] );
442 doc->DeleteNode( comment );
443
444 element->FirstChildElement()->SetAttribute( "attrib", true );
445 element->LastChildElement()->DeleteAttribute( "attrib" );
446
447 XMLTest( "Programmatic DOM", true, doc->FirstChildElement()->FirstChildElement()->BoolAttribute( "attrib" ) );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700448 int value1 = 10;
449 int value2 = doc->FirstChildElement()->LastChildElement()->IntAttribute( "attrib", 10 );
450 int result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value1 );
Lee Thomason21be8822012-07-15 17:27:22 -0700451 XMLTest( "Programmatic DOM", result, (int)XML_NO_ATTRIBUTE );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700452 XMLTest( "Programmatic DOM", value1, 10 );
453 XMLTest( "Programmatic DOM", value2, 10 );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800454
455 doc->Print();
456
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700457 {
458 XMLPrinter streamer;
459 doc->Print( &streamer );
460 printf( "%s", streamer.CStr() );
461 }
462 {
463 XMLPrinter streamer( 0, true );
464 doc->Print( &streamer );
Doruk Turak1f212f32016-08-28 20:54:17 +0200465 XMLTest( "Compact mode", "<element><sub attrib=\"true\"/><sub/></element>", streamer.CStr(), false );
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700466 }
Lee Thomason (grinliz)6b8b0122012-09-08 21:21:00 -0700467 doc->SaveFile( "./resources/out/pretty.xml" );
468 doc->SaveFile( "./resources/out/compact.xml", true );
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800469 delete doc;
470 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800471 {
472 // Test: Dream
473 // XML1 : 1,187,569 bytes in 31,209 allocations
474 // XML2 : 469,073 bytes in 323 allocations
475 //int newStart = gNew;
476 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300477 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800478
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400479 doc.SaveFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800480 doc.PrintError();
481
482 XMLTest( "Dream", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400483 doc.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800484 XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false );
485 XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
486 doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
487 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400488 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800489 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400490 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800491
492 XMLDocument doc2;
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400493 doc2.LoadFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800494 XMLTest( "Dream-out", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400495 doc2.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800496 XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false );
497 XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
498 doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
499 XMLTest( "Dream-out", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400500 doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800501
502 //gNewTotal = gNew - newStart;
503 }
Lee Thomason6f381b72012-03-02 12:59:39 -0800504
505
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800506 {
507 const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
508 "<passages count=\"006\" formatversion=\"20020620\">\n"
509 " <wrong error>\n"
510 "</passages>";
511
512 XMLDocument doc;
513 doc.Parse( error );
Lee Thomason2fa81722012-11-09 12:37:46 -0800514 XMLTest( "Bad XML", doc.ErrorID(), XML_ERROR_PARSING_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800515 }
516
517 {
518 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
519
520 XMLDocument doc;
521 doc.Parse( str );
522
523 XMLElement* ele = doc.FirstChildElement();
524
525 int iVal, result;
526 double dVal;
527
528 result = ele->QueryDoubleAttribute( "attr0", &dVal );
Lee Thomason85536252016-06-04 19:10:53 -0700529 XMLTest( "Query attribute: int as double", result, (int)XML_SUCCESS);
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800530 XMLTest( "Query attribute: int as double", (int)dVal, 1 );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700531 XMLTest( "Query attribute: int as double", (int)ele->DoubleAttribute("attr0"), 1);
532
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800533 result = ele->QueryDoubleAttribute( "attr1", &dVal );
Lee Thomason85536252016-06-04 19:10:53 -0700534 XMLTest( "Query attribute: double as double", result, (int)XML_SUCCESS);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700535 XMLTest( "Query attribute: double as double", dVal, 2.0 );
536 XMLTest( "Query attribute: double as double", ele->DoubleAttribute("attr1"), 2.0 );
537
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800538 result = ele->QueryIntAttribute( "attr1", &iVal );
Lee Thomason85536252016-06-04 19:10:53 -0700539 XMLTest( "Query attribute: double as int", result, (int)XML_SUCCESS);
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800540 XMLTest( "Query attribute: double as int", iVal, 2 );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700541
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800542 result = ele->QueryIntAttribute( "attr2", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700543 XMLTest( "Query attribute: not a number", result, (int)XML_WRONG_ATTRIBUTE_TYPE );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700544 XMLTest( "Query attribute: not a number", ele->DoubleAttribute("attr2", 4.0), 4.0 );
545
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800546 result = ele->QueryIntAttribute( "bar", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700547 XMLTest( "Query attribute: does not exist", result, (int)XML_NO_ATTRIBUTE );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700548 XMLTest( "Query attribute: does not exist", ele->BoolAttribute("bar", true), true );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800549 }
550
551 {
552 const char* str = "<doc/>";
553
554 XMLDocument doc;
555 doc.Parse( str );
556
557 XMLElement* ele = doc.FirstChildElement();
558
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800559 int iVal, iVal2;
560 double dVal, dVal2;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800561
562 ele->SetAttribute( "str", "strValue" );
563 ele->SetAttribute( "int", 1 );
564 ele->SetAttribute( "double", -1.0 );
565
566 const char* cStr = ele->Attribute( "str" );
567 ele->QueryIntAttribute( "int", &iVal );
568 ele->QueryDoubleAttribute( "double", &dVal );
569
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800570 ele->QueryAttribute( "int", &iVal2 );
571 ele->QueryAttribute( "double", &dVal2 );
572
Lee Thomason8ba7f7d2012-03-24 13:04:04 -0700573 XMLTest( "Attribute match test", ele->Attribute( "str", "strValue" ), "strValue" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800574 XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
575 XMLTest( "Attribute round trip. int.", 1, iVal );
576 XMLTest( "Attribute round trip. double.", -1, (int)dVal );
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800577 XMLTest( "Alternate query", true, iVal == iVal2 );
578 XMLTest( "Alternate query", true, dVal == dVal2 );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700579 XMLTest( "Alternate query", true, iVal == ele->IntAttribute("int") );
580 XMLTest( "Alternate query", true, dVal == ele->DoubleAttribute("double") );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800581 }
582
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800583 {
584 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300585 doc.LoadFile( "resources/utf8test.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800586
587 // Get the attribute "value" from the "Russian" element and check it.
588 XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700589 const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800590 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
591
592 XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
593
594 const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U,
595 0xd1U, 0x81U, 0xd1U, 0x81U,
596 0xd0U, 0xbaU, 0xd0U, 0xb8U,
597 0xd0U, 0xb9U, 0 };
598 const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
599
600 XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
601 XMLTest( "UTF-8: Browsing russian element name.",
602 russianText,
603 text->Value() );
604
605 // Now try for a round trip.
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400606 doc.SaveFile( "resources/out/utf8testout.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800607
608 // Check the round trip.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800609 int okay = 0;
610
Thomas Roßa6dd8c62012-07-26 20:42:18 +0200611 FILE* saved = fopen( "resources/out/utf8testout.xml", "r" );
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300612 FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800613
614 if ( saved && verify )
615 {
616 okay = 1;
PKEuSc28ba3a2012-07-16 03:08:47 -0700617 char verifyBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800618 while ( fgets( verifyBuf, 256, verify ) )
619 {
PKEuSc28ba3a2012-07-16 03:08:47 -0700620 char savedBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800621 fgets( savedBuf, 256, saved );
622 NullLineEndings( verifyBuf );
623 NullLineEndings( savedBuf );
624
625 if ( strcmp( verifyBuf, savedBuf ) )
626 {
627 printf( "verify:%s<\n", verifyBuf );
628 printf( "saved :%s<\n", savedBuf );
629 okay = 0;
630 break;
631 }
632 }
633 }
634 if ( saved )
635 fclose( saved );
636 if ( verify )
637 fclose( verify );
638 XMLTest( "UTF-8: Verified multi-language round trip.", 1, okay );
639 }
640
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800641 // --------GetText()-----------
642 {
643 const char* str = "<foo>This is text</foo>";
644 XMLDocument doc;
645 doc.Parse( str );
646 const XMLElement* element = doc.RootElement();
647
648 XMLTest( "GetText() normal use.", "This is text", element->GetText() );
649
650 str = "<foo><b>This is text</b></foo>";
651 doc.Parse( str );
652 element = doc.RootElement();
653
654 XMLTest( "GetText() contained element.", element->GetText() == 0, true );
655 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800656
Lee Thomasond6277762012-02-22 16:00:12 -0800657
Uli Kusterer321072e2014-01-21 01:57:38 +0100658 // --------SetText()-----------
659 {
660 const char* str = "<foo></foo>";
661 XMLDocument doc;
662 doc.Parse( str );
663 XMLElement* element = doc.RootElement();
664
Lee Thomason9c0678a2014-01-24 10:18:27 -0800665 element->SetText("darkness.");
666 XMLTest( "SetText() normal use (open/close).", "darkness.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100667
Lee Thomason9c0678a2014-01-24 10:18:27 -0800668 element->SetText("blue flame.");
669 XMLTest( "SetText() replace.", "blue flame.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100670
671 str = "<foo/>";
672 doc.Parse( str );
673 element = doc.RootElement();
674
Lee Thomason9c0678a2014-01-24 10:18:27 -0800675 element->SetText("The driver");
676 XMLTest( "SetText() normal use. (self-closing)", "The driver", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100677
Lee Thomason9c0678a2014-01-24 10:18:27 -0800678 element->SetText("<b>horses</b>");
679 XMLTest( "SetText() replace with tag-like text.", "<b>horses</b>", element->GetText() );
680 //doc.Print();
Uli Kusterer321072e2014-01-21 01:57:38 +0100681
682 str = "<foo><bar>Text in nested element</bar></foo>";
683 doc.Parse( str );
684 element = doc.RootElement();
685
Lee Thomason9c0678a2014-01-24 10:18:27 -0800686 element->SetText("wolves");
687 XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800688
689 str = "<foo/>";
690 doc.Parse( str );
691 element = doc.RootElement();
692
693 element->SetText( "str" );
694 XMLTest( "SetText types", "str", element->GetText() );
695
696 element->SetText( 1 );
697 XMLTest( "SetText types", "1", element->GetText() );
698
699 element->SetText( 1U );
700 XMLTest( "SetText types", "1", element->GetText() );
701
702 element->SetText( true );
Doruk Turak1f212f32016-08-28 20:54:17 +0200703 XMLTest( "SetText types", "true", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800704
705 element->SetText( 1.5f );
706 XMLTest( "SetText types", "1.5", element->GetText() );
707
708 element->SetText( 1.5 );
709 XMLTest( "SetText types", "1.5", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100710 }
711
Lee Thomason51c12712016-06-04 20:18:49 -0700712 // ---------- Attributes ---------
713 {
714 static const int64_t BIG = -123456789012345678;
715 XMLDocument doc;
716 XMLElement* element = doc.NewElement("element");
717 doc.InsertFirstChild(element);
718
719 {
720 element->SetAttribute("attrib", int(-100));
721 int v = 0;
722 element->QueryIntAttribute("attrib", &v);
723 XMLTest("Attribute: int", -100, v, true);
724 element->QueryAttribute("attrib", &v);
725 XMLTest("Attribute: int", -100, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700726 XMLTest("Attribute: int", -100, element->IntAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700727 }
728 {
729 element->SetAttribute("attrib", unsigned(100));
730 unsigned v = 0;
731 element->QueryUnsignedAttribute("attrib", &v);
732 XMLTest("Attribute: unsigned", unsigned(100), v, true);
733 element->QueryAttribute("attrib", &v);
734 XMLTest("Attribute: unsigned", unsigned(100), v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700735 XMLTest("Attribute: unsigned", unsigned(100), element->UnsignedAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700736 }
737 {
738 element->SetAttribute("attrib", BIG);
739 int64_t v = 0;
740 element->QueryInt64Attribute("attrib", &v);
741 XMLTest("Attribute: int64_t", BIG, v, true);
742 element->QueryAttribute("attrib", &v);
743 XMLTest("Attribute: int64_t", BIG, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700744 XMLTest("Attribute: int64_t", BIG, element->Int64Attribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700745 }
746 {
747 element->SetAttribute("attrib", true);
748 bool v = false;
749 element->QueryBoolAttribute("attrib", &v);
750 XMLTest("Attribute: bool", true, v, true);
751 element->QueryAttribute("attrib", &v);
752 XMLTest("Attribute: bool", true, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700753 XMLTest("Attribute: bool", true, element->BoolAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700754 }
755 {
756 element->SetAttribute("attrib", 100.0);
757 double v = 0;
758 element->QueryDoubleAttribute("attrib", &v);
759 XMLTest("Attribute: double", 100.0, v, true);
760 element->QueryAttribute("attrib", &v);
761 XMLTest("Attribute: double", 100.0, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700762 XMLTest("Attribute: double", 100.0, element->DoubleAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700763 }
764 {
765 element->SetAttribute("attrib", 100.0f);
766 float v = 0;
767 element->QueryFloatAttribute("attrib", &v);
768 XMLTest("Attribute: float", 100.0f, v, true);
769 element->QueryAttribute("attrib", &v);
770 XMLTest("Attribute: float", 100.0f, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700771 XMLTest("Attribute: float", 100.0f, element->FloatAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700772 }
773 {
774 element->SetText(BIG);
775 int64_t v = 0;
776 element->QueryInt64Text(&v);
777 XMLTest("Element: int64_t", BIG, v, true);
778 }
779 }
780
781 // ---------- XMLPrinter stream mode ------
782 {
783 {
784 FILE* printerfp = fopen("resources/printer.xml", "w");
785 XMLPrinter printer(printerfp);
786 printer.OpenElement("foo");
787 printer.PushAttribute("attrib-text", "text");
788 printer.PushAttribute("attrib-int", int(1));
789 printer.PushAttribute("attrib-unsigned", unsigned(2));
790 printer.PushAttribute("attrib-int64", int64_t(3));
791 printer.PushAttribute("attrib-bool", true);
792 printer.PushAttribute("attrib-double", 4.0);
793 printer.CloseElement();
794 fclose(printerfp);
795 }
796 {
797 XMLDocument doc;
798 doc.LoadFile("resources/printer.xml");
799 XMLTest("XMLPrinter Stream mode: load", doc.ErrorID(), XML_SUCCESS, true);
800
801 const XMLDocument& cdoc = doc;
802
803 const XMLAttribute* attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-text");
804 XMLTest("attrib-text", "text", attrib->Value(), true);
805 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int");
806 XMLTest("attrib-int", int(1), attrib->IntValue(), true);
807 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-unsigned");
808 XMLTest("attrib-unsigned", unsigned(2), attrib->UnsignedValue(), true);
809 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int64");
810 XMLTest("attrib-int64", int64_t(3), attrib->Int64Value(), true);
811 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-bool");
812 XMLTest("attrib-bool", true, attrib->BoolValue(), true);
813 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-double");
814 XMLTest("attrib-double", 4.0, attrib->DoubleValue(), true);
815 }
816
817 }
818
Uli Kusterer321072e2014-01-21 01:57:38 +0100819
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800820 // ---------- CDATA ---------------
821 {
822 const char* str = "<xmlElement>"
823 "<![CDATA["
824 "I am > the rules!\n"
825 "...since I make symbolic puns"
826 "]]>"
827 "</xmlElement>";
828 XMLDocument doc;
829 doc.Parse( str );
830 doc.Print();
Lee Thomasond6277762012-02-22 16:00:12 -0800831
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700832 XMLTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800833 "I am > the rules!\n...since I make symbolic puns",
Lee Thomasond6277762012-02-22 16:00:12 -0800834 false );
835 }
836
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800837 // ----------- CDATA -------------
838 {
839 const char* str = "<xmlElement>"
840 "<![CDATA["
841 "<b>I am > the rules!</b>\n"
842 "...since I make symbolic puns"
843 "]]>"
844 "</xmlElement>";
845 XMLDocument doc;
846 doc.Parse( str );
847 doc.Print();
848
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700849 XMLTest( "CDATA parse. [ tixml1:1480107 ]", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800850 "<b>I am > the rules!</b>\n...since I make symbolic puns",
851 false );
852 }
853
854 // InsertAfterChild causes crash.
855 {
856 // InsertBeforeChild and InsertAfterChild causes crash.
857 XMLDocument doc;
858 XMLElement* parent = doc.NewElement( "Parent" );
859 doc.InsertFirstChild( parent );
860
861 XMLElement* childText0 = doc.NewElement( "childText0" );
862 XMLElement* childText1 = doc.NewElement( "childText1" );
863
864 XMLNode* childNode0 = parent->InsertEndChild( childText0 );
865 XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
866
867 XMLTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent->LastChild() ), true );
868 }
Lee Thomasond6277762012-02-22 16:00:12 -0800869
870 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800871 // Entities not being written correctly.
872 // From Lynn Allen
Lee Thomasond6277762012-02-22 16:00:12 -0800873
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800874 const char* passages =
875 "<?xml version=\"1.0\" standalone=\"no\" ?>"
876 "<passages count=\"006\" formatversion=\"20020620\">"
877 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
878 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
879 "</passages>";
Lee Thomasond6277762012-02-22 16:00:12 -0800880
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800881 XMLDocument doc;
882 doc.Parse( passages );
883 XMLElement* psg = doc.RootElement()->FirstChildElement();
884 const char* context = psg->Attribute( "context" );
885 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 -0800886
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800887 XMLTest( "Entity transformation: read. ", expected, context, true );
Lee Thomasond6277762012-02-22 16:00:12 -0800888
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400889 FILE* textfile = fopen( "resources/out/textfile.txt", "w" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800890 if ( textfile )
891 {
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800892 XMLPrinter streamer( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800893 psg->Accept( &streamer );
894 fclose( textfile );
895 }
Thomas Roß0922b732012-09-23 16:31:22 +0200896
897 textfile = fopen( "resources/out/textfile.txt", "r" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800898 TIXMLASSERT( textfile );
899 if ( textfile )
900 {
901 char buf[ 1024 ];
902 fgets( buf, 1024, textfile );
903 XMLTest( "Entity transformation: write. ",
904 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
905 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
906 buf, false );
PKEuSc28ba3a2012-07-16 03:08:47 -0700907 fclose( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800908 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800909 }
910
911 {
Lee Thomason6f381b72012-03-02 12:59:39 -0800912 // Suppress entities.
913 const char* passages =
914 "<?xml version=\"1.0\" standalone=\"no\" ?>"
915 "<passages count=\"006\" formatversion=\"20020620\">"
916 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
917 "</passages>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700918
Lee Thomason6f381b72012-03-02 12:59:39 -0800919 XMLDocument doc( false );
920 doc.Parse( passages );
921
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700922 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ),
Lee Thomason6f381b72012-03-02 12:59:39 -0800923 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;." );
924 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value(),
925 "Crazy &ttk;" );
926 doc.Print();
927 }
928
929 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400930 const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800931
932 XMLDocument doc;
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400933 doc.Parse( test );
934 XMLTest( "dot in names", doc.Error(), false );
935 XMLTest( "dot in names", doc.FirstChildElement()->Name(), "a.elem" );
936 XMLTest( "dot in names", doc.FirstChildElement()->Attribute( "xmi.version" ), "2.0" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800937 }
938
939 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400940 const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800941
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400942 XMLDocument doc;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800943 doc.Parse( test );
944
945 XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
946 XMLTest( "Entity with one digit.",
947 text->Value(), "1.1 Start easy ignore fin thickness\n",
948 false );
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400949 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800950
951 {
952 // DOCTYPE not preserved (950171)
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700953 //
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800954 const char* doctype =
955 "<?xml version=\"1.0\" ?>"
956 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
957 "<!ELEMENT title (#PCDATA)>"
958 "<!ELEMENT books (title,authors)>"
959 "<element />";
960
961 XMLDocument doc;
962 doc.Parse( doctype );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400963 doc.SaveFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800964 doc.DeleteChild( doc.RootElement() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400965 doc.LoadFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800966 doc.Print();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700967
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800968 const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
969 XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
970
971 }
972
973 {
974 // Comments do not stream out correctly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700975 const char* doctype =
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800976 "<!-- Somewhat<evil> -->";
977 XMLDocument doc;
978 doc.Parse( doctype );
979
980 XMLComment* comment = doc.FirstChild()->ToComment();
981
982 XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
983 }
984 {
985 // Double attributes
986 const char* doctype = "<element attr='red' attr='blue' />";
987
988 XMLDocument doc;
989 doc.Parse( doctype );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700990
Lee Thomason2fa81722012-11-09 12:37:46 -0800991 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 -0800992 doc.PrintError();
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800993 }
994
995 {
996 // Embedded null in stream.
997 const char* doctype = "<element att\0r='red' attr='blue' />";
998
999 XMLDocument doc;
1000 doc.Parse( doctype );
1001 XMLTest( "Embedded null throws error.", true, doc.Error() );
1002 }
1003
1004 {
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -07001005 // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
Dmitry-Me588bb8d2014-12-25 18:59:18 +03001006 const char* str = "";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001007 XMLDocument doc;
1008 doc.Parse( str );
Lee Thomason2fa81722012-11-09 12:37:46 -08001009 XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001010 }
1011
1012 {
Dmitry-Me588bb8d2014-12-25 18:59:18 +03001013 // Documents with all whitespaces should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
1014 const char* str = " ";
1015 XMLDocument doc;
1016 doc.Parse( str );
1017 XMLTest( "All whitespaces document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
1018 }
1019
1020 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001021 // Low entities
1022 XMLDocument doc;
1023 doc.Parse( "<test>&#x0e;</test>" );
1024 const char result[] = { 0x0e, 0 };
1025 XMLTest( "Low entities.", doc.FirstChildElement()->GetText(), result );
1026 doc.Print();
1027 }
1028
1029 {
1030 // Attribute values with trailing quotes not handled correctly
1031 XMLDocument doc;
1032 doc.Parse( "<foo attribute=bar\" />" );
1033 XMLTest( "Throw error with bad end quotes.", doc.Error(), true );
1034 }
1035
1036 {
1037 // [ 1663758 ] Failure to report error on bad XML
1038 XMLDocument xml;
1039 xml.Parse("<x>");
1040 XMLTest("Missing end tag at end of input", xml.Error(), true);
1041 xml.Parse("<x> ");
1042 XMLTest("Missing end tag with trailing whitespace", xml.Error(), true);
1043 xml.Parse("<x></y>");
Lee Thomason2fa81722012-11-09 12:37:46 -08001044 XMLTest("Mismatched tags", xml.ErrorID(), XML_ERROR_MISMATCHED_ELEMENT);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001045 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001046
1047
1048 {
1049 // [ 1475201 ] TinyXML parses entities in comments
1050 XMLDocument xml;
1051 xml.Parse("<!-- declarations for <head> & <body> -->"
1052 "<!-- far &amp; away -->" );
1053
1054 XMLNode* e0 = xml.FirstChild();
1055 XMLNode* e1 = e0->NextSibling();
1056 XMLComment* c0 = e0->ToComment();
1057 XMLComment* c1 = e1->ToComment();
1058
1059 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
1060 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
1061 }
1062
1063 {
1064 XMLDocument xml;
1065 xml.Parse( "<Parent>"
1066 "<child1 att=''/>"
1067 "<!-- With this comment, child2 will not be parsed! -->"
1068 "<child2 att=''/>"
1069 "</Parent>" );
1070 xml.Print();
1071
1072 int count = 0;
1073
1074 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
1075 ele;
1076 ele = ele->NextSibling() )
1077 {
1078 ++count;
1079 }
1080
1081 XMLTest( "Comments iterate correctly.", 3, count );
1082 }
1083
1084 {
1085 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
1086 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
1087 buf[60] = 239;
1088 buf[61] = 0;
1089
1090 XMLDocument doc;
1091 doc.Parse( (const char*)buf);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001092 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001093
1094
1095 {
1096 // bug 1827248 Error while parsing a little bit malformed file
1097 // Actually not malformed - should work.
1098 XMLDocument xml;
1099 xml.Parse( "<attributelist> </attributelist >" );
1100 XMLTest( "Handle end tag whitespace", false, xml.Error() );
1101 }
1102
1103 {
1104 // This one must not result in an infinite loop
1105 XMLDocument xml;
1106 xml.Parse( "<infinite>loop" );
1107 XMLTest( "Infinite loop test.", true, true );
1108 }
1109#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001110 {
1111 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
1112 XMLDocument doc;
1113 doc.Parse( pub );
1114
1115 XMLDocument clone;
1116 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
1117 XMLNode* copy = node->ShallowClone( &clone );
1118 clone.InsertEndChild( copy );
1119 }
1120
1121 clone.Print();
1122
1123 int count=0;
1124 const XMLNode* a=clone.FirstChild();
1125 const XMLNode* b=doc.FirstChild();
1126 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
1127 ++count;
1128 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
1129 }
1130 XMLTest( "Clone and Equal", 4, count );
1131 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001132
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001133 {
1134 // This shouldn't crash.
1135 XMLDocument doc;
Lee Thomason85536252016-06-04 19:10:53 -07001136 if(XML_SUCCESS != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001137 {
1138 doc.PrintError();
1139 }
1140 XMLTest( "Error in snprinf handling.", true, doc.Error() );
1141 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001142
Lee Thomason5e3803c2012-04-16 08:57:05 -07001143 {
1144 // Attribute ordering.
1145 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
1146 XMLDocument doc;
1147 doc.Parse( xml );
1148 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001149
Lee Thomason5e3803c2012-04-16 08:57:05 -07001150 const XMLAttribute* a = ele->FirstAttribute();
1151 XMLTest( "Attribute order", "1", a->Value() );
1152 a = a->Next();
1153 XMLTest( "Attribute order", "2", a->Value() );
1154 a = a->Next();
1155 XMLTest( "Attribute order", "3", a->Value() );
1156 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001157
Lee Thomason5e3803c2012-04-16 08:57:05 -07001158 ele->DeleteAttribute( "attrib2" );
1159 a = ele->FirstAttribute();
1160 XMLTest( "Attribute order", "1", a->Value() );
1161 a = a->Next();
1162 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001163
Lee Thomason5e3803c2012-04-16 08:57:05 -07001164 ele->DeleteAttribute( "attrib1" );
1165 ele->DeleteAttribute( "attrib3" );
1166 XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
1167 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001168
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001169 {
1170 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -07001171 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
1172 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
1173 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
1174 XMLDocument doc0;
1175 doc0.Parse( xml0 );
1176 XMLDocument doc1;
1177 doc1.Parse( xml1 );
1178 XMLDocument doc2;
1179 doc2.Parse( xml2 );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001180
Lee Thomason78a773d2012-07-02 10:10:19 -07001181 XMLElement* ele = 0;
1182 ele = doc0.FirstChildElement();
1183 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
1184 ele = doc1.FirstChildElement();
1185 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
1186 ele = doc2.FirstChildElement();
1187 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001188 }
1189
1190 {
1191 // Make sure we don't go into an infinite loop.
1192 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
1193 XMLDocument doc;
1194 doc.Parse( xml );
1195 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
1196 XMLElement* ele1 = ele0->NextSiblingElement();
1197 bool equal = ele0->ShallowEqual( ele1 );
1198
1199 XMLTest( "Infinite loop in shallow equal.", true, equal );
1200 }
1201
Lee Thomason5708f812012-03-28 17:46:41 -07001202 // -------- Handles ------------
1203 {
1204 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1205 XMLDocument doc;
1206 doc.Parse( xml );
Lee Thomason5708f812012-03-28 17:46:41 -07001207
1208 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
1209 XMLTest( "Handle, success, mutable", ele->Value(), "sub" );
1210
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001211 XMLHandle docH( doc );
1212 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001213 XMLTest( "Handle, dne, mutable", false, ele != 0 );
Lee Thomason5708f812012-03-28 17:46:41 -07001214 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001215
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001216 {
1217 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1218 XMLDocument doc;
1219 doc.Parse( xml );
1220 XMLConstHandle docH( doc );
1221
1222 const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
1223 XMLTest( "Handle, success, const", ele->Value(), "sub" );
1224
1225 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001226 XMLTest( "Handle, dne, const", false, ele != 0 );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001227 }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001228 {
1229 // Default Declaration & BOM
1230 XMLDocument doc;
1231 doc.InsertEndChild( doc.NewDeclaration() );
1232 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001233
Lee Thomasonf68c4382012-04-28 14:37:11 -07001234 XMLPrinter printer;
1235 doc.Print( &printer );
1236
1237 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1238 XMLTest( "BOM and default declaration", printer.CStr(), result, false );
Lee Thomason (grinliz)48ea0bc2012-05-26 14:41:14 -07001239 XMLTest( "CStrSize", printer.CStrSize(), 42, false );
Lee Thomasonf68c4382012-04-28 14:37:11 -07001240 }
Lee Thomason21be8822012-07-15 17:27:22 -07001241 {
1242 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1243 XMLDocument doc;
1244 doc.Parse( xml );
1245 XMLTest( "Ill formed XML", true, doc.Error() );
1246 }
1247
1248 // QueryXYZText
1249 {
1250 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1251 XMLDocument doc;
1252 doc.Parse( xml );
1253
1254 const XMLElement* pointElement = doc.RootElement();
1255
1256 int intValue = 0;
1257 unsigned unsignedValue = 0;
1258 float floatValue = 0;
1259 double doubleValue = 0;
1260 bool boolValue = false;
1261
1262 pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1263 pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1264 pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1265 pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1266 pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1267
1268
1269 XMLTest( "QueryIntText", intValue, 1, false );
1270 XMLTest( "QueryUnsignedText", unsignedValue, (unsigned)1, false );
1271 XMLTest( "QueryFloatText", floatValue, 1.2f, false );
1272 XMLTest( "QueryDoubleText", doubleValue, 1.2, false );
1273 XMLTest( "QueryBoolText", boolValue, true, false );
1274 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001275
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001276 {
1277 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1278 XMLDocument doc;
1279 doc.Parse( xml );
1280 XMLTest( "Non-alpha element lead letter parses.", doc.Error(), false );
1281 }
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001282
1283 {
1284 const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1285 XMLDocument doc;
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001286 doc.Parse( xml );
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001287 XMLTest("Non-alpha attribute lead character parses.", doc.Error(), false);
1288 }
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001289
1290 {
1291 const char* xml = "<3lement></3lement>";
1292 XMLDocument doc;
1293 doc.Parse( xml );
1294 XMLTest("Element names with lead digit fail to parse.", doc.Error(), true);
1295 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -07001296
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001297 {
1298 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1299 XMLDocument doc;
1300 doc.Parse( xml, 10 );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001301 XMLTest( "Set length of incoming data", doc.Error(), false );
1302 }
1303
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001304 {
1305 XMLDocument doc;
Dmitry-Me48b5df02015-04-06 18:20:25 +03001306 XMLTest( "Document is initially empty", doc.NoChildren(), true );
1307 doc.Clear();
1308 XMLTest( "Empty is empty after Clear()", doc.NoChildren(), true );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001309 doc.LoadFile( "resources/dream.xml" );
Dmitry-Meaaa4cea2015-02-06 16:00:46 +03001310 XMLTest( "Document has something to Clear()", doc.NoChildren(), false );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001311 doc.Clear();
1312 XMLTest( "Document Clear()'s", doc.NoChildren(), true );
1313 }
1314
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001315 // ----------- Whitespace ------------
1316 {
1317 const char* xml = "<element>"
1318 "<a> This \nis &apos; text &apos; </a>"
1319 "<b> This is &apos; text &apos; \n</b>"
1320 "<c>This is &apos; \n\n text &apos;</c>"
1321 "</element>";
1322 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1323 doc.Parse( xml );
1324
1325 const XMLElement* element = doc.FirstChildElement();
1326 for( const XMLElement* parent = element->FirstChildElement();
1327 parent;
1328 parent = parent->NextSiblingElement() )
1329 {
1330 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1331 }
1332 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001333
Lee Thomasonae9ab072012-10-24 10:17:53 -07001334#if 0
1335 {
1336 // Passes if assert doesn't fire.
1337 XMLDocument xmlDoc;
1338
1339 xmlDoc.NewDeclaration();
1340 xmlDoc.NewComment("Configuration file");
1341
1342 XMLElement *root = xmlDoc.NewElement("settings");
1343 root->SetAttribute("version", 2);
1344 }
1345#endif
1346
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001347 {
1348 const char* xml = "<element> </element>";
1349 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1350 doc.Parse( xml );
1351 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1352 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001353
Lee Thomason5b0a6772012-11-19 13:54:42 -08001354 {
1355 // An assert should not fire.
1356 const char* xml = "<element/>";
1357 XMLDocument doc;
1358 doc.Parse( xml );
1359 XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope.
1360 XMLTest( "Tracking unused elements", true, ele != 0, false );
1361 }
1362
Lee Thomasona6412ac2012-12-13 15:39:11 -08001363
1364 {
1365 const char* xml = "<parent><child>abc</child></parent>";
1366 XMLDocument doc;
1367 doc.Parse( xml );
1368 XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
1369
1370 XMLPrinter printer;
1371 ele->Accept( &printer );
1372 XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1373 }
1374
1375
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001376 {
1377 XMLDocument doc;
1378 XMLError error = doc.LoadFile( "resources/empty.xml" );
1379 XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
Lee Thomason331596e2014-09-11 14:56:43 -07001380 XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() );
Lee Thomasonc7556672014-09-14 12:39:42 -07001381 doc.PrintError();
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001382 }
1383
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001384 {
1385 // BOM preservation
1386 static const char* xml_bom_preservation = "\xef\xbb\xbf<element/>\n";
1387 {
1388 XMLDocument doc;
Lee Thomason85536252016-06-04 19:10:53 -07001389 XMLTest( "BOM preservation (parse)", XML_SUCCESS, doc.Parse( xml_bom_preservation ), false );
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001390 XMLPrinter printer;
1391 doc.Print( &printer );
1392
1393 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1394 doc.SaveFile( "resources/bomtest.xml" );
1395 }
1396 {
1397 XMLDocument doc;
1398 doc.LoadFile( "resources/bomtest.xml" );
1399 XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
1400
1401 XMLPrinter printer;
1402 doc.Print( &printer );
1403 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1404 }
1405 }
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001406
Michael Daumlinged523282013-10-23 07:47:29 +02001407 {
1408 // Insertion with Removal
1409 const char* xml = "<?xml version=\"1.0\" ?>"
1410 "<root>"
1411 "<one>"
1412 "<subtree>"
1413 "<elem>element 1</elem>text<!-- comment -->"
1414 "</subtree>"
1415 "</one>"
1416 "<two/>"
1417 "</root>";
1418 const char* xmlInsideTwo = "<?xml version=\"1.0\" ?>"
1419 "<root>"
1420 "<one/>"
1421 "<two>"
1422 "<subtree>"
1423 "<elem>element 1</elem>text<!-- comment -->"
1424 "</subtree>"
1425 "</two>"
1426 "</root>";
1427 const char* xmlAfterOne = "<?xml version=\"1.0\" ?>"
1428 "<root>"
1429 "<one/>"
1430 "<subtree>"
1431 "<elem>element 1</elem>text<!-- comment -->"
1432 "</subtree>"
1433 "<two/>"
1434 "</root>";
1435 const char* xmlAfterTwo = "<?xml version=\"1.0\" ?>"
1436 "<root>"
1437 "<one/>"
1438 "<two/>"
1439 "<subtree>"
1440 "<elem>element 1</elem>text<!-- comment -->"
1441 "</subtree>"
1442 "</root>";
1443
1444 XMLDocument doc;
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001445 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001446 XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1447 XMLElement* two = doc.RootElement()->FirstChildElement("two");
1448 two->InsertFirstChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001449 XMLPrinter printer1(0, true);
1450 doc.Accept(&printer1);
1451 XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
Michael Daumlinged523282013-10-23 07:47:29 +02001452
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001453 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001454 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1455 two = doc.RootElement()->FirstChildElement("two");
1456 doc.RootElement()->InsertAfterChild(two, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001457 XMLPrinter printer2(0, true);
1458 doc.Accept(&printer2);
1459 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001460
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001461 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001462 XMLNode* one = doc.RootElement()->FirstChildElement("one");
1463 subtree = one->FirstChildElement("subtree");
1464 doc.RootElement()->InsertAfterChild(one, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001465 XMLPrinter printer3(0, true);
1466 doc.Accept(&printer3);
1467 XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001468
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001469 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001470 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1471 two = doc.RootElement()->FirstChildElement("two");
1472 doc.RootElement()->InsertEndChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001473 XMLPrinter printer4(0, true);
1474 doc.Accept(&printer4);
1475 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001476 }
1477
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001478 {
1479 const char* xml = "<svg width = \"128\" height = \"128\">"
1480 " <text> </text>"
1481 "</svg>";
1482 XMLDocument doc;
1483 doc.Parse(xml);
1484 doc.Print();
1485 }
1486
Lee Thomason92e521b2014-11-15 17:45:51 -08001487 {
1488 // Test that it doesn't crash.
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001489 const char* xml = "<?xml version=\"1.0\"?><root><sample><field0><1</field0><field1>2</field1></sample></root>";
1490 XMLDocument doc;
1491 doc.Parse(xml);
1492 doc.PrintError();
Lee Thomason92e521b2014-11-15 17:45:51 -08001493 }
1494
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001495#if 1
1496 // the question being explored is what kind of print to use:
1497 // https://github.com/leethomason/tinyxml2/issues/63
1498 {
1499 //const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
1500 const char* xml = "<element/>";
1501 XMLDocument doc;
1502 doc.Parse( xml );
1503 doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
1504 doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
1505 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
1506 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
1507 doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
1508 doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
1509
1510 doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
1511 doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
1512 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
1513 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
1514 doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
1515 doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
1516
1517 doc.Print();
1518
1519 /* The result of this test is platform, compiler, and library version dependent. :("
1520 XMLPrinter printer;
1521 doc.Print( &printer );
1522 XMLTest( "Float and double formatting.",
1523 "<element attrA-f64=\"123456789.12345679\" attrB-f64=\"1001000000\" attrC-f64=\"1e+20\" attrD-f64=\"0.123456789\" attrA-f32=\"1.2345679e+08\" attrB-f32=\"1.001e+09\" attrC-f32=\"1e+20\" attrD-f32=\"0.12345679\"/>\n",
1524 printer.CStr(),
1525 true );
1526 */
1527 }
1528#endif
Lee Thomasonf07b9522014-10-30 13:25:12 -07001529
1530 {
1531 // Issue #184
1532 // If it doesn't assert, it passes. Caused by objects
1533 // getting created during parsing which are then
1534 // inaccessible in the memory pools.
1535 {
1536 XMLDocument doc;
1537 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1538 }
1539 {
1540 XMLDocument doc;
1541 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1542 doc.Clear();
1543 }
1544 }
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001545
1546 {
1547 // If this doesn't assert in DEBUG, all is well.
1548 tinyxml2::XMLDocument doc;
1549 tinyxml2::XMLElement *pRoot = doc.NewElement("Root");
1550 doc.DeleteNode(pRoot);
1551 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001552
Dmitry-Me8b67d742014-12-22 11:35:12 +03001553 {
1554 // Should not assert in DEBUG
1555 XMLPrinter printer;
1556 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001557
Dmitry-Me6f51c802015-03-14 13:25:03 +03001558 {
1559 // Issue 291. Should not crash
1560 const char* xml = "&#0</a>";
1561 XMLDocument doc;
1562 doc.Parse( xml );
1563
1564 XMLPrinter printer;
1565 doc.Print( &printer );
1566 }
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001567 {
1568 // Issue 299. Can print elements that are not linked in.
1569 // Will crash if issue not fixed.
1570 XMLDocument doc;
1571 XMLElement* newElement = doc.NewElement( "printme" );
1572 XMLPrinter printer;
1573 newElement->Accept( &printer );
Dmitry-Me5daa54c2015-04-08 17:45:07 +03001574 // Delete the node to avoid possible memory leak report in debug output
1575 doc.DeleteNode( newElement );
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001576 }
Lee Thomasonf6577832015-03-26 11:18:21 -07001577 {
Ant Mitchell189198f2015-03-24 16:20:36 +00001578 // Issue 302. Clear errors from LoadFile/SaveFile
1579 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001580 XMLTest( "Issue 302. Should be no error initially", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001581 doc.SaveFile( "./no/such/path/pretty.xml" );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001582 XMLTest( "Issue 302. Fail to save", "XML_ERROR_FILE_COULD_NOT_BE_OPENED", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001583 doc.SaveFile( "./resources/out/compact.xml", true );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001584 XMLTest( "Issue 302. Subsequent success in saving", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001585 }
Dmitry-Me6f51c802015-03-14 13:25:03 +03001586
Dmitry-Med9852a52015-03-25 10:17:49 +03001587 {
1588 // If a document fails to load then subsequent
1589 // successful loads should clear the error
1590 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001591 XMLTest( "Should be no error initially", false, doc.Error() );
Dmitry-Med9852a52015-03-25 10:17:49 +03001592 doc.LoadFile( "resources/no-such-file.xml" );
1593 XMLTest( "No such file - should fail", true, doc.Error() );
1594
1595 doc.LoadFile( "resources/dream.xml" );
1596 XMLTest( "Error should be cleared", false, doc.Error() );
1597 }
Sarat Addepalli8e85afa2015-05-19 09:07:03 +05301598
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301599 {
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001600 // Check that declarations are allowed only at beginning of document
Lee Thomason85492022015-05-22 11:07:45 -07001601 const char* xml0 = "<?xml version=\"1.0\" ?>"
1602 " <!-- xml version=\"1.1\" -->"
1603 "<first />";
1604 const char* xml1 = "<?xml version=\"1.0\" ?>"
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001605 "<?xml-stylesheet type=\"text/xsl\" href=\"Anything.xsl\"?>"
Lee Thomason85492022015-05-22 11:07:45 -07001606 "<first />";
1607 const char* xml2 = "<first />"
1608 "<?xml version=\"1.0\" ?>";
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001609 const char* xml3 = "<first></first>"
1610 "<?xml version=\"1.0\" ?>";
1611
1612 const char* xml4 = "<first><?xml version=\"1.0\" ?></first>";
1613
Lee Thomason85492022015-05-22 11:07:45 -07001614 XMLDocument doc;
1615 doc.Parse(xml0);
1616 XMLTest("Test that the code changes do not affect normal parsing", doc.Error(), false);
1617 doc.Parse(xml1);
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001618 XMLTest("Test that the second declaration is allowed", doc.Error(), false);
Lee Thomason85492022015-05-22 11:07:45 -07001619 doc.Parse(xml2);
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001620 XMLTest("Test that declaration after a child is not allowed", doc.ErrorID(), XML_ERROR_PARSING_DECLARATION);
1621 doc.Parse(xml3);
1622 XMLTest("Test that declaration after a child is not allowed", doc.ErrorID(), XML_ERROR_PARSING_DECLARATION);
1623 doc.Parse(xml4);
1624 XMLTest("Test that declaration inside a child is not allowed", doc.ErrorID(), XML_ERROR_PARSING_DECLARATION);
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301625 }
Dmitry-Med9852a52015-03-25 10:17:49 +03001626
Lee Thomason85492022015-05-22 11:07:45 -07001627 {
1628 // No matter - before or after successfully parsing a text -
1629 // calling XMLDocument::Value() causes an assert in debug.
1630 const char* validXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
1631 "<first />"
1632 "<second />";
1633 XMLDocument* doc = new XMLDocument();
1634 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1635 doc->Parse( validXml );
1636 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1637 delete doc;
1638 }
1639
Dmitry-Mea1beddf2015-05-26 16:19:21 +03001640 {
1641 XMLDocument doc;
1642 for( int i = 0; i < XML_ERROR_COUNT; i++ ) {
kezenatorec694152016-11-26 17:21:43 +10001643 doc.SetError( (XMLError)i, 0, 0, 0 );
Dmitry-Mea1beddf2015-05-26 16:19:21 +03001644 doc.ErrorName();
1645 }
1646 }
1647
kezenatorec694152016-11-26 17:21:43 +10001648 // ----------- Line Number Tracking --------------
1649 {
Lee Thomasone90e9012016-12-24 07:34:39 -08001650 struct TestUtil: XMLVisitor
kezenatorec694152016-11-26 17:21:43 +10001651 {
1652 void TestParseError(const char *testString, const char *docStr, XMLError expected_error, int expectedLine)
1653 {
1654 XMLDocument doc;
1655 XMLError err = doc.Parse(docStr);
1656
1657 XMLTest(testString, true, doc.Error());
1658 XMLTest(testString, expected_error, err);
1659 XMLTest(testString, expectedLine, doc.GetErrorLineNum());
1660 };
1661
1662 void TestStringLines(const char *testString, const char *docStr, const char *expectedLines)
1663 {
1664 XMLDocument doc;
1665 doc.Parse(docStr);
1666 XMLTest(testString, false, doc.Error());
1667 TestDocLines(testString, doc, expectedLines);
1668 }
1669
1670 void TestFileLines(const char *testString, const char *file_name, const char *expectedLines)
1671 {
1672 XMLDocument doc;
1673 doc.LoadFile(file_name);
1674 XMLTest(testString, false, doc.Error());
1675 TestDocLines(testString, doc, expectedLines);
1676 }
1677
1678 private:
1679 DynArray<char, 10> str;
1680
1681 void Push(char type, int lineNum)
1682 {
1683 str.Push(type);
1684 str.Push(char('0' + (lineNum / 10)));
1685 str.Push(char('0' + (lineNum % 10)));
1686 }
1687
1688 bool VisitEnter(const XMLDocument& doc)
1689 {
kezenator19d8ea82016-11-29 19:50:27 +10001690 Push('D', doc.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001691 return true;
1692 }
1693 bool VisitEnter(const XMLElement& element, const XMLAttribute* firstAttribute)
1694 {
kezenator19d8ea82016-11-29 19:50:27 +10001695 Push('E', element.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001696 for (const XMLAttribute *attr = firstAttribute; attr != 0; attr = attr->Next())
kezenator19d8ea82016-11-29 19:50:27 +10001697 Push('A', attr->GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001698 return true;
1699 }
1700 bool Visit(const XMLDeclaration& declaration)
1701 {
kezenator19d8ea82016-11-29 19:50:27 +10001702 Push('L', declaration.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001703 return true;
1704 }
1705 bool Visit(const XMLText& text)
1706 {
kezenator19d8ea82016-11-29 19:50:27 +10001707 Push('T', text.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001708 return true;
1709 }
1710 bool Visit(const XMLComment& comment)
1711 {
kezenator19d8ea82016-11-29 19:50:27 +10001712 Push('C', comment.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001713 return true;
1714 }
1715 bool Visit(const XMLUnknown& unknown)
1716 {
kezenator19d8ea82016-11-29 19:50:27 +10001717 Push('U', unknown.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001718 return true;
1719 }
1720
1721 void TestDocLines(const char *testString, XMLDocument &doc, const char *expectedLines)
1722 {
1723 str.Clear();
1724 doc.Accept(this);
1725 str.Push(0);
1726 XMLTest(testString, expectedLines, str.Mem());
1727 }
Lee Thomasone90e9012016-12-24 07:34:39 -08001728 } tester;
kezenatorec694152016-11-26 17:21:43 +10001729
Lee Thomasone90e9012016-12-24 07:34:39 -08001730 tester.TestParseError("ErrorLine-Parsing", "\n<root>\n foo \n<unclosed/>", XML_ERROR_PARSING, 2);
1731 tester.TestParseError("ErrorLine-Declaration", "<root>\n<?xml version=\"1.0\"?>", XML_ERROR_PARSING_DECLARATION, 2);
1732 tester.TestParseError("ErrorLine-Mismatch", "\n<root>\n</mismatch>", XML_ERROR_MISMATCHED_ELEMENT, 2);
1733 tester.TestParseError("ErrorLine-CData", "\n<root><![CDATA[ \n foo bar \n", XML_ERROR_PARSING_CDATA, 2);
1734 tester.TestParseError("ErrorLine-Text", "\n<root>\n foo bar \n", XML_ERROR_PARSING_TEXT, 3);
1735 tester.TestParseError("ErrorLine-Comment", "\n<root>\n<!-- >\n", XML_ERROR_PARSING_COMMENT, 3);
1736 tester.TestParseError("ErrorLine-Declaration", "\n<root>\n<? >\n", XML_ERROR_PARSING_DECLARATION, 3);
1737 tester.TestParseError("ErrorLine-Unknown", "\n<root>\n<! \n", XML_ERROR_PARSING_UNKNOWN, 3);
1738 tester.TestParseError("ErrorLine-Element", "\n<root>\n<unclosed \n", XML_ERROR_PARSING_ELEMENT, 3);
1739 tester.TestParseError("ErrorLine-Attribute", "\n<root>\n<unclosed \n att\n", XML_ERROR_PARSING_ATTRIBUTE, 4);
1740 tester.TestParseError("ErrorLine-ElementClose", "\n<root>\n<unclosed \n/unexpected", XML_ERROR_PARSING_ELEMENT, 3);
kezenatorec694152016-11-26 17:21:43 +10001741
Lee Thomasone90e9012016-12-24 07:34:39 -08001742 tester.TestStringLines(
kezenatorec694152016-11-26 17:21:43 +10001743 "LineNumbers-String",
Lee Thomasone90e9012016-12-24 07:34:39 -08001744
1745 "<?xml version=\"1.0\"?>\n" // 1 Doc, DecL
1746 "<root a='b' \n" // 2 Element Attribute
1747 "c='d'> d <blah/> \n" // 3 Attribute Text Element
1748 "newline in text \n" // 4 Text
1749 "and second <zxcv/><![CDATA[\n" // 5 Element Text
1750 " cdata test ]]><!-- comment -->\n" // 6 Comment
1751 "<! unknown></root>", // 7 Unknown
1752
kezenatorec694152016-11-26 17:21:43 +10001753 "D01L01E02A02A03T03E03T04E05T05C06U07");
1754
Lee Thomasone90e9012016-12-24 07:34:39 -08001755 tester.TestStringLines(
kezenatorec694152016-11-26 17:21:43 +10001756 "LineNumbers-CRLF",
Lee Thomasone90e9012016-12-24 07:34:39 -08001757
1758 "\r\n" // 1 Doc (arguably should be line 2)
1759 "<?xml version=\"1.0\"?>\n" // 2 DecL
1760 "<root>\r\n" // 3 Element
1761 "\n" // 4
1762 "text contining new line \n" // 5 Text
1763 " and also containing crlf \r\n" // 6
1764 "<sub><![CDATA[\n" // 7 Element Text
1765 "cdata containing new line \n" // 8
1766 " and also containing cflr\r\n" // 9
1767 "]]></sub><sub2/></root>", // 10 Element
1768
kezenatorec694152016-11-26 17:21:43 +10001769 "D01L02E03T05E07T07E10");
1770
Lee Thomasone90e9012016-12-24 07:34:39 -08001771 tester.TestFileLines(
kezenatorec694152016-11-26 17:21:43 +10001772 "LineNumbers-File",
1773 "resources/utf8test.xml",
1774 "D01L01E02E03A03A03T03E04A04A04T04E05A05A05T05E06A06A06T06E07A07A07T07E08A08A08T08E09T09E10T10");
1775 }
1776
Lee Thomason85492022015-05-22 11:07:45 -07001777 // ----------- Performance tracking --------------
Lee Thomason6f381b72012-03-02 12:59:39 -08001778 {
1779#if defined( _MSC_VER )
1780 __int64 start, end, freq;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001781 QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
Lee Thomason6f381b72012-03-02 12:59:39 -08001782#endif
1783
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001784 FILE* perfFP = fopen("resources/dream.xml", "r");
1785 fseek(perfFP, 0, SEEK_END);
Armagetron3c21d6f2016-10-13 13:31:23 +02001786 long size = ftell(perfFP);
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001787 fseek(perfFP, 0, SEEK_SET);
Lee Thomason6f381b72012-03-02 12:59:39 -08001788
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001789 char* mem = new char[size + 1];
1790 fread(mem, size, 1, perfFP);
1791 fclose(perfFP);
Lee Thomason6f381b72012-03-02 12:59:39 -08001792 mem[size] = 0;
1793
1794#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001795 QueryPerformanceCounter((LARGE_INTEGER*)&start);
Lee Thomason6f381b72012-03-02 12:59:39 -08001796#else
1797 clock_t cstart = clock();
1798#endif
1799 static const int COUNT = 10;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001800 for (int i = 0; i < COUNT; ++i) {
Lee Thomason6f381b72012-03-02 12:59:39 -08001801 XMLDocument doc;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001802 doc.Parse(mem);
Lee Thomason6f381b72012-03-02 12:59:39 -08001803 }
1804#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001805 QueryPerformanceCounter((LARGE_INTEGER*)&end);
Lee Thomason6f381b72012-03-02 12:59:39 -08001806#else
1807 clock_t cend = clock();
1808#endif
1809
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001810 delete[] mem;
Lee Thomason6f381b72012-03-02 12:59:39 -08001811
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001812 static const char* note =
Lee Thomason6f381b72012-03-02 12:59:39 -08001813#ifdef DEBUG
1814 "DEBUG";
1815#else
1816 "Release";
1817#endif
1818
1819#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001820 printf("\nParsing %s of dream.xml: %.3f milli-seconds\n", note, 1000.0 * (double)(end - start) / ((double)freq * (double)COUNT));
Lee Thomason6f381b72012-03-02 12:59:39 -08001821#else
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001822 printf("\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart) / (double)COUNT);
Lee Thomason6f381b72012-03-02 12:59:39 -08001823#endif
1824 }
1825
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -08001826 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001827 _CrtMemCheckpoint( &endMemState );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001828
1829 _CrtMemState diffMemState;
1830 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
1831 _CrtMemDumpStatistics( &diffMemState );
1832 #endif
1833
1834 printf ("\nPass %d, Fail %d\n", gPass, gFail);
Lee Thomason (grinliz)db304252013-07-31 12:24:52 -07001835
1836 return gFail;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08001837}