1159b3361Sopenharmony_ci#include "tinyxml.h" 2159b3361Sopenharmony_ci#include <iostream> 3159b3361Sopenharmony_ci#include <sstream> 4159b3361Sopenharmony_ci#include <strstream> 5159b3361Sopenharmony_ciusing namespace std; 6159b3361Sopenharmony_ci 7159b3361Sopenharmony_ciint gPass = 0; 8159b3361Sopenharmony_ciint gFail = 0; 9159b3361Sopenharmony_ci 10159b3361Sopenharmony_ci// Utility functions: 11159b3361Sopenharmony_citemplate< class T > 12159b3361Sopenharmony_cibool XmlTest( const char* testString, T expected, T found, bool noEcho = false ) 13159b3361Sopenharmony_ci{ 14159b3361Sopenharmony_ci if ( expected == found ) 15159b3361Sopenharmony_ci cout << "[pass]"; 16159b3361Sopenharmony_ci else 17159b3361Sopenharmony_ci cout << "[fail]"; 18159b3361Sopenharmony_ci 19159b3361Sopenharmony_ci if ( noEcho ) 20159b3361Sopenharmony_ci cout << " " << testString; 21159b3361Sopenharmony_ci else 22159b3361Sopenharmony_ci cout << " " << testString << " [" << expected << "][" << found << "]"; 23159b3361Sopenharmony_ci cout << "\n"; 24159b3361Sopenharmony_ci 25159b3361Sopenharmony_ci bool pass = ( expected == found ); 26159b3361Sopenharmony_ci if ( pass ) 27159b3361Sopenharmony_ci ++gPass; 28159b3361Sopenharmony_ci else 29159b3361Sopenharmony_ci ++gFail; 30159b3361Sopenharmony_ci return pass; 31159b3361Sopenharmony_ci} 32159b3361Sopenharmony_ci 33159b3361Sopenharmony_ci 34159b3361Sopenharmony_ci// 35159b3361Sopenharmony_ci// This file demonstrates some basic functionality of TinyXml. 36159b3361Sopenharmony_ci// Note that the example is very contrived. It presumes you know 37159b3361Sopenharmony_ci// what is in the XML file. But it does test the basic operations, 38159b3361Sopenharmony_ci// and show how to add and remove nodes. 39159b3361Sopenharmony_ci// 40159b3361Sopenharmony_ci 41159b3361Sopenharmony_ciint main() 42159b3361Sopenharmony_ci{ 43159b3361Sopenharmony_ci // 44159b3361Sopenharmony_ci // We start with the 'demoStart' todo list. Process it. And 45159b3361Sopenharmony_ci // should hopefully end up with the todo list as illustrated. 46159b3361Sopenharmony_ci // 47159b3361Sopenharmony_ci const char* demoStart = 48159b3361Sopenharmony_ci "<?xml version=\"1.0\" standalone='no' >\n" 49159b3361Sopenharmony_ci "<!-- Our to do list data -->" 50159b3361Sopenharmony_ci "<ToDo>\n" 51159b3361Sopenharmony_ci "<!-- Do I need a secure PDA? -->\n" 52159b3361Sopenharmony_ci "<Item priority=\"1\" distance='close'> Go to the <bold>Toy store!</bold></Item>" 53159b3361Sopenharmony_ci "<Item priority=\"2\" distance='none'> Do bills </Item>" 54159b3361Sopenharmony_ci "<Item priority=\"2\" distance='far & back'> Look for Evil Dinosaurs! </Item>" 55159b3361Sopenharmony_ci "</ToDo>"; 56159b3361Sopenharmony_ci 57159b3361Sopenharmony_ci /* What the todo list should look like after processing. 58159b3361Sopenharmony_ci In stream (no formatting) representation. */ 59159b3361Sopenharmony_ci const char* demoEnd = 60159b3361Sopenharmony_ci "<?xml version=\"1.0\" standalone=\"no\" ?>" 61159b3361Sopenharmony_ci "<!-- Our to do list data -->" 62159b3361Sopenharmony_ci "<ToDo>" 63159b3361Sopenharmony_ci "<!-- Do I need a secure PDA? -->" 64159b3361Sopenharmony_ci "<Item priority=\"2\" distance=\"close\">Go to the" 65159b3361Sopenharmony_ci "<bold>Toy store!" 66159b3361Sopenharmony_ci "</bold>" 67159b3361Sopenharmony_ci "</Item>" 68159b3361Sopenharmony_ci "<Item priority=\"1\" distance=\"far\">Talk to:" 69159b3361Sopenharmony_ci "<Meeting where=\"School\">" 70159b3361Sopenharmony_ci "<Attendee name=\"Marple\" position=\"teacher\" />" 71159b3361Sopenharmony_ci "<Attendee name=\"Vo‚\" position=\"counselor\" />" 72159b3361Sopenharmony_ci "</Meeting>" 73159b3361Sopenharmony_ci "<Meeting where=\"Lunch\" />" 74159b3361Sopenharmony_ci "</Item>" 75159b3361Sopenharmony_ci "<Item priority=\"2\" distance=\"here\">Do bills" 76159b3361Sopenharmony_ci "</Item>" 77159b3361Sopenharmony_ci "</ToDo>"; 78159b3361Sopenharmony_ci 79159b3361Sopenharmony_ci // The example parses from the character string (above): 80159b3361Sopenharmony_ci 81159b3361Sopenharmony_ci { 82159b3361Sopenharmony_ci // Write to a file and read it back, to check file I/O. 83159b3361Sopenharmony_ci 84159b3361Sopenharmony_ci TiXmlDocument doc( "demotest.xml" ); 85159b3361Sopenharmony_ci doc.Parse( demoStart ); 86159b3361Sopenharmony_ci 87159b3361Sopenharmony_ci if ( doc.Error() ) 88159b3361Sopenharmony_ci { 89159b3361Sopenharmony_ci printf( "Error in %s: %s\n", doc.Value().c_str(), doc.ErrorDesc().c_str() ); 90159b3361Sopenharmony_ci exit( 1 ); 91159b3361Sopenharmony_ci } 92159b3361Sopenharmony_ci doc.SaveFile(); 93159b3361Sopenharmony_ci } 94159b3361Sopenharmony_ci 95159b3361Sopenharmony_ci TiXmlDocument doc( "demotest.xml" ); 96159b3361Sopenharmony_ci bool loadOkay = doc.LoadFile(); 97159b3361Sopenharmony_ci 98159b3361Sopenharmony_ci if ( !loadOkay ) 99159b3361Sopenharmony_ci { 100159b3361Sopenharmony_ci printf( "Could not load test file 'demotest.xml'. Error='%s'. Exiting.\n", doc.ErrorDesc().c_str() ); 101159b3361Sopenharmony_ci exit( 1 ); 102159b3361Sopenharmony_ci } 103159b3361Sopenharmony_ci 104159b3361Sopenharmony_ci printf( "** Demo doc read from disk: ** \n\n" ); 105159b3361Sopenharmony_ci doc.Print( stdout ); 106159b3361Sopenharmony_ci 107159b3361Sopenharmony_ci TiXmlNode* node = 0; 108159b3361Sopenharmony_ci TiXmlElement* todoElement = 0; 109159b3361Sopenharmony_ci TiXmlElement* itemElement = 0; 110159b3361Sopenharmony_ci 111159b3361Sopenharmony_ci 112159b3361Sopenharmony_ci // -------------------------------------------------------- 113159b3361Sopenharmony_ci // An example of changing existing attributes, and removing 114159b3361Sopenharmony_ci // an element from the document. 115159b3361Sopenharmony_ci // -------------------------------------------------------- 116159b3361Sopenharmony_ci 117159b3361Sopenharmony_ci // Get the "ToDo" element. 118159b3361Sopenharmony_ci // It is a child of the document, and can be selected by name. 119159b3361Sopenharmony_ci node = doc.FirstChild( "ToDo" ); 120159b3361Sopenharmony_ci assert( node ); 121159b3361Sopenharmony_ci todoElement = node->ToElement(); 122159b3361Sopenharmony_ci assert( todoElement ); 123159b3361Sopenharmony_ci 124159b3361Sopenharmony_ci // Going to the toy store is now our second priority... 125159b3361Sopenharmony_ci // So set the "priority" attribute of the first item in the list. 126159b3361Sopenharmony_ci node = todoElement->FirstChildElement(); // This skips the "PDA" comment. 127159b3361Sopenharmony_ci assert( node ); 128159b3361Sopenharmony_ci itemElement = node->ToElement(); 129159b3361Sopenharmony_ci assert( itemElement ); 130159b3361Sopenharmony_ci itemElement->SetAttribute( "priority", 2 ); 131159b3361Sopenharmony_ci 132159b3361Sopenharmony_ci // Change the distance to "doing bills" from 133159b3361Sopenharmony_ci // "none" to "here". It's the next sibling element. 134159b3361Sopenharmony_ci itemElement = itemElement->NextSiblingElement(); 135159b3361Sopenharmony_ci assert( itemElement ); 136159b3361Sopenharmony_ci itemElement->SetAttribute( "distance", "here" ); 137159b3361Sopenharmony_ci 138159b3361Sopenharmony_ci // Remove the "Look for Evil Dinosours!" item. 139159b3361Sopenharmony_ci // It is 1 more sibling away. We ask the parent to remove 140159b3361Sopenharmony_ci // a particular child. 141159b3361Sopenharmony_ci itemElement = itemElement->NextSiblingElement(); 142159b3361Sopenharmony_ci todoElement->RemoveChild( itemElement ); 143159b3361Sopenharmony_ci 144159b3361Sopenharmony_ci itemElement = 0; 145159b3361Sopenharmony_ci 146159b3361Sopenharmony_ci // -------------------------------------------------------- 147159b3361Sopenharmony_ci // What follows is an example of created elements and text 148159b3361Sopenharmony_ci // nodes and adding them to the document. 149159b3361Sopenharmony_ci // -------------------------------------------------------- 150159b3361Sopenharmony_ci 151159b3361Sopenharmony_ci // Add some meetings. 152159b3361Sopenharmony_ci TiXmlElement item( "Item" ); 153159b3361Sopenharmony_ci item.SetAttribute( "priority", "1" ); 154159b3361Sopenharmony_ci item.SetAttribute( "distance", "far" ); 155159b3361Sopenharmony_ci 156159b3361Sopenharmony_ci TiXmlText text( "Talk to:" ); 157159b3361Sopenharmony_ci 158159b3361Sopenharmony_ci TiXmlElement meeting1( "Meeting" ); 159159b3361Sopenharmony_ci meeting1.SetAttribute( "where", "School" ); 160159b3361Sopenharmony_ci 161159b3361Sopenharmony_ci TiXmlElement meeting2( "Meeting" ); 162159b3361Sopenharmony_ci meeting2.SetAttribute( "where", "Lunch" ); 163159b3361Sopenharmony_ci 164159b3361Sopenharmony_ci TiXmlElement attendee1( "Attendee" ); 165159b3361Sopenharmony_ci attendee1.SetAttribute( "name", "Marple" ); 166159b3361Sopenharmony_ci attendee1.SetAttribute( "position", "teacher" ); 167159b3361Sopenharmony_ci 168159b3361Sopenharmony_ci TiXmlElement attendee2( "Attendee" ); 169159b3361Sopenharmony_ci attendee2.SetAttribute( "name", "Vo‚" ); 170159b3361Sopenharmony_ci attendee2.SetAttribute( "position", "counselor" ); 171159b3361Sopenharmony_ci 172159b3361Sopenharmony_ci // Assemble the nodes we've created: 173159b3361Sopenharmony_ci meeting1.InsertEndChild( attendee1 ); 174159b3361Sopenharmony_ci meeting1.InsertEndChild( attendee2 ); 175159b3361Sopenharmony_ci 176159b3361Sopenharmony_ci item.InsertEndChild( text ); 177159b3361Sopenharmony_ci item.InsertEndChild( meeting1 ); 178159b3361Sopenharmony_ci item.InsertEndChild( meeting2 ); 179159b3361Sopenharmony_ci 180159b3361Sopenharmony_ci // And add the node to the existing list after the first child. 181159b3361Sopenharmony_ci node = todoElement->FirstChild( "Item" ); 182159b3361Sopenharmony_ci assert( node ); 183159b3361Sopenharmony_ci itemElement = node->ToElement(); 184159b3361Sopenharmony_ci assert( itemElement ); 185159b3361Sopenharmony_ci 186159b3361Sopenharmony_ci todoElement->InsertAfterChild( itemElement, item ); 187159b3361Sopenharmony_ci 188159b3361Sopenharmony_ci printf( "\n** Demo doc processed: ** \n\n" ); 189159b3361Sopenharmony_ci doc.Print( stdout ); 190159b3361Sopenharmony_ci 191159b3361Sopenharmony_ci printf( "** Demo doc processed to stream: ** \n\n" ); 192159b3361Sopenharmony_ci cout << doc << endl << endl; 193159b3361Sopenharmony_ci 194159b3361Sopenharmony_ci // -------------------------------------------------------- 195159b3361Sopenharmony_ci // Different tests...do we have what we expect? 196159b3361Sopenharmony_ci // -------------------------------------------------------- 197159b3361Sopenharmony_ci 198159b3361Sopenharmony_ci int count = 0; 199159b3361Sopenharmony_ci TiXmlElement* element; 200159b3361Sopenharmony_ci 201159b3361Sopenharmony_ci ////////////////////////////////////////////////////// 202159b3361Sopenharmony_ci cout << "** Basic structure. **\n"; 203159b3361Sopenharmony_ci ostringstream outputStream( ostringstream::out ); 204159b3361Sopenharmony_ci outputStream << doc; 205159b3361Sopenharmony_ci 206159b3361Sopenharmony_ci XmlTest( "Output stream correct.", string( demoEnd ), outputStream.str(), true ); 207159b3361Sopenharmony_ci 208159b3361Sopenharmony_ci node = doc.RootElement(); 209159b3361Sopenharmony_ci XmlTest( "Root element exists.", true, ( node != 0 && node->ToElement() ) ); 210159b3361Sopenharmony_ci XmlTest( "Root element value is 'ToDo'.", string( "ToDo" ), node->Value() ); 211159b3361Sopenharmony_ci node = node->FirstChild(); 212159b3361Sopenharmony_ci XmlTest( "First child exists & is a comment.", true, ( node != 0 && node->ToComment() ) ); 213159b3361Sopenharmony_ci node = node->NextSibling(); 214159b3361Sopenharmony_ci XmlTest( "Sibling element exists & is an element.", true, ( node != 0 && node->ToElement() ) ); 215159b3361Sopenharmony_ci XmlTest( "Value is 'Item'.", string( "Item" ), node->Value() ); 216159b3361Sopenharmony_ci node = node->FirstChild(); 217159b3361Sopenharmony_ci XmlTest( "First child exists.", true, ( node != 0 && node->ToText() ) ); 218159b3361Sopenharmony_ci XmlTest( "Value is 'Go to the'.", string( "Go to the" ), node->Value() ); 219159b3361Sopenharmony_ci 220159b3361Sopenharmony_ci 221159b3361Sopenharmony_ci ////////////////////////////////////////////////////// 222159b3361Sopenharmony_ci cout << "\n** Iterators. **" << "\n"; 223159b3361Sopenharmony_ci // Walk all the top level nodes of the document. 224159b3361Sopenharmony_ci count = 0; 225159b3361Sopenharmony_ci for( node = doc.FirstChild(); 226159b3361Sopenharmony_ci node; 227159b3361Sopenharmony_ci node = node->NextSibling() ) 228159b3361Sopenharmony_ci { 229159b3361Sopenharmony_ci count++; 230159b3361Sopenharmony_ci } 231159b3361Sopenharmony_ci XmlTest( "Top level nodes, using First / Next.", 3, count ); 232159b3361Sopenharmony_ci 233159b3361Sopenharmony_ci count = 0; 234159b3361Sopenharmony_ci for( node = doc.LastChild(); 235159b3361Sopenharmony_ci node; 236159b3361Sopenharmony_ci node = node->PreviousSibling() ) 237159b3361Sopenharmony_ci { 238159b3361Sopenharmony_ci count++; 239159b3361Sopenharmony_ci } 240159b3361Sopenharmony_ci XmlTest( "Top level nodes, using Last / Previous.", 3, count ); 241159b3361Sopenharmony_ci 242159b3361Sopenharmony_ci // Walk all the top level nodes of the document, 243159b3361Sopenharmony_ci // using a different sytax. 244159b3361Sopenharmony_ci count = 0; 245159b3361Sopenharmony_ci for( node = doc.IterateChildren( 0 ); 246159b3361Sopenharmony_ci node; 247159b3361Sopenharmony_ci node = doc.IterateChildren( node ) ) 248159b3361Sopenharmony_ci { 249159b3361Sopenharmony_ci count++; 250159b3361Sopenharmony_ci } 251159b3361Sopenharmony_ci XmlTest( "Top level nodes, using IterateChildren.", 3, count ); 252159b3361Sopenharmony_ci 253159b3361Sopenharmony_ci // Walk all the elements in a node. 254159b3361Sopenharmony_ci count = 0; 255159b3361Sopenharmony_ci for( element = todoElement->FirstChildElement(); 256159b3361Sopenharmony_ci element; 257159b3361Sopenharmony_ci element = element->NextSiblingElement() ) 258159b3361Sopenharmony_ci { 259159b3361Sopenharmony_ci count++; 260159b3361Sopenharmony_ci } 261159b3361Sopenharmony_ci XmlTest( "Children of the 'ToDo' element, using First / Next.", 262159b3361Sopenharmony_ci 3, count ); 263159b3361Sopenharmony_ci 264159b3361Sopenharmony_ci // Walk all the elements in a node by value. 265159b3361Sopenharmony_ci count = 0; 266159b3361Sopenharmony_ci for( node = todoElement->FirstChild( "Item" ); 267159b3361Sopenharmony_ci node; 268159b3361Sopenharmony_ci node = node->NextSibling( "Item" ) ) 269159b3361Sopenharmony_ci { 270159b3361Sopenharmony_ci count++; 271159b3361Sopenharmony_ci } 272159b3361Sopenharmony_ci XmlTest( "'Item' children of the 'ToDo' element, using First/Next.", 3, count ); 273159b3361Sopenharmony_ci 274159b3361Sopenharmony_ci count = 0; 275159b3361Sopenharmony_ci for( node = todoElement->LastChild( "Item" ); 276159b3361Sopenharmony_ci node; 277159b3361Sopenharmony_ci node = node->PreviousSibling( "Item" ) ) 278159b3361Sopenharmony_ci { 279159b3361Sopenharmony_ci count++; 280159b3361Sopenharmony_ci } 281159b3361Sopenharmony_ci XmlTest( "'Item' children of the 'ToDo' element, using Last/Previous.", 3, count ); 282159b3361Sopenharmony_ci 283159b3361Sopenharmony_ci 284159b3361Sopenharmony_ci ////////////////////////////////////////////////////// 285159b3361Sopenharmony_ci cout << "\n** Parsing. **\n"; 286159b3361Sopenharmony_ci istringstream parse0( "<Element0 attribute0='foo0' attribute1= noquotes attribute2 = '>' />" ); 287159b3361Sopenharmony_ci TiXmlElement element0( "default" ); 288159b3361Sopenharmony_ci parse0 >> element0; 289159b3361Sopenharmony_ci 290159b3361Sopenharmony_ci XmlTest( "Element parsed, value is 'Element0'.", string( "Element0" ), element0.Value() ); 291159b3361Sopenharmony_ci XmlTest( "Reads attribute 'attribute0=\"foo0\"'.", string( "foo0" ), *( element0.Attribute( "attribute0" ) ) ); 292159b3361Sopenharmony_ci XmlTest( "Reads incorrectly formatted 'attribute1=noquotes'.", string( "noquotes" ), *( element0.Attribute( "attribute1" ) ) ); 293159b3361Sopenharmony_ci XmlTest( "Read attribute with entity value '>'.", string( ">" ), *( element0.Attribute( "attribute2" ) ) ); 294159b3361Sopenharmony_ci 295159b3361Sopenharmony_ci ////////////////////////////////////////////////////// 296159b3361Sopenharmony_ci cout << "\n** Streaming. **\n"; 297159b3361Sopenharmony_ci 298159b3361Sopenharmony_ci // Round trip check: stream in, then stream back out to verify. The stream 299159b3361Sopenharmony_ci // out has already been checked, above. We use the output 300159b3361Sopenharmony_ci 301159b3361Sopenharmony_ci istringstream inputStringStream( outputStream.str() ); 302159b3361Sopenharmony_ci TiXmlDocument document0; 303159b3361Sopenharmony_ci 304159b3361Sopenharmony_ci inputStringStream >> document0; 305159b3361Sopenharmony_ci 306159b3361Sopenharmony_ci ostringstream outputStream0( ostringstream::out ); 307159b3361Sopenharmony_ci outputStream0 << document0; 308159b3361Sopenharmony_ci 309159b3361Sopenharmony_ci XmlTest( "Stream round trip correct.", string( demoEnd ), outputStream0.str(), true ); 310159b3361Sopenharmony_ci 311159b3361Sopenharmony_ci ////////////////////////////////////////////////////// 312159b3361Sopenharmony_ci cout << "\n** Parsing, no Condense Whitespace **\n"; 313159b3361Sopenharmony_ci TiXmlBase::SetCondenseWhiteSpace( false ); 314159b3361Sopenharmony_ci 315159b3361Sopenharmony_ci istringstream parse1( "<start>This is \ntext</start>" ); 316159b3361Sopenharmony_ci TiXmlElement text1( "text" ); 317159b3361Sopenharmony_ci parse1 >> text1; 318159b3361Sopenharmony_ci 319159b3361Sopenharmony_ci XmlTest( "Condense white space OFF.", string( "This is \ntext" ), 320159b3361Sopenharmony_ci text1.FirstChild()->Value(), 321159b3361Sopenharmony_ci true ); 322159b3361Sopenharmony_ci 323159b3361Sopenharmony_ci cout << endl << "Pass " << gPass << ", Fail " << gFail << endl; 324159b3361Sopenharmony_ci return 0; 325159b3361Sopenharmony_ci} 326159b3361Sopenharmony_ci 327