Home | History | Annotate | Download | only in tinyxml
      1 /*
      2    Test program for TinyXML.
      3 */
      4 
      5 
      6 #include "tinyxml.h"
      7 
      8 #ifdef TIXML_USE_STL
      9 	#include <iostream>
     10 	#include <sstream>
     11 	using namespace std;
     12 #else
     13 	#include <stdio.h>
     14 #endif
     15 
     16 #if defined( WIN32 ) && defined( TUNE )
     17 	#include <windows.h>
     18 	// Apologies to non-windows users! But I need some good timers for
     19 	// profiling, and these are very platform specific.
     20 	__int64 start;
     21 	__int64 end;
     22 	__int64 freq;
     23 #endif
     24 
     25 static int gPass = 0;
     26 static int gFail = 0;
     27 
     28 
     29 bool XmlTest (const char* testString, const char* expected, const char* found, bool noEcho = false)
     30 {
     31 	bool pass = !strcmp( expected, found );
     32 	if ( pass )
     33 		printf ("[pass]");
     34 	else
     35 		printf ("[fail]");
     36 
     37 	if ( noEcho )
     38 		printf (" %s\n", testString);
     39 	else
     40 		printf (" %s [%s][%s]\n", testString, expected, found);
     41 
     42 	if ( pass )
     43 		++gPass;
     44 	else
     45 		++gFail;
     46 	return pass;
     47 }
     48 
     49 
     50 bool XmlTest( const char* testString, int expected, int found, bool noEcho = false )
     51 {
     52 	bool pass = ( expected == found );
     53 	if ( pass )
     54 		printf ("[pass]");
     55 	else
     56 		printf ("[fail]");
     57 
     58 	if ( noEcho )
     59 		printf (" %s\n", testString);
     60 	else
     61 		printf (" %s [%d][%d]\n", testString, expected, found);
     62 
     63 	if ( pass )
     64 		++gPass;
     65 	else
     66 		++gFail;
     67 	return pass;
     68 }
     69 
     70 
     71 //
     72 // This file demonstrates some basic functionality of TinyXml.
     73 // Note that the example is very contrived. It presumes you know
     74 // what is in the XML file. But it does test the basic operations,
     75 // and show how to add and remove nodes.
     76 //
     77 
     78 int main()
     79 {
     80 	//
     81 	// We start with the 'demoStart' todo list. Process it. And
     82 	// should hopefully end up with the todo list as illustrated.
     83 	//
     84 	const char* demoStart =
     85 		"<?xml version=\"1.0\"  standalone='no' >\n"
     86 		"<!-- Our to do list data -->"
     87 		"<ToDo>\n"
     88 		"<!-- Do I need a secure PDA? -->\n"
     89 		"<Item priority=\"1\" distance='close'> Go to the <bold>Toy store!</bold></Item>"
     90 		"<Item priority=\"2\" distance='none'> Do bills   </Item>"
     91 		"<Item priority=\"2\" distance='far &amp; back'> Look for Evil Dinosaurs! </Item>"
     92 		"</ToDo>";
     93 
     94 #ifdef TIXML_USE_STL
     95 	/*	What the todo list should look like after processing.
     96 		In stream (no formatting) representation. */
     97 	const char* demoEnd =
     98 		"<?xml version=\"1.0\" standalone=\"no\" ?>"
     99 		"<!-- Our to do list data -->"
    100 		"<ToDo>"
    101 		"<!-- Do I need a secure PDA? -->"
    102 		"<Item priority=\"2\" distance=\"close\">Go to the"
    103 		"<bold>Toy store!"
    104 		"</bold>"
    105 		"</Item>"
    106 		"<Item priority=\"1\" distance=\"far\">Talk to:"
    107 		"<Meeting where=\"School\">"
    108 		"<Attendee name=\"Marple\" position=\"teacher\" />"
    109 		"<Attendee name=\"Voel\" position=\"counselor\" />"
    110 		"</Meeting>"
    111 		"<Meeting where=\"Lunch\" />"
    112 		"</Item>"
    113 		"<Item priority=\"2\" distance=\"here\">Do bills"
    114 		"</Item>"
    115 		"</ToDo>";
    116 #endif
    117 
    118 	// The example parses from the character string (above):
    119 	#if defined( WIN32 ) && defined( TUNE )
    120 	QueryPerformanceCounter( (LARGE_INTEGER*) (&start) );
    121 	#endif
    122 
    123 	{
    124 		// Write to a file and read it back, to check file I/O.
    125 
    126 		TiXmlDocument doc( "demotest.xml" );
    127 		doc.Parse( demoStart );
    128 
    129 		if ( doc.Error() )
    130 		{
    131 			printf( "Error in %s: %s\n", doc.Value(), doc.ErrorDesc() );
    132 			exit( 1 );
    133 		}
    134 		doc.SaveFile();
    135 	}
    136 
    137 	TiXmlDocument doc( "demotest.xml" );
    138 	bool loadOkay = doc.LoadFile();
    139 
    140 	if ( !loadOkay )
    141 	{
    142 		printf( "Could not load test file 'demotest.xml'. Error='%s'. Exiting.\n", doc.ErrorDesc() );
    143 		exit( 1 );
    144 	}
    145 
    146 	printf( "** Demo doc read from disk: ** \n\n" );
    147 	doc.Print( stdout );
    148 
    149 	TiXmlNode* node = 0;
    150 	TiXmlElement* todoElement = 0;
    151 	TiXmlElement* itemElement = 0;
    152 
    153 
    154 	// --------------------------------------------------------
    155 	// An example of changing existing attributes, and removing
    156 	// an element from the document.
    157 	// --------------------------------------------------------
    158 
    159 	// Get the "ToDo" element.
    160 	// It is a child of the document, and can be selected by name.
    161 	node = doc.FirstChild( "ToDo" );
    162 	assert( node );
    163 	todoElement = node->ToElement();
    164 	assert( todoElement  );
    165 
    166 	// Going to the toy store is now our second priority...
    167 	// So set the "priority" attribute of the first item in the list.
    168 	node = todoElement->FirstChildElement();	// This skips the "PDA" comment.
    169 	assert( node );
    170 	itemElement = node->ToElement();
    171 	assert( itemElement  );
    172 	itemElement->SetAttribute( "priority", 2 );
    173 
    174 	// Change the distance to "doing bills" from
    175 	// "none" to "here". It's the next sibling element.
    176 	itemElement = itemElement->NextSiblingElement();
    177 	assert( itemElement );
    178 	itemElement->SetAttribute( "distance", "here" );
    179 
    180 	// Remove the "Look for Evil Dinosaurs!" item.
    181 	// It is 1 more sibling away. We ask the parent to remove
    182 	// a particular child.
    183 	itemElement = itemElement->NextSiblingElement();
    184 	todoElement->RemoveChild( itemElement );
    185 
    186 	itemElement = 0;
    187 
    188 	// --------------------------------------------------------
    189 	// What follows is an example of created elements and text
    190 	// nodes and adding them to the document.
    191 	// --------------------------------------------------------
    192 
    193 	// Add some meetings.
    194 	TiXmlElement item( "Item" );
    195 	item.SetAttribute( "priority", "1" );
    196 	item.SetAttribute( "distance", "far" );
    197 
    198 	TiXmlText text( "Talk to:" );
    199 
    200 	TiXmlElement meeting1( "Meeting" );
    201 	meeting1.SetAttribute( "where", "School" );
    202 
    203 	TiXmlElement meeting2( "Meeting" );
    204 	meeting2.SetAttribute( "where", "Lunch" );
    205 
    206 	TiXmlElement attendee1( "Attendee" );
    207 	attendee1.SetAttribute( "name", "Marple" );
    208 	attendee1.SetAttribute( "position", "teacher" );
    209 
    210 	TiXmlElement attendee2( "Attendee" );
    211 	attendee2.SetAttribute( "name", "Voel" );
    212 	attendee2.SetAttribute( "position", "counselor" );
    213 
    214 	// Assemble the nodes we've created:
    215 	meeting1.InsertEndChild( attendee1 );
    216 	meeting1.InsertEndChild( attendee2 );
    217 
    218 	item.InsertEndChild( text );
    219 	item.InsertEndChild( meeting1 );
    220 	item.InsertEndChild( meeting2 );
    221 
    222 	// And add the node to the existing list after the first child.
    223 	node = todoElement->FirstChild( "Item" );
    224 	assert( node );
    225 	itemElement = node->ToElement();
    226 	assert( itemElement );
    227 
    228 	todoElement->InsertAfterChild( itemElement, item );
    229 
    230 	printf( "\n** Demo doc processed: ** \n\n" );
    231 	doc.Print( stdout );
    232 
    233 
    234 #ifdef TIXML_USE_STL
    235 	printf( "** Demo doc processed to stream: ** \n\n" );
    236 	cout << doc << endl << endl;
    237 #endif
    238 
    239 	// --------------------------------------------------------
    240 	// Different tests...do we have what we expect?
    241 	// --------------------------------------------------------
    242 
    243 	int count = 0;
    244 	TiXmlElement*	element;
    245 
    246 	//////////////////////////////////////////////////////
    247 
    248 #ifdef TIXML_USE_STL
    249 	cout << "** Basic structure. **\n";
    250 	ostringstream outputStream( ostringstream::out );
    251 	outputStream << doc;
    252 	XmlTest( "Output stream correct.",	string( demoEnd ).c_str(),
    253 										outputStream.str().c_str(), true );
    254 #endif
    255 
    256 	node = doc.RootElement();
    257 	XmlTest( "Root element exists.", true, ( node != 0 && node->ToElement() ) );
    258 	XmlTest ( "Root element value is 'ToDo'.", "ToDo",  node->Value());
    259 
    260 	node = node->FirstChild();
    261 	XmlTest( "First child exists & is a comment.", true, ( node != 0 && node->ToComment() ) );
    262 	node = node->NextSibling();
    263 	XmlTest( "Sibling element exists & is an element.", true, ( node != 0 && node->ToElement() ) );
    264 	XmlTest ( "Value is 'Item'.", "Item", node->Value() );
    265 
    266 	node = node->FirstChild();
    267 	XmlTest ( "First child exists.", true, ( node != 0 && node->ToText() ) );
    268 	XmlTest ( "Value is 'Go to the'.", "Go to the", node->Value() );
    269 
    270 
    271 	//////////////////////////////////////////////////////
    272 	printf ("\n** Iterators. **\n");
    273 
    274 	// Walk all the top level nodes of the document.
    275 	count = 0;
    276 	for( node = doc.FirstChild();
    277 		 node;
    278 		 node = node->NextSibling() )
    279 	{
    280 		count++;
    281 	}
    282 	XmlTest( "Top level nodes, using First / Next.", 3, count );
    283 
    284 	count = 0;
    285 	for( node = doc.LastChild();
    286 		 node;
    287 		 node = node->PreviousSibling() )
    288 	{
    289 		count++;
    290 	}
    291 	XmlTest( "Top level nodes, using Last / Previous.", 3, count );
    292 
    293 	// Walk all the top level nodes of the document,
    294 	// using a different syntax.
    295 	count = 0;
    296 	for( node = doc.IterateChildren( 0 );
    297 		 node;
    298 		 node = doc.IterateChildren( node ) )
    299 	{
    300 		count++;
    301 	}
    302 	XmlTest( "Top level nodes, using IterateChildren.", 3, count );
    303 
    304 	// Walk all the elements in a node.
    305 	count = 0;
    306 	for( element = todoElement->FirstChildElement();
    307 		 element;
    308 		 element = element->NextSiblingElement() )
    309 	{
    310 		count++;
    311 	}
    312 	XmlTest( "Children of the 'ToDo' element, using First / Next.",
    313 		3, count );
    314 
    315 	// Walk all the elements in a node by value.
    316 	count = 0;
    317 	for( node = todoElement->FirstChild( "Item" );
    318 		 node;
    319 		 node = node->NextSibling( "Item" ) )
    320 	{
    321 		count++;
    322 	}
    323 	XmlTest( "'Item' children of the 'ToDo' element, using First/Next.", 3, count );
    324 
    325 	count = 0;
    326 	for( node = todoElement->LastChild( "Item" );
    327 		 node;
    328 		 node = node->PreviousSibling( "Item" ) )
    329 	{
    330 		count++;
    331 	}
    332 	XmlTest( "'Item' children of the 'ToDo' element, using Last/Previous.", 3, count );
    333 
    334 #ifdef TIXML_USE_STL
    335 	{
    336 		cout << "\n** Parsing. **\n";
    337 		istringstream parse0( "<Element0 attribute0='foo0' attribute1= noquotes attribute2 = '&gt;' />" );
    338 		TiXmlElement element0( "default" );
    339 		parse0 >> element0;
    340 
    341 		XmlTest ( "Element parsed, value is 'Element0'.", "Element0", element0.Value() );
    342 		XmlTest ( "Reads attribute 'attribute0=\"foo0\"'.", "foo0", element0.Attribute( "attribute0" ));
    343 		XmlTest ( "Reads incorrectly formatted 'attribute1=noquotes'.", "noquotes", element0.Attribute( "attribute1" ) );
    344 		XmlTest ( "Read attribute with entity value '>'.", ">", element0.Attribute( "attribute2" ) );
    345 	}
    346 #endif
    347 
    348 	{
    349 		const char* error =	"<?xml version=\"1.0\" standalone=\"no\" ?>\n"
    350 							"<passages count=\"006\" formatversion=\"20020620\">\n"
    351 							"    <wrong error>\n"
    352 							"</passages>";
    353 
    354         TiXmlDocument doc;
    355 		doc.Parse( error );
    356 		XmlTest( "Error row", doc.ErrorRow(), 3 );
    357 		XmlTest( "Error column", doc.ErrorCol(), 17 );
    358 		//printf( "error=%d id='%s' row %d col%d\n", (int) doc.Error(), doc.ErrorDesc(), doc.ErrorRow()+1, doc.ErrorCol() + 1 );
    359 
    360 	}
    361 	{
    362 		const char* str =	"\t<?xml version=\"1.0\" standalone=\"no\" ?>\t<room doors='2'>\n"
    363 							"  <!-- Silly example -->\n"
    364 							"    <door wall='north'>A great door!</door>\n"
    365 							"\t<door wall='east'/>"
    366 							"</room>";
    367 
    368         TiXmlDocument doc;
    369 		doc.Parse( str );
    370 
    371 		TiXmlHandle docHandle( &doc );
    372 		TiXmlHandle roomHandle = docHandle.FirstChildElement( "room" );
    373 		TiXmlHandle commentHandle = docHandle.FirstChildElement( "room" ).FirstChild();
    374 		TiXmlHandle textHandle = docHandle.FirstChildElement( "room" ).ChildElement( "door", 0 ).FirstChild();
    375 		TiXmlHandle door0Handle = docHandle.FirstChildElement( "room" ).ChildElement( 0 );
    376 		TiXmlHandle door1Handle = docHandle.FirstChildElement( "room" ).ChildElement( 1 );
    377 
    378 		assert( docHandle.Node() );
    379 		assert( roomHandle.Element() );
    380 		assert( commentHandle.Node() );
    381 		assert( textHandle.Text() );
    382 		assert( door0Handle.Element() );
    383 		assert( door1Handle.Element() );
    384 
    385 		TiXmlDeclaration* declaration = doc.FirstChild()->ToDeclaration();
    386 		assert( declaration );
    387 		TiXmlElement* room = roomHandle.Element();
    388 		assert( room );
    389 		TiXmlAttribute* doors = room->FirstAttribute();
    390 		assert( doors );
    391 		TiXmlText* text = textHandle.Text();
    392 		TiXmlComment* comment = commentHandle.Node()->ToComment();
    393 		assert( comment );
    394 		TiXmlElement* door0 = door0Handle.Element();
    395 		TiXmlElement* door1 = door1Handle.Element();
    396 
    397 		XmlTest( "Location tracking: Declaration row", declaration->Row(), 1 );
    398 		XmlTest( "Location tracking: Declaration col", declaration->Column(), 5 );
    399 		XmlTest( "Location tracking: room row", room->Row(), 1 );
    400 		XmlTest( "Location tracking: room col", room->Column(), 45 );
    401 		XmlTest( "Location tracking: doors row", doors->Row(), 1 );
    402 		XmlTest( "Location tracking: doors col", doors->Column(), 51 );
    403 		XmlTest( "Location tracking: Comment row", comment->Row(), 2 );
    404 		XmlTest( "Location tracking: Comment col", comment->Column(), 3 );
    405 		XmlTest( "Location tracking: text row", text->Row(), 3 );
    406 		XmlTest( "Location tracking: text col", text->Column(), 24 );
    407 		XmlTest( "Location tracking: door0 row", door0->Row(), 3 );
    408 		XmlTest( "Location tracking: door0 col", door0->Column(), 5 );
    409 		XmlTest( "Location tracking: door1 row", door1->Row(), 4 );
    410 		XmlTest( "Location tracking: door1 col", door1->Column(), 5 );
    411 	}
    412 	{
    413 		const char* str =	"\t<?xml version=\"1.0\" standalone=\"no\" ?>\t<room doors='2'>\n"
    414 							"</room>";
    415 
    416         TiXmlDocument doc;
    417 		doc.SetTabSize( 8 );
    418 		doc.Parse( str );
    419 
    420 		TiXmlHandle docHandle( &doc );
    421 		TiXmlHandle roomHandle = docHandle.FirstChildElement( "room" );
    422 
    423 		assert( docHandle.Node() );
    424 		assert( roomHandle.Element() );
    425 
    426 		TiXmlElement* room = roomHandle.Element();
    427 		assert( room );
    428 		TiXmlAttribute* doors = room->FirstAttribute();
    429 		assert( doors );
    430 
    431 		XmlTest( "Location tracking: Tab 8: room row", room->Row(), 1 );
    432 		XmlTest( "Location tracking: Tab 8: room col", room->Column(), 49 );
    433 		XmlTest( "Location tracking: Tab 8: doors row", doors->Row(), 1 );
    434 		XmlTest( "Location tracking: Tab 8: doors col", doors->Column(), 55 );
    435 	}
    436 
    437 	{
    438 		const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
    439 
    440 		TiXmlDocument doc;
    441 		doc.Parse( str );
    442 
    443 		TiXmlElement* ele = doc.FirstChildElement();
    444 
    445 		int iVal, result;
    446 		double dVal;
    447 
    448 		result = ele->QueryDoubleAttribute( "attr0", &dVal );
    449 		XmlTest( "Query attribute: int as double", result, TIXML_SUCCESS );
    450 		XmlTest( "Query attribute: int as double", (int)dVal, 1 );
    451 		result = ele->QueryDoubleAttribute( "attr1", &dVal );
    452 		XmlTest( "Query attribute: double as double", (int)dVal, 2 );
    453 		result = ele->QueryIntAttribute( "attr1", &iVal );
    454 		XmlTest( "Query attribute: double as int", result, TIXML_SUCCESS );
    455 		XmlTest( "Query attribute: double as int", iVal, 2 );
    456 		result = ele->QueryIntAttribute( "attr2", &iVal );
    457 		XmlTest( "Query attribute: not a number", result, TIXML_WRONG_TYPE );
    458 		result = ele->QueryIntAttribute( "bar", &iVal );
    459 		XmlTest( "Query attribute: does not exist", result, TIXML_NO_ATTRIBUTE );
    460 	}
    461 
    462 #ifdef TIXML_USE_STL
    463 	{
    464 		//////////////////////////////////////////////////////
    465 		cout << "\n** Streaming. **\n";
    466 
    467 		// Round trip check: stream in, then stream back out to verify. The stream
    468 		// out has already been checked, above. We use the output
    469 
    470 		istringstream inputStringStream( outputStream.str() );
    471 		TiXmlDocument document0;
    472 
    473 		inputStringStream >> document0;
    474 
    475 		ostringstream outputStream0( ostringstream::out );
    476 		outputStream0 << document0;
    477 
    478 		XmlTest( "Stream round trip correct.",	string( demoEnd ).c_str(),
    479 												outputStream0.str().c_str(), true );
    480 
    481 		std::string str;
    482 		str << document0;
    483 
    484 		XmlTest( "String printing correct.", string( demoEnd ).c_str(),
    485 											 str.c_str(), true );
    486 	}
    487 #endif
    488 
    489 	// --------------------------------------------------------
    490 	// UTF-8 testing. It is important to test:
    491 	//	1. Making sure name, value, and text read correctly
    492 	//	2. Row, Col functionality
    493 	//	3. Correct output
    494 	// --------------------------------------------------------
    495 	printf ("\n** UTF-8 **\n");
    496 	{
    497 		TiXmlDocument doc( "utf8test.xml" );
    498 		doc.LoadFile();
    499 		if ( doc.Error() && doc.ErrorId() == TiXmlBase::TIXML_ERROR_OPENING_FILE ) {
    500 			printf( "WARNING: File 'utf8test.xml' not found.\n"
    501 					"(Are you running the test from the wrong directory?)\n"
    502 				    "Could not test UTF-8 functionality.\n" );
    503 		}
    504 		else
    505 		{
    506 			TiXmlHandle docH( &doc );
    507 			// Get the attribute "value" from the "Russian" element and check it.
    508 			TiXmlElement* element = docH.FirstChildElement( "document" ).FirstChildElement( "Russian" ).Element();
    509 			const unsigned char correctValue[] = {	0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
    510 													0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
    511 
    512 			XmlTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ), true );
    513 			XmlTest( "UTF-8: Russian value row.", 4, element->Row() );
    514 			XmlTest( "UTF-8: Russian value column.", 5, element->Column() );
    515 
    516 			const unsigned char russianElementName[] = {	0xd0U, 0xa0U, 0xd1U, 0x83U,
    517 															0xd1U, 0x81U, 0xd1U, 0x81U,
    518 															0xd0U, 0xbaU, 0xd0U, 0xb8U,
    519 															0xd0U, 0xb9U, 0 };
    520 			const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
    521 
    522 			TiXmlText* text = docH.FirstChildElement( "document" ).FirstChildElement( (const char*) russianElementName ).Child( 0 ).Text();
    523 			XmlTest( "UTF-8: Browsing russian element name.",
    524 					 russianText,
    525 					 text->Value(),
    526 					 true );
    527 			XmlTest( "UTF-8: Russian element name row.", 7, text->Row() );
    528 			XmlTest( "UTF-8: Russian element name column.", 47, text->Column() );
    529 
    530 			TiXmlDeclaration* dec = docH.Child( 0 ).Node()->ToDeclaration();
    531 			XmlTest( "UTF-8: Declaration column.", 1, dec->Column() );
    532 			XmlTest( "UTF-8: Document column.", 1, doc.Column() );
    533 
    534 			// Now try for a round trip.
    535 			doc.SaveFile( "utf8testout.xml" );
    536 
    537 			// Check the round trip.
    538 			char savedBuf[256];
    539 			char verifyBuf[256];
    540 			int okay = 1;
    541 
    542 			FILE* saved  = fopen( "utf8testout.xml", "r" );
    543 			FILE* verify = fopen( "utf8testverify.xml", "r" );
    544 			if ( saved && verify )
    545 			{
    546 				while ( fgets( verifyBuf, 256, verify ) )
    547 				{
    548 					fgets( savedBuf, 256, saved );
    549 					if ( strcmp( verifyBuf, savedBuf ) )
    550 					{
    551 						okay = 0;
    552 						break;
    553 					}
    554 				}
    555 				fclose( saved );
    556 				fclose( verify );
    557 			}
    558 			XmlTest( "UTF-8: Verified multi-language round trip.", 1, okay );
    559 
    560 			// On most Western machines, this is an element that contains
    561 			// the word "resume" with the correct accents, in a latin encoding.
    562 			// It will be something else completely on non-wester machines,
    563 			// which is why TinyXml is switching to UTF-8.
    564 			const char latin[] = "<element>r\x82sum\x82</element>";
    565 
    566 			TiXmlDocument latinDoc;
    567 			latinDoc.Parse( latin, 0, TIXML_ENCODING_LEGACY );
    568 
    569 			text = latinDoc.FirstChildElement()->FirstChild()->ToText();
    570 			XmlTest( "Legacy encoding: Verify text element.", "r\x82sum\x82", text->Value() );
    571 		}
    572 	}
    573 
    574 	//////////////////////
    575 	// Copy and assignment
    576 	//////////////////////
    577 	printf ("\n** Copy and Assignment **\n");
    578 	{
    579 		TiXmlElement element( "foo" );
    580 		element.Parse( "<element name='value' />", 0, TIXML_ENCODING_UNKNOWN );
    581 
    582 		TiXmlElement elementCopy( element );
    583 		TiXmlElement elementAssign( "foo" );
    584 		elementAssign.Parse( "<incorrect foo='bar'/>", 0, TIXML_ENCODING_UNKNOWN );
    585 		elementAssign = element;
    586 
    587 		XmlTest( "Copy/Assign: element copy #1.", "element", elementCopy.Value() );
    588 		XmlTest( "Copy/Assign: element copy #2.", "value", elementCopy.Attribute( "name" ) );
    589 		XmlTest( "Copy/Assign: element assign #1.", "element", elementAssign.Value() );
    590 		XmlTest( "Copy/Assign: element assign #2.", "value", elementAssign.Attribute( "name" ) );
    591 		XmlTest( "Copy/Assign: element assign #3.", 0, (int) elementAssign.Attribute( "foo" ) );
    592 
    593 		TiXmlComment comment;
    594 		comment.Parse( "<!--comment-->", 0, TIXML_ENCODING_UNKNOWN );
    595 		TiXmlComment commentCopy( comment );
    596 		TiXmlComment commentAssign;
    597 		commentAssign = commentCopy;
    598 		XmlTest( "Copy/Assign: comment copy.", "comment", commentCopy.Value() );
    599 		XmlTest( "Copy/Assign: comment assign.", "comment", commentAssign.Value() );
    600 
    601 		TiXmlUnknown unknown;
    602 		unknown.Parse( "<[unknown]>", 0, TIXML_ENCODING_UNKNOWN );
    603 		TiXmlUnknown unknownCopy( unknown );
    604 		TiXmlUnknown unknownAssign;
    605 		unknownAssign.Parse( "incorrect", 0, TIXML_ENCODING_UNKNOWN );
    606 		unknownAssign = unknownCopy;
    607 		XmlTest( "Copy/Assign: unknown copy.", "[unknown]", unknownCopy.Value() );
    608 		XmlTest( "Copy/Assign: unknown assign.", "[unknown]", unknownAssign.Value() );
    609 
    610 		TiXmlText text( "TextNode" );
    611 		TiXmlText textCopy( text );
    612 		TiXmlText textAssign( "incorrect" );
    613 		textAssign = text;
    614 		XmlTest( "Copy/Assign: text copy.", "TextNode", textCopy.Value() );
    615 		XmlTest( "Copy/Assign: text assign.", "TextNode", textAssign.Value() );
    616 
    617 		TiXmlDeclaration dec;
    618 		dec.Parse( "<?xml version='1.0' encoding='UTF-8'?>", 0, TIXML_ENCODING_UNKNOWN );
    619 		TiXmlDeclaration decCopy( dec );
    620 		TiXmlDeclaration decAssign;
    621 		decAssign = dec;
    622 
    623 		XmlTest( "Copy/Assign: declaration copy.", "UTF-8", decCopy.Encoding() );
    624 		XmlTest( "Copy/Assign: text assign.", "UTF-8", decAssign.Encoding() );
    625 
    626 		TiXmlDocument doc;
    627 		elementCopy.InsertEndChild( textCopy );
    628 		doc.InsertEndChild( decAssign );
    629 		doc.InsertEndChild( elementCopy );
    630 		doc.InsertEndChild( unknownAssign );
    631 
    632 		TiXmlDocument docCopy( doc );
    633 		TiXmlDocument docAssign;
    634 		docAssign = docCopy;
    635 
    636 		#ifdef TIXML_USE_STL
    637 		std::string original, copy, assign;
    638 		original << doc;
    639 		copy << docCopy;
    640 		assign << docAssign;
    641 		XmlTest( "Copy/Assign: document copy.", original.c_str(), copy.c_str(), true );
    642 		XmlTest( "Copy/Assign: document assign.", original.c_str(), assign.c_str(), true );
    643 
    644 		#endif
    645 	}
    646 
    647 	//////////////////////////////////////////////////////
    648 #ifdef TIXML_USE_STL
    649 	printf ("\n** Parsing, no Condense Whitespace **\n");
    650 	TiXmlBase::SetCondenseWhiteSpace( false );
    651 
    652 	istringstream parse1( "<start>This  is    \ntext</start>" );
    653 	TiXmlElement text1( "text" );
    654 	parse1 >> text1;
    655 
    656 	XmlTest ( "Condense white space OFF.", "This  is    \ntext",
    657 				text1.FirstChild()->Value(),
    658 				true );
    659 
    660 	TiXmlBase::SetCondenseWhiteSpace( true );
    661 #endif
    662 
    663 	//////////////////////////////////////////////////////
    664 	// GetText();
    665 	{
    666 		const char* str = "<foo>This is text</foo>";
    667 		TiXmlDocument doc;
    668 		doc.Parse( str );
    669 		const TiXmlElement* element = doc.RootElement();
    670 
    671 		XmlTest( "GetText() normal use.", "This is text", element->GetText() );
    672 
    673 		str = "<foo><b>This is text</b></foo>";
    674 		doc.Clear();
    675 		doc.Parse( str );
    676 		element = doc.RootElement();
    677 
    678 		XmlTest( "GetText() contained element.", element->GetText() == 0, true );
    679 
    680 		str = "<foo>This is <b>text</b></foo>";
    681 		doc.Clear();
    682 		TiXmlBase::SetCondenseWhiteSpace( false );
    683 		doc.Parse( str );
    684 		TiXmlBase::SetCondenseWhiteSpace( true );
    685 		element = doc.RootElement();
    686 
    687 		XmlTest( "GetText() partial.", "This is ", element->GetText() );
    688 	}
    689 
    690 
    691 	//////////////////////////////////////////////////////
    692 	// CDATA
    693 	{
    694 		const char* str =	"<xmlElement>"
    695 								"<![CDATA["
    696 									"I am > the rules!\n"
    697 									"...since I make symbolic puns"
    698 								"]]>"
    699 							"</xmlElement>";
    700 		TiXmlDocument doc;
    701 		doc.Parse( str );
    702 		//doc.Print();
    703 
    704 		XmlTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(),
    705 								 "I am > the rules!\n...since I make symbolic puns",
    706 								 true );
    707 
    708 		#ifdef TIXML_USE_STL
    709 		//cout << doc << '\n';
    710 
    711 		doc.Clear();
    712 
    713 		istringstream parse0( str );
    714 		parse0 >> doc;
    715 		//cout << doc << '\n';
    716 
    717 		XmlTest( "CDATA stream.", doc.FirstChildElement()->FirstChild()->Value(),
    718 								 "I am > the rules!\n...since I make symbolic puns",
    719 								 true );
    720 		#endif
    721 
    722 		TiXmlDocument doc1 = doc;
    723 		//doc.Print();
    724 
    725 		XmlTest( "CDATA copy.", doc1.FirstChildElement()->FirstChild()->Value(),
    726 								 "I am > the rules!\n...since I make symbolic puns",
    727 								 true );
    728 	}
    729 
    730 
    731 	//////////////////////////////////////////////////////
    732 	printf ("\n** Bug regression tests **\n");
    733 
    734 	// InsertBeforeChild and InsertAfterChild causes crash.
    735 	{
    736 		TiXmlElement parent( "Parent" );
    737 		TiXmlElement childText0( "childText0" );
    738 		TiXmlElement childText1( "childText1" );
    739 		TiXmlNode* childNode0 = parent.InsertEndChild( childText0 );
    740 		TiXmlNode* childNode1 = parent.InsertBeforeChild( childNode0, childText1 );
    741 
    742 		XmlTest( "Test InsertBeforeChild on empty node.", ( childNode1 == parent.FirstChild() ), true );
    743 	}
    744 
    745 	{
    746 		// InsertBeforeChild and InsertAfterChild causes crash.
    747 		TiXmlElement parent( "Parent" );
    748 		TiXmlElement childText0( "childText0" );
    749 		TiXmlElement childText1( "childText1" );
    750 		TiXmlNode* childNode0 = parent.InsertEndChild( childText0 );
    751 		TiXmlNode* childNode1 = parent.InsertAfterChild( childNode0, childText1 );
    752 
    753 		XmlTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent.LastChild() ), true );
    754 	}
    755 
    756 	// Reports of missing constructors, irregular string problems.
    757 	{
    758 		// Missing constructor implementation. No test -- just compiles.
    759 		TiXmlText text( "Missing" );
    760 
    761 		#ifdef TIXML_USE_STL
    762 			// Missing implementation:
    763 			TiXmlDocument doc;
    764 			string name = "missing";
    765 			doc.LoadFile( name );
    766 
    767 			TiXmlText textSTL( name );
    768 		#else
    769 			// verifying some basic string functions:
    770 			TiXmlString a;
    771 			TiXmlString b( "Hello" );
    772 			TiXmlString c( "ooga" );
    773 
    774 			c = " World!";
    775 			a = b;
    776 			a += c;
    777 			a = a;
    778 
    779 			XmlTest( "Basic TiXmlString test. ", "Hello World!", a.c_str() );
    780 		#endif
    781  	}
    782 
    783 	// Long filenames crashing STL version
    784 	{
    785 		TiXmlDocument doc( "midsummerNightsDreamWithAVeryLongFilenameToConfuseTheStringHandlingRoutines.xml" );
    786 		bool loadOkay = doc.LoadFile();
    787 		loadOkay = true;	// get rid of compiler warning.
    788 		// Won't pass on non-dev systems. Just a "no crash" check.
    789 		//XmlTest( "Long filename. ", true, loadOkay );
    790 	}
    791 
    792 	{
    793 		// Entities not being written correctly.
    794 		// From Lynn Allen
    795 
    796 		const char* passages =
    797 			"<?xml version=\"1.0\" standalone=\"no\" ?>"
    798 			"<passages count=\"006\" formatversion=\"20020620\">"
    799 				"<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
    800 				" It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
    801 			"</passages>";
    802 
    803 		TiXmlDocument doc( "passages.xml" );
    804 		doc.Parse( passages );
    805 		TiXmlElement* psg = doc.RootElement()->FirstChildElement();
    806 		const char* context = psg->Attribute( "context" );
    807 		const char* expected = "Line 5 has \"quotation marks\" and 'apostrophe marks'. It also has <, >, and &, as well as a fake copyright \xC2\xA9.";
    808 
    809 		XmlTest( "Entity transformation: read. ", expected, context, true );
    810 
    811 		FILE* textfile = fopen( "textfile.txt", "w" );
    812 		if ( textfile )
    813 		{
    814 			psg->Print( textfile, 0 );
    815 			fclose( textfile );
    816 		}
    817 		textfile = fopen( "textfile.txt", "r" );
    818 		assert( textfile );
    819 		if ( textfile )
    820 		{
    821 			char buf[ 1024 ];
    822 			fgets( buf, 1024, textfile );
    823 			XmlTest( "Entity transformation: write. ",
    824 					 "<psg context=\'Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
    825 					 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.' />",
    826 					 buf,
    827 					 true );
    828 		}
    829 		fclose( textfile );
    830 	}
    831 
    832     {
    833 		FILE* textfile = fopen( "test5.xml", "w" );
    834 		if ( textfile )
    835 		{
    836             fputs("<?xml version='1.0'?><a.elem xmi.version='2.0'/>", textfile);
    837             fclose(textfile);
    838 
    839 			TiXmlDocument doc;
    840             doc.LoadFile( "test5.xml" );
    841             XmlTest( "dot in element attributes and names", doc.Error(), 0);
    842 		}
    843     }
    844 
    845 	{
    846 		FILE* textfile = fopen( "test6.xml", "w" );
    847 		if ( textfile )
    848 		{
    849             fputs("<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>", textfile );
    850             fclose(textfile);
    851 
    852             TiXmlDocument doc;
    853             bool result = doc.LoadFile( "test6.xml" );
    854             XmlTest( "Entity with one digit.", result, true );
    855 
    856 			TiXmlText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
    857 			XmlTest( "Entity with one digit.",
    858 						text->Value(), "1.1 Start easy ignore fin thickness\n" );
    859 		}
    860     }
    861 
    862 	{
    863 		// DOCTYPE not preserved (950171)
    864 		//
    865 		const char* doctype =
    866 			"<?xml version=\"1.0\" ?>"
    867 			"<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
    868 			"<!ELEMENT title (#PCDATA)>"
    869 			"<!ELEMENT books (title,authors)>"
    870 			"<element />";
    871 
    872 		TiXmlDocument doc;
    873 		doc.Parse( doctype );
    874 		doc.SaveFile( "test7.xml" );
    875 		doc.Clear();
    876 		doc.LoadFile( "test7.xml" );
    877 
    878 		TiXmlHandle docH( &doc );
    879 		TiXmlUnknown* unknown = docH.Child( 1 ).Unknown();
    880 		XmlTest( "Correct value of unknown.", "!DOCTYPE PLAY SYSTEM 'play.dtd'", unknown->Value() );
    881 		#ifdef TIXML_USE_STL
    882 		TiXmlNode* node = docH.Child( 2 ).Node();
    883 		std::string str;
    884 		str << (*node);
    885 		XmlTest( "Correct streaming of unknown.", "<!ELEMENT title (#PCDATA)>", str.c_str() );
    886 		#endif
    887 	}
    888 
    889 	{
    890 		// [ 791411 ] Formatting bug
    891 		// Comments do not stream out correctly.
    892 		const char* doctype =
    893 			"<!-- Somewhat<evil> -->";
    894 		TiXmlDocument doc;
    895 		doc.Parse( doctype );
    896 
    897 		TiXmlHandle docH( &doc );
    898 		TiXmlComment* comment = docH.Child( 0 ).Node()->ToComment();
    899 
    900 		XmlTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
    901 		#ifdef TIXML_USE_STL
    902 		std::string str;
    903 		str << (*comment);
    904 		XmlTest( "Comment streaming.", "<!-- Somewhat<evil> -->", str.c_str() );
    905 		#endif
    906 	}
    907 
    908 	{
    909 		// [ 870502 ] White space issues
    910 		TiXmlDocument doc;
    911 		TiXmlText* text;
    912 		TiXmlHandle docH( &doc );
    913 
    914 		const char* doctype0 = "<element> This has leading and trailing space </element>";
    915 		const char* doctype1 = "<element>This has  internal space</element>";
    916 		const char* doctype2 = "<element> This has leading, trailing, and  internal space </element>";
    917 
    918 		TiXmlBase::SetCondenseWhiteSpace( false );
    919 		doc.Clear();
    920 		doc.Parse( doctype0 );
    921 		text = docH.FirstChildElement( "element" ).Child( 0 ).Text();
    922 		XmlTest( "White space kept.", " This has leading and trailing space ", text->Value() );
    923 
    924 		doc.Clear();
    925 		doc.Parse( doctype1 );
    926 		text = docH.FirstChildElement( "element" ).Child( 0 ).Text();
    927 		XmlTest( "White space kept.", "This has  internal space", text->Value() );
    928 
    929 		doc.Clear();
    930 		doc.Parse( doctype2 );
    931 		text = docH.FirstChildElement( "element" ).Child( 0 ).Text();
    932 		XmlTest( "White space kept.", " This has leading, trailing, and  internal space ", text->Value() );
    933 
    934 		TiXmlBase::SetCondenseWhiteSpace( true );
    935 		doc.Clear();
    936 		doc.Parse( doctype0 );
    937 		text = docH.FirstChildElement( "element" ).Child( 0 ).Text();
    938 		XmlTest( "White space condensed.", "This has leading and trailing space", text->Value() );
    939 
    940 		doc.Clear();
    941 		doc.Parse( doctype1 );
    942 		text = docH.FirstChildElement( "element" ).Child( 0 ).Text();
    943 		XmlTest( "White space condensed.", "This has internal space", text->Value() );
    944 
    945 		doc.Clear();
    946 		doc.Parse( doctype2 );
    947 		text = docH.FirstChildElement( "element" ).Child( 0 ).Text();
    948 		XmlTest( "White space condensed.", "This has leading, trailing, and internal space", text->Value() );
    949 	}
    950 
    951 	{
    952 		// Double attributes
    953 		const char* doctype = "<element attr='red' attr='blue' />";
    954 
    955 		TiXmlDocument doc;
    956 		doc.Parse( doctype );
    957 
    958 		XmlTest( "Parsing repeated attributes.", 0, (int)doc.Error() );	// not an  error to tinyxml
    959 		XmlTest( "Parsing repeated attributes.", "blue", doc.FirstChildElement( "element" )->Attribute( "attr" ) );
    960 	}
    961 
    962 	{
    963 		// Embedded null in stream.
    964 		const char* doctype = "<element att\0r='red' attr='blue' />";
    965 
    966 		TiXmlDocument doc;
    967 		doc.Parse( doctype );
    968 		XmlTest( "Embedded null throws error.", true, doc.Error() );
    969 
    970 		#ifdef TIXML_USE_STL
    971 		istringstream strm( doctype );
    972 		doc.Clear();
    973 		doc.ClearError();
    974 		strm >> doc;
    975 		XmlTest( "Embedded null throws error.", true, doc.Error() );
    976 		#endif
    977 	}
    978 
    979     {
    980             // Legacy mode test. (This test may only pass on a western system)
    981             const char* str =
    982                         "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>"
    983                         "<>"
    984                         "Cntnt"
    985                         "</>";
    986 
    987             TiXmlDocument doc;
    988             doc.Parse( str );
    989 
    990 			//doc.Print( stdout, 0 );
    991 
    992             TiXmlHandle docHandle( &doc );
    993             TiXmlHandle aHandle = docHandle.FirstChildElement( "" );
    994             TiXmlHandle tHandle = aHandle.Child( 0 );
    995             assert( aHandle.Element() );
    996             assert( tHandle.Text() );
    997             XmlTest( "ISO-8859-1 Parsing.", "Cntnt", tHandle.Text()->Value() );
    998     }
    999 
   1000 	{
   1001 		// Empty documents should return TIXML_ERROR_PARSING_EMPTY, bug 1070717
   1002 		const char* str = "    ";
   1003 		TiXmlDocument doc;
   1004 		doc.Parse( str );
   1005 		XmlTest( "Empty document error TIXML_ERROR_DOCUMENT_EMPTY", TiXmlBase::TIXML_ERROR_DOCUMENT_EMPTY, doc.ErrorId() );
   1006 	}
   1007 	#ifndef TIXML_USE_STL
   1008 	{
   1009 		// String equality. [ 1006409 ] string operator==/!= no worky in all cases
   1010 		TiXmlString temp;
   1011 		XmlTest( "Empty tinyxml string compare equal", ( temp == "" ), true );
   1012 
   1013 		TiXmlString    foo;
   1014 		TiXmlString    bar( "" );
   1015 		XmlTest( "Empty tinyxml string compare equal", ( foo == bar ), true );
   1016 	}
   1017 
   1018 	#endif
   1019 	{
   1020 		// Bug [ 1195696 ] from marlonism
   1021 		TiXmlBase::SetCondenseWhiteSpace(false);
   1022 		TiXmlDocument xml;
   1023 		xml.Parse("<text><break/>This hangs</text>");
   1024 		XmlTest( "Test safe error return.", xml.Error(), false );
   1025 	}
   1026 
   1027 	{
   1028 		// Bug [ 1243992 ] - another infinite loop
   1029 		TiXmlDocument doc;
   1030 		doc.SetCondenseWhiteSpace(false);
   1031 		doc.Parse("<p><pb></pb>test</p>");
   1032 	}
   1033 	{
   1034 		// Low entities
   1035 		TiXmlDocument xml;
   1036 		xml.Parse( "<test>&#x0e;</test>" );
   1037 		const char result[] = { 0x0e, 0 };
   1038 		XmlTest( "Low entities.", xml.FirstChildElement()->GetText(), result );
   1039 		xml.Print();
   1040 	}
   1041 
   1042 	#if defined( WIN32 ) && defined( TUNE )
   1043 	QueryPerformanceCounter( (LARGE_INTEGER*) (&end) );
   1044 	QueryPerformanceFrequency( (LARGE_INTEGER*) (&freq) );
   1045 	printf( "Time for run: %f\n", ( double )( end-start ) / (double) freq );
   1046 	#endif
   1047 
   1048 	printf ("\nPass %d, Fail %d\n", gPass, gFail);
   1049 	return gFail;
   1050 }
   1051 
   1052 
   1053