tinyxml2

FORK: TinyXML2 is a simple, small, efficient, C++ XML parser that can be easily integrated into other programs.
git clone https://git.neptards.moe/neptards/tinyxml2.git
Log | Files | Refs

xmltest.cpp (87260B)


      1 #if defined( _MSC_VER )
      2 	#if !defined( _CRT_SECURE_NO_WARNINGS )
      3 		#define _CRT_SECURE_NO_WARNINGS		// This test file is not intended to be secure.
      4 	#endif
      5 #endif
      6 
      7 #include "tinyxml2.h"
      8 #include <cerrno>
      9 #include <cstdlib>
     10 #include <cstring>
     11 #include <ctime>
     12 
     13 #if defined( _MSC_VER ) || defined (WIN32)
     14 	#include <crtdbg.h>
     15 	#define WIN32_LEAN_AND_MEAN
     16 	#include <windows.h>
     17 	_CrtMemState startMemState;
     18 	_CrtMemState endMemState;
     19 #else
     20 	#include <sys/stat.h>
     21 	#include <sys/types.h>
     22 #endif
     23 
     24 using namespace tinyxml2;
     25 using namespace std;
     26 int gPass = 0;
     27 int gFail = 0;
     28 
     29 
     30 bool XMLTest (const char* testString, const char* expected, const char* found, bool echo=true, bool extraNL=false )
     31 {
     32 	bool pass;
     33 	if ( !expected && !found )
     34 		pass = true;
     35 	else if ( !expected || !found )
     36 		pass = false;
     37 	else
     38 		pass = !strcmp( expected, found );
     39 	if ( pass )
     40 		printf ("[pass]");
     41 	else
     42 		printf ("[fail]");
     43 
     44 	if ( !echo ) {
     45 		printf (" %s\n", testString);
     46 	}
     47 	else {
     48 		if ( extraNL ) {
     49 			printf( " %s\n", testString );
     50 			printf( "%s\n", expected );
     51 			printf( "%s\n", found );
     52 		}
     53 		else {
     54 			printf (" %s [%s][%s]\n", testString, expected, found);
     55 		}
     56 	}
     57 
     58 	if ( pass )
     59 		++gPass;
     60 	else
     61 		++gFail;
     62 	return pass;
     63 }
     64 
     65 bool XMLTest(const char* testString, XMLError expected, XMLError found, bool echo = true, bool extraNL = false)
     66 {
     67     return XMLTest(testString, XMLDocument::ErrorIDToName(expected), XMLDocument::ErrorIDToName(found), echo, extraNL);
     68 }
     69 
     70 bool XMLTest(const char* testString, bool expected, bool found, bool echo = true, bool extraNL = false)
     71 {
     72     return XMLTest(testString, expected ? "true" : "false", found ? "true" : "false", echo, extraNL);
     73 }
     74 
     75 template< class T > bool XMLTest( const char* testString, T expected, T found, bool echo=true )
     76 {
     77 	bool pass = ( expected == found );
     78 	if ( pass )
     79 		printf ("[pass]");
     80 	else
     81 		printf ("[fail]");
     82 
     83 	if ( !echo )
     84 		printf (" %s\n", testString);
     85 	else {
     86 		char expectedAsString[64];
     87 		XMLUtil::ToStr(expected, expectedAsString, sizeof(expectedAsString));
     88 
     89 		char foundAsString[64];
     90 		XMLUtil::ToStr(found, foundAsString, sizeof(foundAsString));
     91 
     92 		printf (" %s [%s][%s]\n", testString, expectedAsString, foundAsString );
     93 	}
     94 
     95 	if ( pass )
     96 		++gPass;
     97 	else
     98 		++gFail;
     99 	return pass;
    100 }
    101 
    102 
    103 void NullLineEndings( char* p )
    104 {
    105 	while( p && *p ) {
    106 		if ( *p == '\n' || *p == '\r' ) {
    107 			*p = 0;
    108 			return;
    109 		}
    110 		++p;
    111 	}
    112 }
    113 
    114 
    115 int example_1()
    116 {
    117 	XMLDocument doc;
    118 	doc.LoadFile( "resources/dream.xml" );
    119 
    120 	return doc.ErrorID();
    121 }
    122 /** @page Example_1 Load an XML File
    123  *  @dontinclude ./xmltest.cpp
    124  *  Basic XML file loading.
    125  *  The basic syntax to load an XML file from
    126  *  disk and check for an error. (ErrorID()
    127  *  will return 0 for no error.)
    128  *  @skip example_1()
    129  *  @until }
    130  */
    131 
    132 
    133 int example_2()
    134 {
    135 	static const char* xml = "<element/>";
    136 	XMLDocument doc;
    137 	doc.Parse( xml );
    138 
    139 	return doc.ErrorID();
    140 }
    141 /** @page Example_2 Parse an XML from char buffer
    142  *  @dontinclude ./xmltest.cpp
    143  *  Basic XML string parsing.
    144  *  The basic syntax to parse an XML for
    145  *  a char* and check for an error. (ErrorID()
    146  *  will return 0 for no error.)
    147  *  @skip example_2()
    148  *  @until }
    149  */
    150 
    151 
    152 int example_3()
    153 {
    154 	static const char* xml =
    155 		"<?xml version=\"1.0\"?>"
    156 		"<!DOCTYPE PLAY SYSTEM \"play.dtd\">"
    157 		"<PLAY>"
    158 		"<TITLE>A Midsummer Night's Dream</TITLE>"
    159 		"</PLAY>";
    160 
    161 	XMLDocument doc;
    162 	doc.Parse( xml );
    163 
    164 	XMLElement* titleElement = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" );
    165 	const char* title = titleElement->GetText();
    166 	printf( "Name of play (1): %s\n", title );
    167 
    168 	XMLText* textNode = titleElement->FirstChild()->ToText();
    169 	title = textNode->Value();
    170 	printf( "Name of play (2): %s\n", title );
    171 
    172 	return doc.ErrorID();
    173 }
    174 /** @page Example_3 Get information out of XML
    175 	@dontinclude ./xmltest.cpp
    176 	In this example, we navigate a simple XML
    177 	file, and read some interesting text. Note
    178 	that this example doesn't use error
    179 	checking; working code should check for null
    180 	pointers when walking an XML tree, or use
    181 	XMLHandle.
    182 
    183 	(The XML is an excerpt from "dream.xml").
    184 
    185 	@skip example_3()
    186 	@until </PLAY>";
    187 
    188 	The structure of the XML file is:
    189 
    190 	<ul>
    191 		<li>(declaration)</li>
    192 		<li>(dtd stuff)</li>
    193 		<li>Element "PLAY"</li>
    194 		<ul>
    195 			<li>Element "TITLE"</li>
    196 			<ul>
    197 			    <li>Text "A Midsummer Night's Dream"</li>
    198 			</ul>
    199 		</ul>
    200 	</ul>
    201 
    202 	For this example, we want to print out the
    203 	title of the play. The text of the title (what
    204 	we want) is child of the "TITLE" element which
    205 	is a child of the "PLAY" element.
    206 
    207 	We want to skip the declaration and dtd, so the
    208 	method FirstChildElement() is a good choice. The
    209 	FirstChildElement() of the Document is the "PLAY"
    210 	Element, the FirstChildElement() of the "PLAY" Element
    211 	is the "TITLE" Element.
    212 
    213 	@until ( "TITLE" );
    214 
    215 	We can then use the convenience function GetText()
    216 	to get the title of the play.
    217 
    218 	@until title );
    219 
    220 	Text is just another Node in the XML DOM. And in
    221 	fact you should be a little cautious with it, as
    222 	text nodes can contain elements.
    223 
    224 	@verbatim
    225 	Consider: A Midsummer Night's <b>Dream</b>
    226 	@endverbatim
    227 
    228 	It is more correct to actually query the Text Node
    229 	if in doubt:
    230 
    231 	@until title );
    232 
    233 	Noting that here we use FirstChild() since we are
    234 	looking for XMLText, not an element, and ToText()
    235 	is a cast from a Node to a XMLText.
    236 */
    237 
    238 
    239 bool example_4()
    240 {
    241 	static const char* xml =
    242 		"<information>"
    243 		"	<attributeApproach v='2' />"
    244 		"	<textApproach>"
    245 		"		<v>2</v>"
    246 		"	</textApproach>"
    247 		"</information>";
    248 
    249 	XMLDocument doc;
    250 	doc.Parse( xml );
    251 
    252 	int v0 = 0;
    253 	int v1 = 0;
    254 
    255 	XMLElement* attributeApproachElement = doc.FirstChildElement()->FirstChildElement( "attributeApproach" );
    256 	attributeApproachElement->QueryIntAttribute( "v", &v0 );
    257 
    258 	XMLElement* textApproachElement = doc.FirstChildElement()->FirstChildElement( "textApproach" );
    259 	textApproachElement->FirstChildElement( "v" )->QueryIntText( &v1 );
    260 
    261 	printf( "Both values are the same: %d and %d\n", v0, v1 );
    262 
    263 	return !doc.Error() && ( v0 == v1 );
    264 }
    265 /** @page Example_4 Read attributes and text information.
    266 	@dontinclude ./xmltest.cpp
    267 
    268 	There are fundamentally 2 ways of writing a key-value
    269 	pair into an XML file. (Something that's always annoyed
    270 	me about XML.) Either by using attributes, or by writing
    271 	the key name into an element and the value into
    272 	the text node wrapped by the element. Both approaches
    273 	are illustrated in this example, which shows two ways
    274 	to encode the value "2" into the key "v":
    275 
    276 	@skip example_4()
    277 	@until "</information>";
    278 
    279 	TinyXML-2 has accessors for both approaches.
    280 
    281 	When using an attribute, you navigate to the XMLElement
    282 	with that attribute and use the QueryIntAttribute()
    283 	group of methods. (Also QueryFloatAttribute(), etc.)
    284 
    285 	@skip XMLElement* attributeApproachElement
    286 	@until &v0 );
    287 
    288 	When using the text approach, you need to navigate
    289 	down one more step to the XMLElement that contains
    290 	the text. Note the extra FirstChildElement( "v" )
    291 	in the code below. The value of the text can then
    292 	be safely queried with the QueryIntText() group
    293 	of methods. (Also QueryFloatText(), etc.)
    294 
    295 	@skip XMLElement* textApproachElement
    296 	@until &v1 );
    297 */
    298 
    299 
    300 int main( int argc, const char ** argv )
    301 {
    302 	#if defined( _MSC_VER ) && defined( TINYXML2_DEBUG )
    303 		_CrtMemCheckpoint( &startMemState );
    304 		// Enable MS Visual C++ debug heap memory leaks dump on exit
    305 		_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
    306 		{
    307 			int leaksOnStart = _CrtDumpMemoryLeaks();
    308 			XMLTest( "No leaks on start?", FALSE, leaksOnStart );
    309 		}
    310 	#endif
    311 
    312 	{
    313 		TIXMLASSERT( true );
    314 	}
    315 
    316 	if ( argc > 1 ) {
    317 		XMLDocument* doc = new XMLDocument();
    318 		clock_t startTime = clock();
    319 		doc->LoadFile( argv[1] );
    320  		clock_t loadTime = clock();
    321 		int errorID = doc->ErrorID();
    322 		delete doc; doc = 0;
    323  		clock_t deleteTime = clock();
    324 
    325 		printf( "Test file '%s' loaded. ErrorID=%d\n", argv[1], errorID );
    326 		if ( !errorID ) {
    327 			printf( "Load time=%u\n",   (unsigned)(loadTime - startTime) );
    328 			printf( "Delete time=%u\n", (unsigned)(deleteTime - loadTime) );
    329 			printf( "Total time=%u\n",  (unsigned)(deleteTime - startTime) );
    330 		}
    331 		exit(0);
    332 	}
    333 
    334 	FILE* fp = fopen( "resources/dream.xml", "r" );
    335 	if ( !fp ) {
    336 		printf( "Error opening test file 'dream.xml'.\n"
    337 				"Is your working directory the same as where \n"
    338 				"the xmltest.cpp and dream.xml file are?\n\n"
    339 	#if defined( _MSC_VER )
    340 				"In windows Visual Studio you may need to set\n"
    341 				"Properties->Debugging->Working Directory to '..'\n"
    342 	#endif
    343 			  );
    344 		exit( 1 );
    345 	}
    346 	fclose( fp );
    347 
    348 	XMLTest( "Example_1", 0, example_1() );
    349 	XMLTest( "Example_2", 0, example_2() );
    350 	XMLTest( "Example_3", 0, example_3() );
    351 	XMLTest( "Example_4", true, example_4() );
    352 
    353 	/* ------ Example 2: Lookup information. ---- */
    354 
    355 	{
    356 		static const char* test[] = {	"<element />",
    357 										"<element></element>",
    358 										"<element><subelement/></element>",
    359 										"<element><subelement></subelement></element>",
    360 										"<element><subelement><subsub/></subelement></element>",
    361 										"<!--comment beside elements--><element><subelement></subelement></element>",
    362 										"<!--comment beside elements, this time with spaces-->  \n <element>  <subelement> \n </subelement> </element>",
    363 										"<element attrib1='foo' attrib2=\"bar\" ></element>",
    364 										"<element attrib1='foo' attrib2=\"bar\" ><subelement attrib3='yeehaa' /></element>",
    365 										"<element>Text inside element.</element>",
    366 										"<element><b></b></element>",
    367 										"<element>Text inside and <b>bolded</b> in the element.</element>",
    368 										"<outer><element>Text inside and <b>bolded</b> in the element.</element></outer>",
    369 										"<element>This &amp; That.</element>",
    370 										"<element attrib='This&lt;That' />",
    371 										0
    372 		};
    373 		for( int i=0; test[i]; ++i ) {
    374 			XMLDocument doc;
    375 			doc.Parse( test[i] );
    376 			XMLTest( "Element test", false, doc.Error() );
    377 			doc.Print();
    378 			printf( "----------------------------------------------\n" );
    379 		}
    380 	}
    381 #if 1
    382 	{
    383 		static const char* test = "<!--hello world\n"
    384 								  "          line 2\r"
    385 								  "          line 3\r\n"
    386 								  "          line 4\n\r"
    387 								  "          line 5\r-->";
    388 
    389 		XMLDocument doc;
    390 		doc.Parse( test );
    391 		XMLTest( "Hello world declaration", false, doc.Error() );
    392 		doc.Print();
    393 	}
    394 
    395 	{
    396 		// This test is pre-test for the next one
    397 		// (where Element1 is inserted "after itself".
    398 		// This code didn't use to crash.
    399 		XMLDocument doc;
    400 		XMLElement* element1 = doc.NewElement("Element1");
    401 		XMLElement* element2 = doc.NewElement("Element2");
    402 		doc.InsertEndChild(element1);
    403 		doc.InsertEndChild(element2);
    404 		doc.InsertAfterChild(element2, element2);
    405 		doc.InsertAfterChild(element2, element2);
    406 	}
    407 
    408 	{
    409 		XMLDocument doc;
    410 		XMLElement* element1 = doc.NewElement("Element1");
    411 		XMLElement* element2 = doc.NewElement("Element2");
    412 		doc.InsertEndChild(element1);
    413 		doc.InsertEndChild(element2);
    414 
    415 		// This insertion "after itself"
    416 		// used to cause invalid memory access and crash
    417 		doc.InsertAfterChild(element1, element1);
    418 		doc.InsertAfterChild(element1, element1);
    419 		doc.InsertAfterChild(element2, element2);
    420 		doc.InsertAfterChild(element2, element2);
    421 	}
    422 
    423 	{
    424 		static const char* test = "<element>Text before.</element>";
    425 		XMLDocument doc;
    426 		doc.Parse( test );
    427 		XMLTest( "Element text before", false, doc.Error() );
    428 		XMLElement* root = doc.FirstChildElement();
    429 		XMLElement* newElement = doc.NewElement( "Subelement" );
    430 		root->InsertEndChild( newElement );
    431 		doc.Print();
    432 	}
    433 	{
    434 		XMLDocument* doc = new XMLDocument();
    435 		static const char* test = "<element><sub/></element>";
    436 		doc->Parse( test );
    437 		XMLTest( "Element with sub element", false, doc->Error() );
    438 		delete doc;
    439 	}
    440 	{
    441 		// Test: Programmatic DOM nodes insertion return values
    442 		XMLDocument doc;
    443 
    444 		XMLNode* first = doc.NewElement( "firstElement" );
    445 		XMLTest( "New element", true, first != 0 );
    446 		XMLNode* firstAfterInsertion = doc.InsertFirstChild( first );
    447 		XMLTest( "New element inserted first", true, firstAfterInsertion == first );
    448 
    449 		XMLNode* last = doc.NewElement( "lastElement" );
    450 		XMLTest( "New element", true, last != 0 );
    451 		XMLNode* lastAfterInsertion = doc.InsertEndChild( last );
    452 		XMLTest( "New element inserted last", true, lastAfterInsertion == last );
    453 
    454 		XMLNode* middle = doc.NewElement( "middleElement" );
    455 		XMLTest( "New element", true, middle != 0 );
    456 		XMLNode* middleAfterInsertion = doc.InsertAfterChild( first, middle );
    457 		XMLTest( "New element inserted middle", true, middleAfterInsertion == middle );
    458 	}
    459 	{
    460 		// Test: Programmatic DOM
    461 		// Build:
    462 		//		<element>
    463 		//			<!--comment-->
    464 		//			<sub attrib="0" />
    465 		//			<sub attrib="1" />
    466 		//			<sub attrib="2" >& Text!</sub>
    467 		//		<element>
    468 
    469 		XMLDocument* doc = new XMLDocument();
    470 		XMLNode* element = doc->InsertEndChild( doc->NewElement( "element" ) );
    471 
    472 		XMLElement* sub[3] = { doc->NewElement( "sub" ), doc->NewElement( "sub" ), doc->NewElement( "sub" ) };
    473 		for( int i=0; i<3; ++i ) {
    474 			sub[i]->SetAttribute( "attrib", i );
    475 		}
    476 		element->InsertEndChild( sub[2] );
    477 
    478 		const int dummyInitialValue = 1000;
    479 		int dummyValue = dummyInitialValue;
    480 
    481 		XMLNode* comment = element->InsertFirstChild( doc->NewComment( "comment" ) );
    482 		comment->SetUserData(&dummyValue);
    483 		element->InsertAfterChild( comment, sub[0] );
    484 		element->InsertAfterChild( sub[0], sub[1] );
    485 		sub[2]->InsertFirstChild( doc->NewText( "& Text!" ));
    486 		doc->Print();
    487 		XMLTest( "Programmatic DOM", "comment", doc->FirstChildElement( "element" )->FirstChild()->Value() );
    488 		XMLTest( "Programmatic DOM", "0", doc->FirstChildElement( "element" )->FirstChildElement()->Attribute( "attrib" ) );
    489 		XMLTest( "Programmatic DOM", 2, doc->FirstChildElement()->LastChildElement( "sub" )->IntAttribute( "attrib" ) );
    490 		XMLTest( "Programmatic DOM", "& Text!",
    491 				 doc->FirstChildElement()->LastChildElement( "sub" )->FirstChild()->ToText()->Value() );
    492 		XMLTest("User data - pointer", true, &dummyValue == comment->GetUserData(), false);
    493 		XMLTest("User data - value behind pointer", dummyInitialValue, dummyValue, false);
    494 
    495 		// And now deletion:
    496 		element->DeleteChild( sub[2] );
    497 		doc->DeleteNode( comment );
    498 
    499 		element->FirstChildElement()->SetAttribute( "attrib", true );
    500 		element->LastChildElement()->DeleteAttribute( "attrib" );
    501 
    502 		XMLTest( "Programmatic DOM", true, doc->FirstChildElement()->FirstChildElement()->BoolAttribute( "attrib" ) );
    503 		const int defaultIntValue = 10;
    504 		const int replacementIntValue = 20;
    505 		int value1 = defaultIntValue;
    506 		int value2 = doc->FirstChildElement()->LastChildElement()->IntAttribute( "attrib", replacementIntValue );
    507 		XMLError result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value1 );
    508 		XMLTest( "Programmatic DOM", XML_NO_ATTRIBUTE, result );
    509 		XMLTest( "Programmatic DOM", defaultIntValue, value1 );
    510 		XMLTest( "Programmatic DOM", replacementIntValue, value2 );
    511 
    512 		doc->Print();
    513 
    514 		{
    515 			XMLPrinter streamer;
    516 			doc->Print( &streamer );
    517 			printf( "%s", streamer.CStr() );
    518 		}
    519 		{
    520 			XMLPrinter streamer( 0, true );
    521 			doc->Print( &streamer );
    522 			XMLTest( "Compact mode", "<element><sub attrib=\"true\"/><sub/></element>", streamer.CStr(), false );
    523 		}
    524 		doc->SaveFile( "./resources/out/pretty.xml" );
    525 		XMLTest( "Save pretty.xml", false, doc->Error() );
    526 		doc->SaveFile( "./resources/out/compact.xml", true );
    527 		XMLTest( "Save compact.xml", false, doc->Error() );
    528 		delete doc;
    529 	}
    530 	{
    531 		// Test: Dream
    532 		// XML1 : 1,187,569 bytes	in 31,209 allocations
    533 		// XML2 :   469,073	bytes	in    323 allocations
    534 		//int newStart = gNew;
    535 		XMLDocument doc;
    536 		doc.LoadFile( "resources/dream.xml" );
    537 		XMLTest( "Load dream.xml", false, doc.Error() );
    538 
    539 		doc.SaveFile( "resources/out/dreamout.xml" );
    540 		XMLTest( "Save dreamout.xml", false, doc.Error() );
    541 		doc.PrintError();
    542 
    543 		XMLTest( "Dream", "xml version=\"1.0\"",
    544 						  doc.FirstChild()->ToDeclaration()->Value() );
    545 		XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() != 0 );
    546 		XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
    547 						  doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
    548 		XMLTest( "Dream", "And Robin shall restore amends.",
    549 						  doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
    550 		XMLTest( "Dream", "And Robin shall restore amends.",
    551 						  doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
    552 
    553 		XMLDocument doc2;
    554 		doc2.LoadFile( "resources/out/dreamout.xml" );
    555 		XMLTest( "Load dreamout.xml", false, doc2.Error() );
    556 		XMLTest( "Dream-out", "xml version=\"1.0\"",
    557 						  doc2.FirstChild()->ToDeclaration()->Value() );
    558 		XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() != 0 );
    559 		XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
    560 						  doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
    561 		XMLTest( "Dream-out", "And Robin shall restore amends.",
    562 						  doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
    563 
    564 		//gNewTotal = gNew - newStart;
    565 	}
    566 
    567 
    568 	{
    569 		const char* error =	"<?xml version=\"1.0\" standalone=\"no\" ?>\n"
    570 							"<passages count=\"006\" formatversion=\"20020620\">\n"
    571 							"    <wrong error>\n"
    572 							"</passages>";
    573 
    574 		XMLDocument doc;
    575 		doc.Parse( error );
    576 		XMLTest( "Bad XML", XML_ERROR_PARSING_ATTRIBUTE, doc.ErrorID() );
    577 		const char* errorStr = doc.ErrorStr();
    578 		XMLTest("Formatted error string",
    579 			"Error=XML_ERROR_PARSING_ATTRIBUTE ErrorID=7 (0x7) Line number=3: XMLElement name=wrong",
    580 			errorStr);
    581 	}
    582 
    583 	{
    584 		const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
    585 
    586 		XMLDocument doc;
    587 		doc.Parse( str );
    588 		XMLTest( "Top level attributes", false, doc.Error() );
    589 
    590 		XMLElement* ele = doc.FirstChildElement();
    591 
    592 		int iVal;
    593 		XMLError result;
    594 		double dVal;
    595 
    596 		result = ele->QueryDoubleAttribute( "attr0", &dVal );
    597 		XMLTest( "Query attribute: int as double", XML_SUCCESS, result);
    598 		XMLTest( "Query attribute: int as double", 1, (int)dVal );
    599 		XMLTest( "Query attribute: int as double", 1, (int)ele->DoubleAttribute("attr0"));
    600 
    601 		result = ele->QueryDoubleAttribute( "attr1", &dVal );
    602 		XMLTest( "Query attribute: double as double", XML_SUCCESS, result);
    603 		XMLTest( "Query attribute: double as double", 2.0, dVal );
    604 		XMLTest( "Query attribute: double as double", 2.0, ele->DoubleAttribute("attr1") );
    605 
    606 		result = ele->QueryIntAttribute( "attr1", &iVal );
    607 		XMLTest( "Query attribute: double as int", XML_SUCCESS, result);
    608 		XMLTest( "Query attribute: double as int", 2, iVal );
    609 
    610 		result = ele->QueryIntAttribute( "attr2", &iVal );
    611 		XMLTest( "Query attribute: not a number", XML_WRONG_ATTRIBUTE_TYPE, result );
    612 		XMLTest( "Query attribute: not a number", 4.0, ele->DoubleAttribute("attr2", 4.0) );
    613 
    614 		result = ele->QueryIntAttribute( "bar", &iVal );
    615 		XMLTest( "Query attribute: does not exist", XML_NO_ATTRIBUTE, result );
    616 		XMLTest( "Query attribute: does not exist", true, ele->BoolAttribute("bar", true) );
    617 	}
    618 
    619 	{
    620 		const char* str = "<doc/>";
    621 
    622 		XMLDocument doc;
    623 		doc.Parse( str );
    624 		XMLTest( "Empty top element", false, doc.Error() );
    625 
    626 		XMLElement* ele = doc.FirstChildElement();
    627 
    628 		int iVal, iVal2;
    629 		double dVal, dVal2;
    630 
    631 		ele->SetAttribute( "str", "strValue" );
    632 		ele->SetAttribute( "int", 1 );
    633 		ele->SetAttribute( "double", -1.0 );
    634 
    635 		const char* cStr = ele->Attribute( "str" );
    636 		{
    637 			XMLError queryResult = ele->QueryIntAttribute( "int", &iVal );
    638 			XMLTest( "Query int attribute", XML_SUCCESS, queryResult);
    639 		}
    640 		{
    641 			XMLError queryResult = ele->QueryDoubleAttribute( "double", &dVal );
    642 			XMLTest( "Query double attribute", XML_SUCCESS, queryResult);
    643 		}
    644 
    645 		{
    646 			int queryResult = ele->QueryAttribute( "int", &iVal2 );
    647 			XMLTest( "Query int attribute generic", (int)XML_SUCCESS, queryResult);
    648 		}
    649 		{
    650 			int queryResult = ele->QueryAttribute( "double", &dVal2 );
    651 			XMLTest( "Query double attribute generic", (int)XML_SUCCESS, queryResult);
    652 		}
    653 
    654 		XMLTest( "Attribute match test", "strValue", ele->Attribute( "str", "strValue" ) );
    655 		XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
    656 		XMLTest( "Attribute round trip. int.", 1, iVal );
    657 		XMLTest( "Attribute round trip. double.", -1, (int)dVal );
    658 		XMLTest( "Alternate query", true, iVal == iVal2 );
    659 		XMLTest( "Alternate query", true, dVal == dVal2 );
    660 		XMLTest( "Alternate query", true, iVal == ele->IntAttribute("int") );
    661 		XMLTest( "Alternate query", true, dVal == ele->DoubleAttribute("double") );
    662 	}
    663 
    664 	{
    665 		XMLDocument doc;
    666 		doc.LoadFile( "resources/utf8test.xml" );
    667 		XMLTest( "Load utf8test.xml", false, doc.Error() );
    668 
    669 		// Get the attribute "value" from the "Russian" element and check it.
    670 		XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
    671 		const unsigned char correctValue[] = {	0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
    672 												0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
    673 
    674 		XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
    675 
    676 		const unsigned char russianElementName[] = {	0xd0U, 0xa0U, 0xd1U, 0x83U,
    677 														0xd1U, 0x81U, 0xd1U, 0x81U,
    678 														0xd0U, 0xbaU, 0xd0U, 0xb8U,
    679 														0xd0U, 0xb9U, 0 };
    680 		const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
    681 
    682 		XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
    683 		XMLTest( "UTF-8: Browsing russian element name.",
    684 				 russianText,
    685 				 text->Value() );
    686 
    687 		// Now try for a round trip.
    688 		doc.SaveFile( "resources/out/utf8testout.xml" );
    689 		XMLTest( "UTF-8: Save testout.xml", false, doc.Error() );
    690 
    691 		// Check the round trip.
    692 		bool roundTripOkay = false;
    693 
    694 		FILE* saved  = fopen( "resources/out/utf8testout.xml", "r" );
    695 		XMLTest( "UTF-8: Open utf8testout.xml", true, saved != 0 );
    696 
    697 		FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
    698 		XMLTest( "UTF-8: Open utf8testverify.xml", true, verify != 0 );
    699 
    700 		if ( saved && verify )
    701 		{
    702 			roundTripOkay = true;
    703 			char verifyBuf[256];
    704 			while ( fgets( verifyBuf, 256, verify ) )
    705 			{
    706 				char savedBuf[256];
    707 				fgets( savedBuf, 256, saved );
    708 				NullLineEndings( verifyBuf );
    709 				NullLineEndings( savedBuf );
    710 
    711 				if ( strcmp( verifyBuf, savedBuf ) )
    712 				{
    713 					printf( "verify:%s<\n", verifyBuf );
    714 					printf( "saved :%s<\n", savedBuf );
    715 					roundTripOkay = false;
    716 					break;
    717 				}
    718 			}
    719 		}
    720 		if ( saved )
    721 			fclose( saved );
    722 		if ( verify )
    723 			fclose( verify );
    724 		XMLTest( "UTF-8: Verified multi-language round trip.", true, roundTripOkay );
    725 	}
    726 
    727 	// --------GetText()-----------
    728 	{
    729 		const char* str = "<foo>This is  text</foo>";
    730 		XMLDocument doc;
    731 		doc.Parse( str );
    732 		XMLTest( "Double whitespace", false, doc.Error() );
    733 		const XMLElement* element = doc.RootElement();
    734 
    735 		XMLTest( "GetText() normal use.", "This is  text", element->GetText() );
    736 
    737 		str = "<foo><b>This is text</b></foo>";
    738 		doc.Parse( str );
    739 		XMLTest( "Bold text simulation", false, doc.Error() );
    740 		element = doc.RootElement();
    741 
    742 		XMLTest( "GetText() contained element.", element->GetText() == 0, true );
    743 	}
    744 
    745 
    746 	// --------SetText()-----------
    747 	{
    748 		const char* str = "<foo></foo>";
    749 		XMLDocument doc;
    750 		doc.Parse( str );
    751 		XMLTest( "Empty closed element", false, doc.Error() );
    752 		XMLElement* element = doc.RootElement();
    753 
    754 		element->SetText("darkness.");
    755 		XMLTest( "SetText() normal use (open/close).", "darkness.", element->GetText() );
    756 
    757 		element->SetText("blue flame.");
    758 		XMLTest( "SetText() replace.", "blue flame.", element->GetText() );
    759 
    760 		str = "<foo/>";
    761 		doc.Parse( str );
    762 		XMLTest( "Empty self-closed element", false, doc.Error() );
    763 		element = doc.RootElement();
    764 
    765 		element->SetText("The driver");
    766 		XMLTest( "SetText() normal use. (self-closing)", "The driver", element->GetText() );
    767 
    768 		element->SetText("<b>horses</b>");
    769 		XMLTest( "SetText() replace with tag-like text.", "<b>horses</b>", element->GetText() );
    770 		//doc.Print();
    771 
    772 		str = "<foo><bar>Text in nested element</bar></foo>";
    773 		doc.Parse( str );
    774 		XMLTest( "Text in nested element", false, doc.Error() );
    775 		element = doc.RootElement();
    776 
    777 		element->SetText("wolves");
    778 		XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() );
    779 
    780 		str = "<foo/>";
    781 		doc.Parse( str );
    782 		XMLTest( "Empty self-closed element round 2", false, doc.Error() );
    783 		element = doc.RootElement();
    784 
    785 		element->SetText( "str" );
    786 		XMLTest( "SetText types", "str", element->GetText() );
    787 
    788 		element->SetText( 1 );
    789 		XMLTest( "SetText types", "1", element->GetText() );
    790 
    791 		element->SetText( 1U );
    792 		XMLTest( "SetText types", "1", element->GetText() );
    793 
    794 		element->SetText( true );
    795 		XMLTest( "SetText types", "true", element->GetText() );
    796 
    797 		element->SetText( 1.5f );
    798 		XMLTest( "SetText types", "1.5", element->GetText() );
    799 
    800 		element->SetText( 1.5 );
    801 		XMLTest( "SetText types", "1.5", element->GetText() );
    802 	}
    803 
    804 	// ---------- Attributes ---------
    805 	{
    806 		static const int64_t BIG = -123456789012345678;
    807         static const uint64_t BIG_POS = 123456789012345678;
    808 		XMLDocument doc;
    809 		XMLElement* element = doc.NewElement("element");
    810 		doc.InsertFirstChild(element);
    811 
    812 		{
    813 			element->SetAttribute("attrib", int(-100));
    814 			{
    815 				int v = 0;
    816 				XMLError queryResult = element->QueryIntAttribute("attrib", &v);
    817 				XMLTest("Attribute: int", XML_SUCCESS, queryResult, true);
    818 				XMLTest("Attribute: int", -100, v, true);
    819 			}
    820 			{
    821 				int v = 0;
    822 				int queryResult = element->QueryAttribute("attrib", &v);
    823 				XMLTest("Attribute: int", (int)XML_SUCCESS, queryResult, true);
    824 				XMLTest("Attribute: int", -100, v, true);
    825 			}
    826 			XMLTest("Attribute: int", -100, element->IntAttribute("attrib"), true);
    827 		}
    828 		{
    829 			element->SetAttribute("attrib", unsigned(100));
    830 			{
    831 				unsigned v = 0;
    832 				XMLError queryResult = element->QueryUnsignedAttribute("attrib", &v);
    833 				XMLTest("Attribute: unsigned", XML_SUCCESS, queryResult, true);
    834 				XMLTest("Attribute: unsigned", unsigned(100), v, true);
    835 			}
    836 			{
    837 				unsigned v = 0;
    838 				int queryResult = element->QueryAttribute("attrib", &v);
    839 				XMLTest("Attribute: unsigned", (int)XML_SUCCESS, queryResult, true);
    840 				XMLTest("Attribute: unsigned", unsigned(100), v, true);
    841 			}
    842 			{
    843 				const char* v = "failed";
    844 				XMLError queryResult = element->QueryStringAttribute("not-attrib", &v);
    845 				XMLTest("Attribute: string default", false, queryResult == XML_SUCCESS);
    846 				queryResult = element->QueryStringAttribute("attrib", &v);
    847 				XMLTest("Attribute: string", XML_SUCCESS, queryResult, true);
    848 				XMLTest("Attribute: string", "100", v);
    849 			}
    850 			XMLTest("Attribute: unsigned", unsigned(100), element->UnsignedAttribute("attrib"), true);
    851 		}
    852 		{
    853 			element->SetAttribute("attrib", BIG);
    854 			{
    855 				int64_t v = 0;
    856 				XMLError queryResult = element->QueryInt64Attribute("attrib", &v);
    857 				XMLTest("Attribute: int64_t", XML_SUCCESS, queryResult, true);
    858 				XMLTest("Attribute: int64_t", BIG, v, true);
    859 			}
    860 			{
    861 				int64_t v = 0;
    862 				int queryResult = element->QueryAttribute("attrib", &v);
    863 				XMLTest("Attribute: int64_t", (int)XML_SUCCESS, queryResult, true);
    864 				XMLTest("Attribute: int64_t", BIG, v, true);
    865 			}
    866 			XMLTest("Attribute: int64_t", BIG, element->Int64Attribute("attrib"), true);
    867 		}
    868         {
    869             element->SetAttribute("attrib", BIG_POS);
    870             {
    871                 uint64_t v = 0;
    872                 XMLError queryResult = element->QueryUnsigned64Attribute("attrib", &v);
    873                 XMLTest("Attribute: uint64_t", XML_SUCCESS, queryResult, true);
    874                 XMLTest("Attribute: uint64_t", BIG_POS, v, true);
    875             }
    876             {
    877                 uint64_t v = 0;
    878                 int queryResult = element->QueryAttribute("attrib", &v);
    879                 XMLTest("Attribute: uint64_t", (int)XML_SUCCESS, queryResult, true);
    880                 XMLTest("Attribute: uint64_t", BIG_POS, v, true);
    881             }
    882             XMLTest("Attribute: uint64_t", BIG_POS, element->Unsigned64Attribute("attrib"), true);
    883         }
    884         {
    885 			element->SetAttribute("attrib", true);
    886 			{
    887 				bool v = false;
    888 				XMLError queryResult = element->QueryBoolAttribute("attrib", &v);
    889 				XMLTest("Attribute: bool", XML_SUCCESS, queryResult, true);
    890 				XMLTest("Attribute: bool", true, v, true);
    891 			}
    892 			{
    893 				bool v = false;
    894 				int queryResult = element->QueryAttribute("attrib", &v);
    895 				XMLTest("Attribute: bool", (int)XML_SUCCESS, queryResult, true);
    896 				XMLTest("Attribute: bool", true, v, true);
    897 			}
    898 			XMLTest("Attribute: bool", true, element->BoolAttribute("attrib"), true);
    899 		}
    900 		{
    901 			element->SetAttribute("attrib", true);
    902 			const char* result = element->Attribute("attrib");
    903 			XMLTest("Bool true is 'true'", "true", result);
    904 
    905 			XMLUtil::SetBoolSerialization("1", "0");
    906 			element->SetAttribute("attrib", true);
    907 			result = element->Attribute("attrib");
    908 			XMLTest("Bool true is '1'", "1", result);
    909 
    910 			XMLUtil::SetBoolSerialization(0, 0);
    911 		}
    912 		{
    913 			element->SetAttribute("attrib", 100.0);
    914 			{
    915 				double v = 0;
    916 				XMLError queryResult = element->QueryDoubleAttribute("attrib", &v);
    917 				XMLTest("Attribute: double", XML_SUCCESS, queryResult, true);
    918 				XMLTest("Attribute: double", 100.0, v, true);
    919 			}
    920 			{
    921 				double v = 0;
    922 				int queryResult = element->QueryAttribute("attrib", &v);
    923 				XMLTest("Attribute: bool", (int)XML_SUCCESS, queryResult, true);
    924 				XMLTest("Attribute: double", 100.0, v, true);
    925 			}
    926 			XMLTest("Attribute: double", 100.0, element->DoubleAttribute("attrib"), true);
    927 		}
    928 		{
    929 			element->SetAttribute("attrib", 100.0f);
    930 			{
    931 				float v = 0;
    932 				XMLError queryResult = element->QueryFloatAttribute("attrib", &v);
    933 				XMLTest("Attribute: float", XML_SUCCESS, queryResult, true);
    934 				XMLTest("Attribute: float", 100.0f, v, true);
    935 			}
    936 			{
    937 				float v = 0;
    938 				int queryResult = element->QueryAttribute("attrib", &v);
    939 				XMLTest("Attribute: float", (int)XML_SUCCESS, queryResult, true);
    940 				XMLTest("Attribute: float", 100.0f, v, true);
    941 			}
    942 			XMLTest("Attribute: float", 100.0f, element->FloatAttribute("attrib"), true);
    943 		}
    944 		{
    945 			element->SetText(BIG);
    946 			int64_t v = 0;
    947 			XMLError queryResult = element->QueryInt64Text(&v);
    948 			XMLTest("Element: int64_t", XML_SUCCESS, queryResult, true);
    949 			XMLTest("Element: int64_t", BIG, v, true);
    950 		}
    951         {
    952             element->SetText(BIG_POS);
    953             uint64_t v = 0;
    954             XMLError queryResult = element->QueryUnsigned64Text(&v);
    955             XMLTest("Element: uint64_t", XML_SUCCESS, queryResult, true);
    956             XMLTest("Element: uint64_t", BIG_POS, v, true);
    957         }
    958     }
    959 
    960 	// ---------- XMLPrinter stream mode ------
    961 	{
    962 		{
    963 			FILE* printerfp = fopen("resources/out/printer.xml", "w");
    964 			XMLTest("Open printer.xml", true, printerfp != 0);
    965 			XMLPrinter printer(printerfp);
    966 			printer.OpenElement("foo");
    967 			printer.PushAttribute("attrib-text", "text");
    968 			printer.PushAttribute("attrib-int", int(1));
    969 			printer.PushAttribute("attrib-unsigned", unsigned(2));
    970 			printer.PushAttribute("attrib-int64", int64_t(3));
    971 			printer.PushAttribute("attrib-uint64", uint64_t(37));
    972 			printer.PushAttribute("attrib-bool", true);
    973 			printer.PushAttribute("attrib-double", 4.0);
    974 			printer.CloseElement();
    975 			fclose(printerfp);
    976 		}
    977 		{
    978 			XMLDocument doc;
    979 			doc.LoadFile("resources/out/printer.xml");
    980 			XMLTest("XMLPrinter Stream mode: load", XML_SUCCESS, doc.ErrorID(), true);
    981 
    982 			const XMLDocument& cdoc = doc;
    983 
    984 			const XMLAttribute* attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-text");
    985 			XMLTest("attrib-text", "text", attrib->Value(), true);
    986 			attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int");
    987 			XMLTest("attrib-int", int(1), attrib->IntValue(), true);
    988 			attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-unsigned");
    989 			XMLTest("attrib-unsigned", unsigned(2), attrib->UnsignedValue(), true);
    990 			attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int64");
    991 			XMLTest("attrib-int64", int64_t(3), attrib->Int64Value(), true);
    992 			attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-uint64");
    993 			XMLTest("attrib-uint64", uint64_t(37), attrib->Unsigned64Value(), true);
    994 			attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-bool");
    995 			XMLTest("attrib-bool", true, attrib->BoolValue(), true);
    996 			attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-double");
    997 			XMLTest("attrib-double", 4.0, attrib->DoubleValue(), true);
    998 		}
    999 		// Add API_testcatse :PushDeclaration();PushText();PushComment()
   1000 		{
   1001 			FILE* fp1 = fopen("resources/out/printer_1.xml", "w");
   1002 			XMLPrinter printer(fp1);
   1003 
   1004 			printer.PushDeclaration("version = '1.0' enconding = 'utf-8'");
   1005 
   1006 			printer.OpenElement("foo");
   1007 			printer.PushAttribute("attrib-text", "text");
   1008 
   1009 			printer.OpenElement("text");
   1010 			printer.PushText("Tinyxml2");
   1011 			printer.CloseElement();
   1012 
   1013 			printer.OpenElement("int");
   1014 			printer.PushText(int(11));
   1015 			printer.CloseElement();
   1016 
   1017 			printer.OpenElement("unsigned");
   1018 			printer.PushText(unsigned(12));
   1019 			printer.CloseElement();
   1020 
   1021 			printer.OpenElement("int64_t");
   1022 			printer.PushText(int64_t(13));
   1023 			printer.CloseElement();
   1024 
   1025 			printer.OpenElement("uint64_t");
   1026 			printer.PushText(uint64_t(14));
   1027 			printer.CloseElement();
   1028 
   1029 			printer.OpenElement("bool");
   1030 			printer.PushText(true);
   1031 			printer.CloseElement();
   1032 
   1033 			printer.OpenElement("float");
   1034 			printer.PushText("1.56");
   1035 			printer.CloseElement();
   1036 
   1037 			printer.OpenElement("double");
   1038 			printer.PushText("12.12");
   1039 			printer.CloseElement();
   1040 
   1041 			printer.OpenElement("comment");
   1042 			printer.PushComment("this is Tinyxml2");
   1043 			printer.CloseElement();
   1044 
   1045 			printer.CloseElement();
   1046 			fclose(fp1);
   1047 		}
   1048 		{
   1049 			XMLDocument doc;
   1050 			doc.LoadFile("resources/out/printer_1.xml");
   1051 			XMLTest("XMLPrinter Stream mode: load", XML_SUCCESS, doc.ErrorID(), true);
   1052 
   1053 			const XMLDocument& cdoc = doc;
   1054 
   1055 			const  XMLElement* root = cdoc.FirstChildElement("foo");
   1056 
   1057 			const char* text_value;
   1058 			text_value = root->FirstChildElement("text")->GetText();
   1059 			XMLTest("PushText( const char* text, bool cdata=false ) test", "Tinyxml2", text_value);
   1060 
   1061 			int  int_value;
   1062 			int_value = root->FirstChildElement("int")->IntText();
   1063 			XMLTest("PushText( int value ) test", 11, int_value);
   1064 
   1065 			unsigned  unsigned_value;
   1066 			unsigned_value = root->FirstChildElement("unsigned")->UnsignedText();
   1067 			XMLTest("PushText( unsigned value ) test", (unsigned)12, unsigned_value);
   1068 
   1069 			int64_t  int64_t_value;
   1070 			int64_t_value = root->FirstChildElement("int64_t")->Int64Text();
   1071 			XMLTest("PushText( int64_t value ) test", (int64_t) 13, int64_t_value);
   1072 
   1073 			uint64_t uint64_t_value;
   1074 			uint64_t_value = root->FirstChildElement("uint64_t")->Unsigned64Text();
   1075 			XMLTest("PushText( uint64_t value ) test", (uint64_t) 14, uint64_t_value);
   1076 
   1077 			float  float_value;
   1078 			float_value = root->FirstChildElement("float")->FloatText();
   1079 			XMLTest("PushText( float value ) test", 1.56f, float_value);
   1080 
   1081 			double double_value;
   1082 			double_value = root->FirstChildElement("double")->DoubleText();
   1083 			XMLTest("PushText( double value ) test", 12.12, double_value);
   1084 
   1085 			bool bool_value;
   1086 			bool_value = root->FirstChildElement("bool")->BoolText();
   1087 			XMLTest("PushText( bool value ) test", true, bool_value);
   1088 
   1089 			const XMLComment* comment = root->FirstChildElement("comment")->FirstChild()->ToComment();
   1090 			const char* comment_value = comment->Value();
   1091 			XMLTest("PushComment() test", "this is Tinyxml2", comment_value);
   1092 
   1093 			const XMLDeclaration* declaration = cdoc.FirstChild()->ToDeclaration();
   1094 			const char* declaration_value = declaration->Value();
   1095 			XMLTest("PushDeclaration() test", "version = '1.0' enconding = 'utf-8'", declaration_value);
   1096 		}
   1097 	}
   1098 
   1099 
   1100 	// ---------- CDATA ---------------
   1101 	{
   1102 		const char* str =	"<xmlElement>"
   1103 								"<![CDATA["
   1104 									"I am > the rules!\n"
   1105 									"...since I make symbolic puns"
   1106 								"]]>"
   1107 							"</xmlElement>";
   1108 		XMLDocument doc;
   1109 		doc.Parse( str );
   1110 		XMLTest( "CDATA symbolic puns round 1", false, doc.Error() );
   1111 		doc.Print();
   1112 
   1113 		XMLTest( "CDATA parse.", "I am > the rules!\n...since I make symbolic puns",
   1114 								 doc.FirstChildElement()->FirstChild()->Value(),
   1115 								 false );
   1116 	}
   1117 
   1118 	// ----------- CDATA -------------
   1119 	{
   1120 		const char* str =	"<xmlElement>"
   1121 								"<![CDATA["
   1122 									"<b>I am > the rules!</b>\n"
   1123 									"...since I make symbolic puns"
   1124 								"]]>"
   1125 							"</xmlElement>";
   1126 		XMLDocument doc;
   1127 		doc.Parse( str );
   1128 		XMLTest( "CDATA symbolic puns round 2", false, doc.Error() );
   1129 		doc.Print();
   1130 
   1131 		XMLTest( "CDATA parse. [ tixml1:1480107 ]",
   1132 								 "<b>I am > the rules!</b>\n...since I make symbolic puns",
   1133 								 doc.FirstChildElement()->FirstChild()->Value(),
   1134 								 false );
   1135 	}
   1136 
   1137 	// InsertAfterChild causes crash.
   1138 	{
   1139 		// InsertBeforeChild and InsertAfterChild causes crash.
   1140 		XMLDocument doc;
   1141 		XMLElement* parent = doc.NewElement( "Parent" );
   1142 		doc.InsertFirstChild( parent );
   1143 
   1144 		XMLElement* childText0 = doc.NewElement( "childText0" );
   1145 		XMLElement* childText1 = doc.NewElement( "childText1" );
   1146 
   1147 		XMLNode* childNode0 = parent->InsertEndChild( childText0 );
   1148 		XMLTest( "InsertEndChild() return", true, childNode0 == childText0 );
   1149 		XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
   1150 		XMLTest( "InsertAfterChild() return", true, childNode1 == childText1 );
   1151 
   1152 		XMLTest( "Test InsertAfterChild on empty node. ", true, ( childNode1 == parent->LastChild() ) );
   1153 	}
   1154 
   1155 	{
   1156 		// Entities not being written correctly.
   1157 		// From Lynn Allen
   1158 
   1159 		const char* passages =
   1160 			"<?xml version=\"1.0\" standalone=\"no\" ?>"
   1161 			"<passages count=\"006\" formatversion=\"20020620\">"
   1162 				"<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
   1163 				" It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
   1164 			"</passages>";
   1165 
   1166 		XMLDocument doc;
   1167 		doc.Parse( passages );
   1168 		XMLTest( "Entity transformation parse round 1", false, doc.Error() );
   1169 		XMLElement* psg = doc.RootElement()->FirstChildElement();
   1170 		const char* context = psg->Attribute( "context" );
   1171 		const char* expected = "Line 5 has \"quotation marks\" and 'apostrophe marks'. It also has <, >, and &, as well as a fake copyright \xC2\xA9.";
   1172 
   1173 		XMLTest( "Entity transformation: read. ", expected, context, true );
   1174 
   1175 		const char* textFilePath = "resources/out/textfile.txt";
   1176 		FILE* textfile = fopen( textFilePath, "w" );
   1177 		XMLTest( "Entity transformation: open text file for writing", true, textfile != 0, true );
   1178 		if ( textfile )
   1179 		{
   1180 			XMLPrinter streamer( textfile );
   1181 			bool acceptResult = psg->Accept( &streamer );
   1182 			fclose( textfile );
   1183 			XMLTest( "Entity transformation: Accept", true, acceptResult );
   1184 		}
   1185 
   1186 		textfile = fopen( textFilePath, "r" );
   1187 		XMLTest( "Entity transformation: open text file for reading", true, textfile != 0, true );
   1188 		if ( textfile )
   1189 		{
   1190 			char buf[ 1024 ];
   1191 			fgets( buf, 1024, textfile );
   1192 			XMLTest( "Entity transformation: write. ",
   1193 					 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
   1194 					 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
   1195 					 buf, false );
   1196 			fclose( textfile );
   1197 		}
   1198 	}
   1199 
   1200 	{
   1201 		// Suppress entities.
   1202 		const char* passages =
   1203 			"<?xml version=\"1.0\" standalone=\"no\" ?>"
   1204 			"<passages count=\"006\" formatversion=\"20020620\">"
   1205 				"<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
   1206 			"</passages>";
   1207 
   1208 		XMLDocument doc( false );
   1209 		doc.Parse( passages );
   1210 		XMLTest( "Entity transformation parse round 2", false, doc.Error() );
   1211 
   1212 		XMLTest( "No entity parsing.",
   1213 				 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.",
   1214 				 doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ) );
   1215 		XMLTest( "No entity parsing.", "Crazy &ttk;",
   1216 				 doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value() );
   1217 		doc.Print();
   1218 	}
   1219 
   1220 	{
   1221 		const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
   1222 
   1223 		XMLDocument doc;
   1224 		doc.Parse( test );
   1225 		XMLTest( "dot in names", false, doc.Error() );
   1226 		XMLTest( "dot in names", "a.elem", doc.FirstChildElement()->Name() );
   1227 		XMLTest( "dot in names", "2.0", doc.FirstChildElement()->Attribute( "xmi.version" ) );
   1228 	}
   1229 
   1230 	{
   1231 		const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
   1232 
   1233 		XMLDocument doc;
   1234 		doc.Parse( test );
   1235 		XMLTest( "fin thickness", false, doc.Error() );
   1236 
   1237 		XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
   1238 		XMLTest( "Entity with one digit.",
   1239 				 "1.1 Start easy ignore fin thickness\n", text->Value(),
   1240 				 false );
   1241 	}
   1242 
   1243 	{
   1244 		// DOCTYPE not preserved (950171)
   1245 		//
   1246 		const char* doctype =
   1247 			"<?xml version=\"1.0\" ?>"
   1248 			"<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
   1249 			"<!ELEMENT title (#PCDATA)>"
   1250 			"<!ELEMENT books (title,authors)>"
   1251 			"<element />";
   1252 
   1253 		XMLDocument doc;
   1254 		doc.Parse( doctype );
   1255 		XMLTest( "PLAY SYSTEM parse", false, doc.Error() );
   1256 		doc.SaveFile( "resources/out/test7.xml" );
   1257 		XMLTest( "PLAY SYSTEM save", false, doc.Error() );
   1258 		doc.DeleteChild( doc.RootElement() );
   1259 		doc.LoadFile( "resources/out/test7.xml" );
   1260 		XMLTest( "PLAY SYSTEM load", false, doc.Error() );
   1261 		doc.Print();
   1262 
   1263 		const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
   1264 		XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
   1265 
   1266 	}
   1267 
   1268 	{
   1269 		// Comments do not stream out correctly.
   1270 		const char* doctype =
   1271 			"<!-- Somewhat<evil> -->";
   1272 		XMLDocument doc;
   1273 		doc.Parse( doctype );
   1274 		XMLTest( "Comment somewhat evil", false, doc.Error() );
   1275 
   1276 		XMLComment* comment = doc.FirstChild()->ToComment();
   1277 
   1278 		XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
   1279 	}
   1280 	{
   1281 		// Double attributes
   1282 		const char* doctype = "<element attr='red' attr='blue' />";
   1283 
   1284 		XMLDocument doc;
   1285 		doc.Parse( doctype );
   1286 
   1287 		XMLTest( "Parsing repeated attributes.", XML_ERROR_PARSING_ATTRIBUTE, doc.ErrorID() );	// is an  error to tinyxml (didn't use to be, but caused issues)
   1288 		doc.PrintError();
   1289 	}
   1290 
   1291 	{
   1292 		// Embedded null in stream.
   1293 		const char* doctype = "<element att\0r='red' attr='blue' />";
   1294 
   1295 		XMLDocument doc;
   1296 		doc.Parse( doctype );
   1297 		XMLTest( "Embedded null throws error.", true, doc.Error() );
   1298 	}
   1299 
   1300 	{
   1301 		// Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
   1302 		const char* str = "";
   1303 		XMLDocument doc;
   1304 		doc.Parse( str );
   1305 		XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
   1306 
   1307 		// But be sure there is an error string!
   1308 		const char* errorStr = doc.ErrorStr();
   1309 		XMLTest("Error string should be set",
   1310 			"Error=XML_ERROR_EMPTY_DOCUMENT ErrorID=13 (0xd) Line number=0",
   1311 			errorStr);
   1312 	}
   1313 
   1314 	{
   1315 		// Documents with all whitespaces should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
   1316 		const char* str = "    ";
   1317 		XMLDocument doc;
   1318 		doc.Parse( str );
   1319 		XMLTest( "All whitespaces document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
   1320 	}
   1321 
   1322 	{
   1323 		// Low entities
   1324 		XMLDocument doc;
   1325 		doc.Parse( "<test>&#x0e;</test>" );
   1326 		XMLTest( "Hex values", false, doc.Error() );
   1327 		const char result[] = { 0x0e, 0 };
   1328 		XMLTest( "Low entities.", result, doc.FirstChildElement()->GetText() );
   1329 		doc.Print();
   1330 	}
   1331 
   1332 	{
   1333 		// Attribute values with trailing quotes not handled correctly
   1334 		XMLDocument doc;
   1335 		doc.Parse( "<foo attribute=bar\" />" );
   1336 		XMLTest( "Throw error with bad end quotes.", true, doc.Error() );
   1337 	}
   1338 
   1339 	{
   1340 		// [ 1663758 ] Failure to report error on bad XML
   1341 		XMLDocument xml;
   1342 		xml.Parse("<x>");
   1343 		XMLTest("Missing end tag at end of input", true, xml.Error());
   1344 		xml.Parse("<x> ");
   1345 		XMLTest("Missing end tag with trailing whitespace", true, xml.Error());
   1346 		xml.Parse("<x></y>");
   1347 		XMLTest("Mismatched tags", XML_ERROR_MISMATCHED_ELEMENT, xml.ErrorID() );
   1348 	}
   1349 
   1350 
   1351 	{
   1352 		// [ 1475201 ] TinyXML parses entities in comments
   1353 		XMLDocument xml;
   1354 		xml.Parse("<!-- declarations for <head> & <body> -->"
   1355 				  "<!-- far &amp; away -->" );
   1356 		XMLTest( "Declarations for head and body", false, xml.Error() );
   1357 
   1358 		XMLNode* e0 = xml.FirstChild();
   1359 		XMLNode* e1 = e0->NextSibling();
   1360 		XMLComment* c0 = e0->ToComment();
   1361 		XMLComment* c1 = e1->ToComment();
   1362 
   1363 		XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
   1364 		XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
   1365 	}
   1366 
   1367 	{
   1368 		XMLDocument xml;
   1369 		xml.Parse( "<Parent>"
   1370 						"<child1 att=''/>"
   1371 						"<!-- With this comment, child2 will not be parsed! -->"
   1372 						"<child2 att=''/>"
   1373 					"</Parent>" );
   1374 		XMLTest( "Comments iteration", false, xml.Error() );
   1375 		xml.Print();
   1376 
   1377 		int count = 0;
   1378 
   1379 		for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
   1380 			 ele;
   1381 			 ele = ele->NextSibling() )
   1382 		{
   1383 			++count;
   1384 		}
   1385 
   1386 		XMLTest( "Comments iterate correctly.", 3, count );
   1387 	}
   1388 
   1389 	{
   1390 		// trying to repro [1874301]. If it doesn't go into an infinite loop, all is well.
   1391 		unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
   1392 		buf[60] = 239;
   1393 		buf[61] = 0;
   1394 
   1395 		XMLDocument doc;
   1396 		doc.Parse( (const char*)buf);
   1397 		XMLTest( "Broken CDATA", true, doc.Error() );
   1398 	}
   1399 
   1400 
   1401 	{
   1402 		// bug 1827248 Error while parsing a little bit malformed file
   1403 		// Actually not malformed - should work.
   1404 		XMLDocument xml;
   1405 		xml.Parse( "<attributelist> </attributelist >" );
   1406 		XMLTest( "Handle end tag whitespace", false, xml.Error() );
   1407 	}
   1408 
   1409 	{
   1410 		// This one must not result in an infinite loop
   1411 		XMLDocument xml;
   1412 		xml.Parse( "<infinite>loop" );
   1413 		XMLTest( "No closing element", true, xml.Error() );
   1414 		XMLTest( "Infinite loop test.", true, true );
   1415 	}
   1416 #endif
   1417 	{
   1418 		const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
   1419 		XMLDocument doc;
   1420 		doc.Parse( pub );
   1421 		XMLTest( "Trailing DOCTYPE", false, doc.Error() );
   1422 
   1423 		XMLDocument clone;
   1424 		for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
   1425 			XMLNode* copy = node->ShallowClone( &clone );
   1426 			clone.InsertEndChild( copy );
   1427 		}
   1428 
   1429 		clone.Print();
   1430 
   1431 		int count=0;
   1432 		const XMLNode* a=clone.FirstChild();
   1433 		const XMLNode* b=doc.FirstChild();
   1434 		for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
   1435 			++count;
   1436 			XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
   1437 		}
   1438 		XMLTest( "Clone and Equal", 4, count );
   1439 	}
   1440 
   1441 	{
   1442 		// Deep Cloning of root element.
   1443 		XMLDocument doc2;
   1444 		XMLPrinter printer1;
   1445 		{
   1446 			// Make sure doc1 is deleted before we test doc2
   1447 			const char* xml =
   1448 				"<root>"
   1449 				"    <child1 foo='bar'/>"
   1450 				"    <!-- comment thing -->"
   1451 				"    <child2 val='1'>Text</child2>"
   1452 				"</root>";
   1453 			XMLDocument doc;
   1454 			doc.Parse(xml);
   1455 			XMLTest( "Parse before deep cloning root element", false, doc.Error() );
   1456 
   1457 			doc.Print(&printer1);
   1458 			XMLNode* root = doc.RootElement()->DeepClone(&doc2);
   1459 			doc2.InsertFirstChild(root);
   1460 		}
   1461 		XMLPrinter printer2;
   1462 		doc2.Print(&printer2);
   1463 
   1464 		XMLTest("Deep clone of element.", printer1.CStr(), printer2.CStr(), true);
   1465 	}
   1466 
   1467 	{
   1468 		// Deep Cloning of sub element.
   1469 		XMLDocument doc2;
   1470 		XMLPrinter printer1;
   1471 		{
   1472 			// Make sure doc1 is deleted before we test doc2
   1473 			const char* xml =
   1474 				"<?xml version ='1.0'?>"
   1475 				"<root>"
   1476 				"    <child1 foo='bar'/>"
   1477 				"    <!-- comment thing -->"
   1478 				"    <child2 val='1'>Text</child2>"
   1479 				"</root>";
   1480 			XMLDocument doc;
   1481 			doc.Parse(xml);
   1482 			XMLTest( "Parse before deep cloning sub element", false, doc.Error() );
   1483 
   1484 			const XMLElement* subElement = doc.FirstChildElement("root")->FirstChildElement("child2");
   1485 			bool acceptResult = subElement->Accept(&printer1);
   1486 			XMLTest( "Accept before deep cloning", true, acceptResult );
   1487 
   1488 			XMLNode* clonedSubElement = subElement->DeepClone(&doc2);
   1489 			doc2.InsertFirstChild(clonedSubElement);
   1490 		}
   1491 		XMLPrinter printer2;
   1492 		doc2.Print(&printer2);
   1493 
   1494 		XMLTest("Deep clone of sub-element.", printer1.CStr(), printer2.CStr(), true);
   1495 	}
   1496 
   1497 	{
   1498 		// Deep cloning of document.
   1499 		XMLDocument doc2;
   1500 		XMLPrinter printer1;
   1501 		{
   1502 			// Make sure doc1 is deleted before we test doc2
   1503 			const char* xml =
   1504 				"<?xml version ='1.0'?>"
   1505 				"<!-- Top level comment. -->"
   1506 				"<root>"
   1507 				"    <child1 foo='bar'/>"
   1508 				"    <!-- comment thing -->"
   1509 				"    <child2 val='1'>Text</child2>"
   1510 				"</root>";
   1511 			XMLDocument doc;
   1512 			doc.Parse(xml);
   1513 			XMLTest( "Parse before deep cloning document", false, doc.Error() );
   1514 			doc.Print(&printer1);
   1515 
   1516 			doc.DeepCopy(&doc2);
   1517 		}
   1518 		XMLPrinter printer2;
   1519 		doc2.Print(&printer2);
   1520 
   1521 		XMLTest("DeepCopy of document.", printer1.CStr(), printer2.CStr(), true);
   1522 	}
   1523 
   1524 
   1525  	{
   1526 		// This shouldn't crash.
   1527 		XMLDocument doc;
   1528 		if(XML_SUCCESS != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
   1529 		{
   1530 			doc.PrintError();
   1531 		}
   1532 		XMLTest( "Error in snprinf handling.", true, doc.Error() );
   1533 	}
   1534 
   1535 	{
   1536 		// Attribute ordering.
   1537 		static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
   1538 		XMLDocument doc;
   1539 		doc.Parse( xml );
   1540 		XMLTest( "Parse for attribute ordering", false, doc.Error() );
   1541 		XMLElement* ele = doc.FirstChildElement();
   1542 
   1543 		const XMLAttribute* a = ele->FirstAttribute();
   1544 		XMLTest( "Attribute order", "1", a->Value() );
   1545 		a = a->Next();
   1546 		XMLTest( "Attribute order", "2", a->Value() );
   1547 		a = a->Next();
   1548 		XMLTest( "Attribute order", "3", a->Value() );
   1549 		XMLTest( "Attribute order", "attrib3", a->Name() );
   1550 
   1551 		ele->DeleteAttribute( "attrib2" );
   1552 		a = ele->FirstAttribute();
   1553 		XMLTest( "Attribute order", "1", a->Value() );
   1554 		a = a->Next();
   1555 		XMLTest( "Attribute order", "3", a->Value() );
   1556 
   1557 		ele->DeleteAttribute( "attrib1" );
   1558 		ele->DeleteAttribute( "attrib3" );
   1559 		XMLTest( "Attribute order (empty)", true, ele->FirstAttribute() == 0 );
   1560 	}
   1561 
   1562 	{
   1563 		// Make sure an attribute with a space in it succeeds.
   1564 		static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
   1565 		static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
   1566 		static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
   1567 		XMLDocument doc0;
   1568 		doc0.Parse( xml0 );
   1569 		XMLTest( "Parse attribute with space 1", false, doc0.Error() );
   1570 		XMLDocument doc1;
   1571 		doc1.Parse( xml1 );
   1572 		XMLTest( "Parse attribute with space 2", false, doc1.Error() );
   1573 		XMLDocument doc2;
   1574 		doc2.Parse( xml2 );
   1575 		XMLTest( "Parse attribute with space 3", false, doc2.Error() );
   1576 
   1577 		XMLElement* ele = 0;
   1578 		ele = doc0.FirstChildElement();
   1579 		XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
   1580 		ele = doc1.FirstChildElement();
   1581 		XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
   1582 		ele = doc2.FirstChildElement();
   1583 		XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
   1584 	}
   1585 
   1586 	{
   1587 		// Make sure we don't go into an infinite loop.
   1588 		static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
   1589 		XMLDocument doc;
   1590 		doc.Parse( xml );
   1591 		XMLTest( "Parse two elements with attribute", false, doc.Error() );
   1592 		XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
   1593 		XMLElement* ele1 = ele0->NextSiblingElement();
   1594 		bool equal = ele0->ShallowEqual( ele1 );
   1595 
   1596 		XMLTest( "Infinite loop in shallow equal.", true, equal );
   1597 	}
   1598 
   1599 	// -------- Handles ------------
   1600 	{
   1601 		static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
   1602 		XMLDocument doc;
   1603 		doc.Parse( xml );
   1604 		XMLTest( "Handle, parse element with attribute and nested element", false, doc.Error() );
   1605 
   1606 		{
   1607 			XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
   1608 			XMLTest( "Handle, non-const, element is found", true, ele != 0 );
   1609 			XMLTest( "Handle, non-const, element name matches", "sub", ele->Value() );
   1610 		}
   1611 
   1612 		{
   1613 			XMLHandle docH( doc );
   1614 			XMLElement* ele = docH.FirstChildElement( "noSuchElement" ).FirstChildElement( "element" ).ToElement();
   1615 			XMLTest( "Handle, non-const, element not found", true, ele == 0 );
   1616 		}
   1617 
   1618 		{
   1619 			const XMLElement* ele = XMLConstHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
   1620 			XMLTest( "Handle, const, element is found", true, ele != 0 );
   1621 			XMLTest( "Handle, const, element name matches", "sub", ele->Value() );
   1622 		}
   1623 
   1624 		{
   1625 			XMLConstHandle docH( doc );
   1626 			const XMLElement* ele = docH.FirstChildElement( "noSuchElement" ).FirstChildElement( "element" ).ToElement();
   1627 			XMLTest( "Handle, const, element not found", true, ele == 0 );
   1628 		}
   1629 	}
   1630 	{
   1631 		// Default Declaration & BOM
   1632 		XMLDocument doc;
   1633 		doc.InsertEndChild( doc.NewDeclaration() );
   1634 		doc.SetBOM( true );
   1635 
   1636 		XMLPrinter printer;
   1637 		doc.Print( &printer );
   1638 
   1639 		static const char* result  = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
   1640 		XMLTest( "BOM and default declaration", result, printer.CStr(), false );
   1641 		XMLTest( "CStrSize", 42, printer.CStrSize(), false );
   1642 	}
   1643 	{
   1644 		const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
   1645 		XMLDocument doc;
   1646 		doc.Parse( xml );
   1647 		XMLTest( "Ill formed XML", true, doc.Error() );
   1648 	}
   1649 
   1650     {
   1651         //API:IntText(),UnsignedText(),Int64Text(),DoubleText(),BoolText() and FloatText() test
   1652         const char* xml = "<point> <IntText>-24</IntText> <UnsignedText>42</UnsignedText> \
   1653 						   <Int64Text>38</Int64Text> <BoolText>true</BoolText> <DoubleText>2.35</DoubleText> </point>";
   1654         XMLDocument doc;
   1655         doc.Parse(xml);
   1656 
   1657         const XMLElement* pointElement = doc.RootElement();
   1658         int test1 = pointElement->FirstChildElement("IntText")->IntText();
   1659         XMLTest("IntText() test", -24, test1);
   1660 
   1661         unsigned test2 = pointElement->FirstChildElement("UnsignedText")->UnsignedText();
   1662         XMLTest("UnsignedText() test", static_cast<unsigned>(42), test2);
   1663 
   1664         int64_t test3 = pointElement->FirstChildElement("Int64Text")->Int64Text();
   1665         XMLTest("Int64Text() test", static_cast<int64_t>(38), test3);
   1666 
   1667         double test4 = pointElement->FirstChildElement("DoubleText")->DoubleText();
   1668         XMLTest("DoubleText() test", 2.35, test4);
   1669 
   1670         float test5 = pointElement->FirstChildElement("DoubleText")->FloatText();
   1671         XMLTest("FloatText()) test", 2.35f, test5);
   1672 
   1673         bool test6 = pointElement->FirstChildElement("BoolText")->BoolText();
   1674         XMLTest("FloatText()) test", true, test6);
   1675     }
   1676 
   1677 	{
   1678 		//API:ShallowEqual() test
   1679 		const char* xml = "<playlist id = 'playlist'>"
   1680 						    "<property name = 'track_name'>voice</property>"
   1681 						  "</playlist>";
   1682 		XMLDocument doc;
   1683 		doc.Parse( xml );
   1684 		const XMLNode* PlaylistNode = doc.RootElement();
   1685 		const XMLNode* PropertyNode = PlaylistNode->FirstChildElement();
   1686 		bool result;
   1687 		result = PlaylistNode->ShallowEqual(PropertyNode);
   1688 		XMLTest("ShallowEqual() test",false,result);
   1689 		result = PlaylistNode->ShallowEqual(PlaylistNode);
   1690 		XMLTest("ShallowEqual() test",true,result);
   1691 	}
   1692 
   1693 	{
   1694 		//API: previousSiblingElement() and NextSiblingElement() test
   1695 		const char* xml = "<playlist id = 'playlist'>"
   1696 						    "<property name = 'track_name'>voice</property>"
   1697 						    "<entry out = '946' producer = '2_playlist1' in = '0'/>"
   1698 							"<blank length = '1'/>"
   1699 						  "</playlist>";
   1700 		XMLDocument doc;
   1701 		doc.Parse( xml );
   1702 		XMLElement* ElementPlaylist = doc.FirstChildElement("playlist");
   1703 		XMLTest("previousSiblingElement() test",true,ElementPlaylist != 0);
   1704 		const XMLElement* pre = ElementPlaylist->PreviousSiblingElement();
   1705 		XMLTest("previousSiblingElement() test",true,pre == 0);
   1706 		const XMLElement* ElementBlank = ElementPlaylist->FirstChildElement("entry")->NextSiblingElement("blank");
   1707 		XMLTest("NextSiblingElement() test",true,ElementBlank != 0);
   1708 		const XMLElement* next = ElementBlank->NextSiblingElement();
   1709 		XMLTest("NextSiblingElement() test",true,next == 0);
   1710 		const XMLElement* ElementEntry = ElementBlank->PreviousSiblingElement("entry");
   1711 		XMLTest("PreviousSiblingElement test",true,ElementEntry != 0);
   1712 	}
   1713 
   1714 	// QueryXYZText
   1715 	{
   1716 		const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
   1717 		XMLDocument doc;
   1718 		doc.Parse( xml );
   1719 		XMLTest( "Parse points", false, doc.Error() );
   1720 
   1721 		const XMLElement* pointElement = doc.RootElement();
   1722 
   1723 		{
   1724 			int intValue = 0;
   1725 			XMLError queryResult = pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
   1726 			XMLTest( "QueryIntText result", XML_SUCCESS, queryResult, false );
   1727 			XMLTest( "QueryIntText", 1, intValue, false );
   1728 		}
   1729 
   1730 		{
   1731 			unsigned unsignedValue = 0;
   1732 			XMLError queryResult = pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
   1733 			XMLTest( "QueryUnsignedText result", XML_SUCCESS, queryResult, false );
   1734 			XMLTest( "QueryUnsignedText", (unsigned)1, unsignedValue, false );
   1735 		}
   1736 
   1737 		{
   1738 			float floatValue = 0;
   1739 			XMLError queryResult = pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
   1740 			XMLTest( "QueryFloatText result", XML_SUCCESS, queryResult, false );
   1741 			XMLTest( "QueryFloatText", 1.2f, floatValue, false );
   1742 		}
   1743 
   1744 		{
   1745 			double doubleValue = 0;
   1746 			XMLError queryResult = pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
   1747 			XMLTest( "QueryDoubleText result", XML_SUCCESS, queryResult, false );
   1748 			XMLTest( "QueryDoubleText", 1.2, doubleValue, false );
   1749 		}
   1750 
   1751 		{
   1752 			bool boolValue = false;
   1753 			XMLError queryResult = pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
   1754 			XMLTest( "QueryBoolText result", XML_SUCCESS, queryResult, false );
   1755 			XMLTest( "QueryBoolText", true, boolValue, false );
   1756 		}
   1757 	}
   1758 
   1759 	{
   1760 		const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
   1761 		XMLDocument doc;
   1762 		doc.Parse( xml );
   1763 		XMLTest( "Non-alpha element lead letter parses.", false, doc.Error() );
   1764 	}
   1765 
   1766     {
   1767         const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
   1768         XMLDocument doc;
   1769         doc.Parse( xml );
   1770         XMLTest("Non-alpha attribute lead character parses.", false, doc.Error());
   1771     }
   1772 
   1773     {
   1774         const char* xml = "<3lement></3lement>";
   1775         XMLDocument doc;
   1776         doc.Parse( xml );
   1777         XMLTest("Element names with lead digit fail to parse.", true, doc.Error());
   1778     }
   1779 
   1780 	{
   1781 		const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
   1782 		XMLDocument doc;
   1783 		doc.Parse( xml, 10 );
   1784 		XMLTest( "Set length of incoming data", false, doc.Error() );
   1785 	}
   1786 
   1787     {
   1788         XMLDocument doc;
   1789         XMLTest( "Document is initially empty", true, doc.NoChildren() );
   1790         doc.Clear();
   1791         XMLTest( "Empty is empty after Clear()", true, doc.NoChildren() );
   1792         doc.LoadFile( "resources/dream.xml" );
   1793         XMLTest( "Load dream.xml", false, doc.Error() );
   1794         XMLTest( "Document has something to Clear()", false, doc.NoChildren() );
   1795         doc.Clear();
   1796         XMLTest( "Document Clear()'s", true, doc.NoChildren() );
   1797     }
   1798 
   1799     {
   1800         XMLDocument doc;
   1801         XMLTest( "No error initially", false, doc.Error() );
   1802         XMLError error = doc.Parse( "This is not XML" );
   1803         XMLTest( "Error after invalid XML", true, doc.Error() );
   1804         XMLTest( "Error after invalid XML", error, doc.ErrorID() );
   1805         doc.Clear();
   1806         XMLTest( "No error after Clear()", false, doc.Error() );
   1807     }
   1808 
   1809 	// ----------- Whitespace ------------
   1810 	{
   1811 		const char* xml = "<element>"
   1812 							"<a> This \nis &apos;  text  &apos; </a>"
   1813 							"<b>  This is &apos; text &apos;  \n</b>"
   1814 							"<c>This  is  &apos;  \n\n text &apos;</c>"
   1815 						  "</element>";
   1816 		XMLDocument doc( true, COLLAPSE_WHITESPACE );
   1817 		doc.Parse( xml );
   1818 		XMLTest( "Parse with whitespace collapsing and &apos", false, doc.Error() );
   1819 
   1820 		const XMLElement* element = doc.FirstChildElement();
   1821 		for( const XMLElement* parent = element->FirstChildElement();
   1822 			 parent;
   1823 			 parent = parent->NextSiblingElement() )
   1824 		{
   1825 			XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
   1826 		}
   1827 	}
   1828 
   1829 #if 0
   1830 	{
   1831 		// Passes if assert doesn't fire.
   1832 		XMLDocument xmlDoc;
   1833 
   1834 	    xmlDoc.NewDeclaration();
   1835 	    xmlDoc.NewComment("Configuration file");
   1836 
   1837 	    XMLElement *root = xmlDoc.NewElement("settings");
   1838 	    root->SetAttribute("version", 2);
   1839 	}
   1840 #endif
   1841 
   1842 	{
   1843 		const char* xml = "<element>    </element>";
   1844 		XMLDocument doc( true, COLLAPSE_WHITESPACE );
   1845 		doc.Parse( xml );
   1846 		XMLTest( "Parse with all whitespaces", false, doc.Error() );
   1847 		XMLTest( "Whitespace  all space", true, 0 == doc.FirstChildElement()->FirstChild() );
   1848 	}
   1849 
   1850 	{
   1851 		// An assert should not fire.
   1852 		const char* xml = "<element/>";
   1853 		XMLDocument doc;
   1854 		doc.Parse( xml );
   1855 		XMLTest( "Parse with self-closed element", false, doc.Error() );
   1856 		XMLElement* ele = doc.NewElement( "unused" );		// This will get cleaned up with the 'doc' going out of scope.
   1857 		XMLTest( "Tracking unused elements", true, ele != 0, false );
   1858 	}
   1859 
   1860 
   1861 	{
   1862 		const char* xml = "<parent><child>abc</child></parent>";
   1863 		XMLDocument doc;
   1864 		doc.Parse( xml );
   1865 		XMLTest( "Parse for printing of sub-element", false, doc.Error() );
   1866 		XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
   1867 
   1868 		XMLPrinter printer;
   1869 		bool acceptResult = ele->Accept( &printer );
   1870 		XMLTest( "Accept of sub-element", true, acceptResult );
   1871 		XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
   1872 	}
   1873 
   1874 
   1875 	{
   1876 		XMLDocument doc;
   1877 		XMLError error = doc.LoadFile( "resources/empty.xml" );
   1878 		XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
   1879 		XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() );
   1880 		doc.PrintError();
   1881 	}
   1882 
   1883 	{
   1884         // BOM preservation
   1885         static const char* xml_bom_preservation  = "\xef\xbb\xbf<element/>\n";
   1886         {
   1887 			XMLDocument doc;
   1888 			XMLTest( "BOM preservation (parse)", XML_SUCCESS, doc.Parse( xml_bom_preservation ), false );
   1889             XMLPrinter printer;
   1890             doc.Print( &printer );
   1891 
   1892             XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
   1893 			doc.SaveFile( "resources/out/bomtest.xml" );
   1894 			XMLTest( "Save bomtest.xml", false, doc.Error() );
   1895         }
   1896 		{
   1897 			XMLDocument doc;
   1898 			doc.LoadFile( "resources/out/bomtest.xml" );
   1899 			XMLTest( "Load bomtest.xml", false, doc.Error() );
   1900 			XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
   1901 
   1902             XMLPrinter printer;
   1903             doc.Print( &printer );
   1904             XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
   1905 		}
   1906 	}
   1907 
   1908 	{
   1909 		// Insertion with Removal
   1910 		const char* xml = "<?xml version=\"1.0\" ?>"
   1911 			"<root>"
   1912 			"<one>"
   1913 			"<subtree>"
   1914 			"<elem>element 1</elem>text<!-- comment -->"
   1915 			"</subtree>"
   1916 			"</one>"
   1917 			"<two/>"
   1918 			"</root>";
   1919 		const char* xmlInsideTwo = "<?xml version=\"1.0\" ?>"
   1920 			"<root>"
   1921 			"<one/>"
   1922 			"<two>"
   1923 			"<subtree>"
   1924 			"<elem>element 1</elem>text<!-- comment -->"
   1925 			"</subtree>"
   1926 			"</two>"
   1927 			"</root>";
   1928 		const char* xmlAfterOne = "<?xml version=\"1.0\" ?>"
   1929 			"<root>"
   1930 			"<one/>"
   1931 			"<subtree>"
   1932 			"<elem>element 1</elem>text<!-- comment -->"
   1933 			"</subtree>"
   1934 			"<two/>"
   1935 			"</root>";
   1936 		const char* xmlAfterTwo = "<?xml version=\"1.0\" ?>"
   1937 			"<root>"
   1938 			"<one/>"
   1939 			"<two/>"
   1940 			"<subtree>"
   1941 			"<elem>element 1</elem>text<!-- comment -->"
   1942 			"</subtree>"
   1943 			"</root>";
   1944 
   1945 		XMLDocument doc;
   1946 		doc.Parse(xml);
   1947 		XMLTest( "Insertion with removal parse round 1", false, doc.Error() );
   1948 		XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
   1949 		XMLElement* two = doc.RootElement()->FirstChildElement("two");
   1950 		two->InsertFirstChild(subtree);
   1951 		XMLPrinter printer1(0, true);
   1952 		bool acceptResult = doc.Accept(&printer1);
   1953 		XMLTest("Move node from within <one> to <two> - Accept()", true, acceptResult);
   1954 		XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
   1955 
   1956 		doc.Parse(xml);
   1957 		XMLTest( "Insertion with removal parse round 2", false, doc.Error() );
   1958 		subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
   1959 		two = doc.RootElement()->FirstChildElement("two");
   1960 		doc.RootElement()->InsertAfterChild(two, subtree);
   1961 		XMLPrinter printer2(0, true);
   1962 		acceptResult = doc.Accept(&printer2);
   1963 		XMLTest("Move node from within <one> after <two> - Accept()", true, acceptResult);
   1964 		XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
   1965 
   1966 		doc.Parse(xml);
   1967 		XMLTest( "Insertion with removal parse round 3", false, doc.Error() );
   1968 		XMLNode* one = doc.RootElement()->FirstChildElement("one");
   1969 		subtree = one->FirstChildElement("subtree");
   1970 		doc.RootElement()->InsertAfterChild(one, subtree);
   1971 		XMLPrinter printer3(0, true);
   1972 		acceptResult = doc.Accept(&printer3);
   1973 		XMLTest("Move node from within <one> after <one> - Accept()", true, acceptResult);
   1974 		XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false);
   1975 
   1976 		doc.Parse(xml);
   1977 		XMLTest( "Insertion with removal parse round 4", false, doc.Error() );
   1978 		subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
   1979 		two = doc.RootElement()->FirstChildElement("two");
   1980 		XMLTest("<two> is the last child at root level", true, two == doc.RootElement()->LastChildElement());
   1981 		doc.RootElement()->InsertEndChild(subtree);
   1982 		XMLPrinter printer4(0, true);
   1983 		acceptResult = doc.Accept(&printer4);
   1984 		XMLTest("Move node from within <one> after <two> - Accept()", true, acceptResult);
   1985 		XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
   1986 	}
   1987 
   1988 	{
   1989 		const char* xml = "<svg width = \"128\" height = \"128\">"
   1990 			"	<text> </text>"
   1991 			"</svg>";
   1992 		XMLDocument doc;
   1993 		doc.Parse(xml);
   1994 		XMLTest( "Parse svg with text", false, doc.Error() );
   1995 		doc.Print();
   1996 	}
   1997 
   1998 	{
   1999 		// Test that it doesn't crash.
   2000 		const char* xml = "<?xml version=\"1.0\"?><root><sample><field0><1</field0><field1>2</field1></sample></root>";
   2001 		XMLDocument doc;
   2002 		doc.Parse(xml);
   2003 		XMLTest( "Parse root-sample-field0", true, doc.Error() );
   2004 		doc.PrintError();
   2005 	}
   2006 
   2007 #if 1
   2008 		// the question being explored is what kind of print to use:
   2009 		// https://github.com/leethomason/tinyxml2/issues/63
   2010 	{
   2011 		//const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
   2012 		const char* xml = "<element/>";
   2013 		XMLDocument doc;
   2014 		doc.Parse( xml );
   2015 		XMLTest( "Parse self-closed empty element", false, doc.Error() );
   2016 		doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
   2017 		doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
   2018 		doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
   2019 		doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
   2020 		doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
   2021 		doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
   2022 
   2023 		doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
   2024 		doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
   2025 		doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
   2026 		doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
   2027 		doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
   2028 		doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
   2029 
   2030 		doc.Print();
   2031 
   2032 		/* The result of this test is platform, compiler, and library version dependent. :("
   2033 		XMLPrinter printer;
   2034 		doc.Print( &printer );
   2035 		XMLTest( "Float and double formatting.",
   2036 			"<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",
   2037 			printer.CStr(),
   2038 			true );
   2039 		*/
   2040 	}
   2041 #endif
   2042 
   2043     {
   2044         // Issue #184
   2045         // If it doesn't assert, it passes. Caused by objects
   2046         // getting created during parsing which are then
   2047         // inaccessible in the memory pools.
   2048         const char* xmlText = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>";
   2049         {
   2050             XMLDocument doc;
   2051             doc.Parse(xmlText);
   2052             XMLTest( "Parse hex no closing tag round 1", true, doc.Error() );
   2053         }
   2054         {
   2055             XMLDocument doc;
   2056             doc.Parse(xmlText);
   2057             XMLTest( "Parse hex no closing tag round 2", true, doc.Error() );
   2058             doc.Clear();
   2059         }
   2060     }
   2061 
   2062     {
   2063         // If this doesn't assert in TINYXML2_DEBUG, all is well.
   2064         tinyxml2::XMLDocument doc;
   2065         tinyxml2::XMLElement *pRoot = doc.NewElement("Root");
   2066         doc.DeleteNode(pRoot);
   2067     }
   2068 
   2069     {
   2070         XMLDocument doc;
   2071         XMLElement* root = doc.NewElement( "Root" );
   2072         XMLTest( "Node document before insertion", true, &doc == root->GetDocument() );
   2073         doc.InsertEndChild( root );
   2074         XMLTest( "Node document after insertion", true, &doc == root->GetDocument() );
   2075     }
   2076 
   2077     {
   2078         // If this doesn't assert in TINYXML2_DEBUG, all is well.
   2079         XMLDocument doc;
   2080         XMLElement* unlinkedRoot = doc.NewElement( "Root" );
   2081         XMLElement* linkedRoot = doc.NewElement( "Root" );
   2082         doc.InsertFirstChild( linkedRoot );
   2083         unlinkedRoot->GetDocument()->DeleteNode( linkedRoot );
   2084         unlinkedRoot->GetDocument()->DeleteNode( unlinkedRoot );
   2085     }
   2086 
   2087 	{
   2088 		// Should not assert in TINYXML2_DEBUG
   2089 		XMLPrinter printer;
   2090 	}
   2091 
   2092 	{
   2093 		// Issue 291. Should not crash
   2094 		const char* xml = "&#0</a>";
   2095 		XMLDocument doc;
   2096 		doc.Parse( xml );
   2097 		XMLTest( "Parse hex with closing tag", false, doc.Error() );
   2098 
   2099 		XMLPrinter printer;
   2100 		doc.Print( &printer );
   2101 	}
   2102 	{
   2103 		// Issue 299. Can print elements that are not linked in.
   2104 		// Will crash if issue not fixed.
   2105 		XMLDocument doc;
   2106 		XMLElement* newElement = doc.NewElement( "printme" );
   2107 		XMLPrinter printer;
   2108 		bool acceptResult = newElement->Accept( &printer );
   2109 		XMLTest( "printme - Accept()", true, acceptResult );
   2110 		// Delete the node to avoid possible memory leak report in debug output
   2111 		doc.DeleteNode( newElement );
   2112 	}
   2113 	{
   2114 		// Issue 302. Clear errors from LoadFile/SaveFile
   2115 		XMLDocument doc;
   2116 		XMLTest( "Issue 302. Should be no error initially", "XML_SUCCESS", doc.ErrorName() );
   2117 		doc.SaveFile( "./no/such/path/pretty.xml" );
   2118 		XMLTest( "Issue 302. Fail to save", "XML_ERROR_FILE_COULD_NOT_BE_OPENED", doc.ErrorName() );
   2119 		doc.SaveFile( "./resources/out/compact.xml", true );
   2120 		XMLTest( "Issue 302. Subsequent success in saving", "XML_SUCCESS", doc.ErrorName() );
   2121 	}
   2122 
   2123 	{
   2124 		// If a document fails to load then subsequent
   2125 		// successful loads should clear the error
   2126 		XMLDocument doc;
   2127 		XMLTest( "Should be no error initially", false, doc.Error() );
   2128 		doc.LoadFile( "resources/no-such-file.xml" );
   2129 		XMLTest( "No such file - should fail", true, doc.Error() );
   2130 
   2131 		doc.LoadFile( "resources/dream.xml" );
   2132 		XMLTest( "Error should be cleared", false, doc.Error() );
   2133 	}
   2134 
   2135 	{
   2136 		// Check that declarations are allowed only at beginning of document
   2137 	    const char* xml0 = "<?xml version=\"1.0\" ?>"
   2138 	                       "   <!-- xml version=\"1.1\" -->"
   2139 	                       "<first />";
   2140 	    const char* xml1 = "<?xml version=\"1.0\" ?>"
   2141 	                       "<?xml-stylesheet type=\"text/xsl\" href=\"Anything.xsl\"?>"
   2142 	                       "<first />";
   2143 	    const char* xml2 = "<first />"
   2144 	                       "<?xml version=\"1.0\" ?>";
   2145 	    const char* xml3 = "<first></first>"
   2146 	                       "<?xml version=\"1.0\" ?>";
   2147 
   2148 	    const char* xml4 = "<first><?xml version=\"1.0\" ?></first>";
   2149 
   2150 	    XMLDocument doc;
   2151 	    doc.Parse(xml0);
   2152 	    XMLTest("Test that the code changes do not affect normal parsing", false, doc.Error() );
   2153 	    doc.Parse(xml1);
   2154 	    XMLTest("Test that the second declaration is allowed", false, doc.Error() );
   2155 	    doc.Parse(xml2);
   2156 	    XMLTest("Test that declaration after self-closed child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
   2157 	    doc.Parse(xml3);
   2158 	    XMLTest("Test that declaration after a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
   2159 	    doc.Parse(xml4);
   2160 	    XMLTest("Test that declaration inside a child is not allowed", XML_ERROR_PARSING_DECLARATION, doc.ErrorID() );
   2161 	}
   2162 
   2163     {
   2164 	    // No matter - before or after successfully parsing a text -
   2165 	    // calling XMLDocument::Value() used to cause an assert in debug.
   2166 	    // Null must be returned.
   2167 	    const char* validXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
   2168 	                           "<first />"
   2169 	                           "<second />";
   2170 	    XMLDocument* doc = new XMLDocument();
   2171 	    XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
   2172 	    doc->Parse( validXml );
   2173 	    XMLTest( "Parse to test XMLDocument::Value()", false, doc->Error());
   2174 	    XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
   2175 	    delete doc;
   2176     }
   2177 
   2178 	{
   2179 		XMLDocument doc;
   2180 		for( int i = 0; i < XML_ERROR_COUNT; i++ ) {
   2181 			const XMLError error = static_cast<XMLError>(i);
   2182 			const char* name = XMLDocument::ErrorIDToName(error);
   2183 			XMLTest( "ErrorName() not null after ClearError()", true, name != 0 );
   2184 			if( name == 0 ) {
   2185 				// passing null pointer into strlen() is undefined behavior, so
   2186 				// compiler is allowed to optimise away the null test above if it's
   2187 				// as reachable as the strlen() call
   2188 				continue;
   2189 			}
   2190 			XMLTest( "ErrorName() not empty after ClearError()", true, strlen(name) > 0 );
   2191 		}
   2192 	}
   2193 
   2194 	{
   2195 		const char* html("<!DOCTYPE html><html><body><p>test</p><p><br/></p></body></html>");
   2196 		XMLDocument doc(false);
   2197 		doc.Parse(html);
   2198 
   2199 		XMLPrinter printer(0, true);
   2200 		doc.Print(&printer);
   2201 
   2202 		XMLTest(html, html, printer.CStr());
   2203 	}
   2204 
   2205 	{
   2206 		// Evil memory leaks.
   2207 		// If an XMLElement (etc) is allocated via NewElement() (etc.)
   2208 		// and NOT added to the XMLDocument, what happens?
   2209 		//
   2210 		// Previously (buggy):
   2211 		//		The memory would be free'd when the XMLDocument is
   2212 		//      destructed. But the XMLElement destructor wasn't called, so
   2213 		//      memory allocated for the XMLElement text would not be free'd.
   2214 		//      In practice this meant strings allocated for the XMLElement
   2215 		//      text would be leaked. An edge case, but annoying.
   2216 		// Now:
   2217 		//      The XMLElement destructor is called. But the unlinked nodes
   2218 		//      have to be tracked using a list. This has a minor performance
   2219 		//      impact that can become significant if you have a lot of
   2220 		//      unlinked nodes. (But why would you do that?)
   2221 		// The only way to see this bug was in a Visual C++ runtime debug heap
   2222 		// leak tracker. This is compiled in by default on Windows Debug and
   2223 		// enabled with _CRTDBG_LEAK_CHECK_DF parameter passed to _CrtSetDbgFlag().
   2224 		{
   2225 			XMLDocument doc;
   2226 			doc.NewElement("LEAK 1");
   2227 		}
   2228 		{
   2229 			XMLDocument doc;
   2230 			XMLElement* ele = doc.NewElement("LEAK 2");
   2231 			doc.DeleteNode(ele);
   2232 		}
   2233 	}
   2234 
   2235 	{
   2236 		// Bad bad crash. Parsing error results in stack overflow, if uncaught.
   2237 		const char* TESTS[] = {
   2238 			"./resources/xmltest-5330.xml",
   2239 			"./resources/xmltest-4636783552757760.xml",
   2240 			"./resources/xmltest-5720541257269248.xml",
   2241 			0
   2242 		};
   2243 		for (int i=0; TESTS[i]; ++i) {
   2244 			XMLDocument doc;
   2245 			doc.LoadFile(TESTS[i]);
   2246 			XMLTest("Stack overflow prevented.", XML_ELEMENT_DEPTH_EXCEEDED, doc.ErrorID());
   2247 		}
   2248 	}
   2249     {
   2250         const char* TESTS[] = {
   2251             "./resources/xmltest-5662204197076992.xml",     // Security-level performance issue.
   2252             0
   2253         };
   2254         for (int i = 0; TESTS[i]; ++i) {
   2255             XMLDocument doc;
   2256             doc.LoadFile(TESTS[i]);
   2257             // Need only not crash / lock up.
   2258             XMLTest("Fuzz attack prevented.", true, true);
   2259         }
   2260     }
   2261 	{
   2262 		// Crashing reported via email.
   2263 		const char* xml =
   2264 			"<playlist id='playlist1'>"
   2265 			"<property name='track_name'>voice</property>"
   2266 			"<property name='audio_track'>1</property>"
   2267 			"<entry out = '604' producer = '4_playlist1' in = '0' />"
   2268 			"<blank length = '1' />"
   2269 			"<entry out = '1625' producer = '3_playlist' in = '0' />"
   2270 			"<blank length = '2' />"
   2271 			"<entry out = '946' producer = '2_playlist1' in = '0' />"
   2272 			"<blank length = '1' />"
   2273 			"<entry out = '128' producer = '1_playlist1' in = '0' />"
   2274 			"</playlist>";
   2275 
   2276 		// It's not a good idea to delete elements as you walk the
   2277 		// list. I'm not sure this technically should work; but it's
   2278 		// an interesting test case.
   2279 		XMLDocument doc;
   2280 		XMLError err = doc.Parse(xml);
   2281 		XMLTest("Crash bug parsing", XML_SUCCESS, err );
   2282 
   2283 		XMLElement* playlist = doc.FirstChildElement("playlist");
   2284 		XMLTest("Crash bug parsing", true, playlist != 0);
   2285 
   2286 		{
   2287 			const char* elementName = "entry";
   2288 			XMLElement* entry = playlist->FirstChildElement(elementName);
   2289 			XMLTest("Crash bug parsing", true, entry != 0);
   2290 			while (entry) {
   2291 				XMLElement* todelete = entry;
   2292 				entry = entry->NextSiblingElement(elementName);
   2293 				playlist->DeleteChild(todelete);
   2294 			}
   2295 			entry = playlist->FirstChildElement(elementName);
   2296 			XMLTest("Crash bug parsing", true, entry == 0);
   2297 		}
   2298 		{
   2299 			const char* elementName = "blank";
   2300 			XMLElement* blank = playlist->FirstChildElement(elementName);
   2301 			XMLTest("Crash bug parsing", true, blank != 0);
   2302 			while (blank) {
   2303 				XMLElement* todelete = blank;
   2304 				blank = blank->NextSiblingElement(elementName);
   2305 				playlist->DeleteChild(todelete);
   2306 			}
   2307 			XMLTest("Crash bug parsing", true, blank == 0);
   2308 		}
   2309 
   2310 		tinyxml2::XMLPrinter printer;
   2311 		const bool acceptResult = playlist->Accept(&printer);
   2312 		XMLTest("Crash bug parsing - Accept()", true, acceptResult);
   2313 		printf("%s\n", printer.CStr());
   2314 
   2315 		// No test; it only need to not crash.
   2316 		// Still, wrap it up with a sanity check
   2317 		int nProperty = 0;
   2318 		for (const XMLElement* p = playlist->FirstChildElement("property"); p; p = p->NextSiblingElement("property")) {
   2319 			nProperty++;
   2320 		}
   2321 		XMLTest("Crash bug parsing", 2, nProperty);
   2322 	}
   2323 
   2324     // ----------- Line Number Tracking --------------
   2325     {
   2326         struct TestUtil: XMLVisitor
   2327         {
   2328             TestUtil() : str() {}
   2329 
   2330             void TestParseError(const char *testString, const char *docStr, XMLError expected_error, int expectedLine)
   2331             {
   2332                 XMLDocument doc;
   2333                 const XMLError parseError = doc.Parse(docStr);
   2334 
   2335                 XMLTest(testString, parseError, doc.ErrorID());
   2336                 XMLTest(testString, true, doc.Error());
   2337                 XMLTest(testString, expected_error, parseError);
   2338                 XMLTest(testString, expectedLine, doc.ErrorLineNum());
   2339             };
   2340 
   2341             void TestStringLines(const char *testString, const char *docStr, const char *expectedLines)
   2342             {
   2343                 XMLDocument doc;
   2344                 doc.Parse(docStr);
   2345                 XMLTest(testString, false, doc.Error());
   2346                 TestDocLines(testString, doc, expectedLines);
   2347             }
   2348 
   2349             void TestFileLines(const char *testString, const char *file_name, const char *expectedLines)
   2350             {
   2351                 XMLDocument doc;
   2352                 doc.LoadFile(file_name);
   2353                 XMLTest(testString, false, doc.Error());
   2354                 TestDocLines(testString, doc, expectedLines);
   2355             }
   2356 
   2357         private:
   2358             DynArray<char, 10> str;
   2359 
   2360             void Push(char type, int lineNum)
   2361             {
   2362                 str.Push(type);
   2363                 str.Push(char('0' + (lineNum / 10)));
   2364                 str.Push(char('0' + (lineNum % 10)));
   2365             }
   2366 
   2367             bool VisitEnter(const XMLDocument& doc)
   2368             {
   2369                 Push('D', doc.GetLineNum());
   2370                 return true;
   2371             }
   2372             bool VisitEnter(const XMLElement& element, const XMLAttribute* firstAttribute)
   2373             {
   2374                 Push('E', element.GetLineNum());
   2375                 for (const XMLAttribute *attr = firstAttribute; attr != 0; attr = attr->Next())
   2376                     Push('A', attr->GetLineNum());
   2377                 return true;
   2378             }
   2379             bool Visit(const XMLDeclaration& declaration)
   2380             {
   2381                 Push('L', declaration.GetLineNum());
   2382                 return true;
   2383             }
   2384             bool Visit(const XMLText& text)
   2385             {
   2386                 Push('T', text.GetLineNum());
   2387                 return true;
   2388             }
   2389             bool Visit(const XMLComment& comment)
   2390             {
   2391                 Push('C', comment.GetLineNum());
   2392                 return true;
   2393             }
   2394             bool Visit(const XMLUnknown& unknown)
   2395             {
   2396                 Push('U', unknown.GetLineNum());
   2397                 return true;
   2398             }
   2399 
   2400             void TestDocLines(const char *testString, XMLDocument &doc, const char *expectedLines)
   2401             {
   2402                 str.Clear();
   2403                 const bool acceptResult = doc.Accept(this);
   2404                 XMLTest(testString, true, acceptResult);
   2405                 str.Push(0);
   2406                 XMLTest(testString, expectedLines, str.Mem());
   2407             }
   2408         } tester;
   2409 
   2410 		tester.TestParseError("ErrorLine-Parsing", "\n<root>\n foo \n<unclosed/>", XML_ERROR_PARSING, 2);
   2411         tester.TestParseError("ErrorLine-Declaration", "<root>\n<?xml version=\"1.0\"?>", XML_ERROR_PARSING_DECLARATION, 2);
   2412         tester.TestParseError("ErrorLine-Mismatch", "\n<root>\n</mismatch>", XML_ERROR_MISMATCHED_ELEMENT, 2);
   2413         tester.TestParseError("ErrorLine-CData", "\n<root><![CDATA[ \n foo bar \n", XML_ERROR_PARSING_CDATA, 2);
   2414         tester.TestParseError("ErrorLine-Text", "\n<root>\n foo bar \n", XML_ERROR_PARSING_TEXT, 3);
   2415         tester.TestParseError("ErrorLine-Comment", "\n<root>\n<!-- >\n", XML_ERROR_PARSING_COMMENT, 3);
   2416         tester.TestParseError("ErrorLine-Declaration", "\n<root>\n<? >\n", XML_ERROR_PARSING_DECLARATION, 3);
   2417         tester.TestParseError("ErrorLine-Unknown", "\n<root>\n<! \n", XML_ERROR_PARSING_UNKNOWN, 3);
   2418         tester.TestParseError("ErrorLine-Element", "\n<root>\n<unclosed \n", XML_ERROR_PARSING_ELEMENT, 3);
   2419         tester.TestParseError("ErrorLine-Attribute", "\n<root>\n<unclosed \n att\n", XML_ERROR_PARSING_ATTRIBUTE, 4);
   2420         tester.TestParseError("ErrorLine-ElementClose", "\n<root>\n<unclosed \n/unexpected", XML_ERROR_PARSING_ELEMENT, 3);
   2421 
   2422 		tester.TestStringLines(
   2423             "LineNumbers-String",
   2424 
   2425             "<?xml version=\"1.0\"?>\n"					// 1 Doc, DecL
   2426                 "<root a='b' \n"						// 2 Element Attribute
   2427                 "c='d'> d <blah/>  \n"					// 3 Attribute Text Element
   2428                 "newline in text \n"					// 4 Text
   2429                 "and second <zxcv/><![CDATA[\n"			// 5 Element Text
   2430                 " cdata test ]]><!-- comment -->\n"		// 6 Comment
   2431                 "<! unknown></root>",					// 7 Unknown
   2432 
   2433             "D01L01E02A02A03T03E03T04E05T05C06U07");
   2434 
   2435 		tester.TestStringLines(
   2436             "LineNumbers-CRLF",
   2437 
   2438             "\r\n"										// 1 Doc (arguably should be line 2)
   2439             "<?xml version=\"1.0\"?>\n"					// 2 DecL
   2440             "<root>\r\n"								// 3 Element
   2441             "\n"										// 4
   2442             "text contining new line \n"				// 5 Text
   2443             " and also containing crlf \r\n"			// 6
   2444             "<sub><![CDATA[\n"							// 7 Element Text
   2445             "cdata containing new line \n"				// 8
   2446             " and also containing cflr\r\n"				// 9
   2447             "]]></sub><sub2/></root>",					// 10 Element
   2448 
   2449             "D01L02E03T05E07T07E10");
   2450 
   2451 		tester.TestFileLines(
   2452             "LineNumbers-File",
   2453             "resources/utf8test.xml",
   2454             "D01L01E02E03A03A03T03E04A04A04T04E05A05A05T05E06A06A06T06E07A07A07T07E08A08A08T08E09T09E10T10");
   2455     }
   2456 
   2457     {
   2458     	const char* xml = "<Hello>Text</Error>";
   2459     	XMLDocument doc;
   2460     	doc.Parse(xml);
   2461     	XMLTest("Test mismatched elements.", true, doc.Error());
   2462     	XMLTest("Test mismatched elements.", XML_ERROR_MISMATCHED_ELEMENT, doc.ErrorID());
   2463     	// For now just make sure calls work & doesn't crash.
   2464     	// May solidify the error output in the future.
   2465     	printf("%s\n", doc.ErrorStr());
   2466     	doc.PrintError();
   2467     }
   2468 
   2469     // ----------- Performance tracking --------------
   2470 	{
   2471 #if defined( _MSC_VER )
   2472 		__int64 start, end, freq;
   2473 		QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
   2474 #endif
   2475 
   2476 		FILE* perfFP = fopen("resources/dream.xml", "r");
   2477 		XMLTest("Open dream.xml", true, perfFP != 0);
   2478 		fseek(perfFP, 0, SEEK_END);
   2479 		long size = ftell(perfFP);
   2480 		fseek(perfFP, 0, SEEK_SET);
   2481 
   2482 		char* mem = new char[size + 1];
   2483 		memset(mem, 0xfe, size);
   2484 		size_t bytesRead = fread(mem, 1, size, perfFP);
   2485 		XMLTest("Read dream.xml", true, uint32_t(size) >= uint32_t(bytesRead));
   2486 		fclose(perfFP);
   2487 		mem[size] = 0;
   2488 
   2489 #if defined( _MSC_VER )
   2490 		QueryPerformanceCounter((LARGE_INTEGER*)&start);
   2491 #else
   2492 		clock_t cstart = clock();
   2493 #endif
   2494 		bool parseDreamXmlFailed = false;
   2495 		static const int COUNT = 10;
   2496 		for (int i = 0; i < COUNT; ++i) {
   2497 			XMLDocument doc;
   2498 			doc.Parse(mem);
   2499 			parseDreamXmlFailed = parseDreamXmlFailed || doc.Error();
   2500 		}
   2501 #if defined( _MSC_VER )
   2502 		QueryPerformanceCounter((LARGE_INTEGER*)&end);
   2503 #else
   2504 		clock_t cend = clock();
   2505 #endif
   2506 		XMLTest( "Parse dream.xml", false, parseDreamXmlFailed );
   2507 
   2508 		delete[] mem;
   2509 
   2510 		static const char* note =
   2511 #ifdef TINYXML2_DEBUG
   2512 			"DEBUG";
   2513 #else
   2514 			"Release";
   2515 #endif
   2516 
   2517 #if defined( _MSC_VER )
   2518 		const double duration = 1000.0 * (double)(end - start) / ((double)freq * (double)COUNT);
   2519 #else
   2520 		const double duration = (double)(cend - cstart) / (double)COUNT;
   2521 #endif
   2522 		printf("\nParsing dream.xml (%s): %.3f milli-seconds\n", note, duration);
   2523 	}
   2524 
   2525 #if defined( _MSC_VER ) &&  defined( TINYXML2_DEBUG )
   2526 	{
   2527 		_CrtMemCheckpoint( &endMemState );
   2528 
   2529 		_CrtMemState diffMemState;
   2530 		_CrtMemDifference( &diffMemState, &startMemState, &endMemState );
   2531 		_CrtMemDumpStatistics( &diffMemState );
   2532 
   2533 		{
   2534 			int leaksBeforeExit = _CrtDumpMemoryLeaks();
   2535 			XMLTest( "No leaks before exit?", FALSE, leaksBeforeExit );
   2536 		}
   2537 	}
   2538 #endif
   2539 
   2540 	printf ("\nPass %d, Fail %d\n", gPass, gFail);
   2541 
   2542 	return gFail;
   2543 }