xmltest.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. #include "tinyxml.h"
  2. #include <iostream>
  3. #include <sstream>
  4. #include <strstream>
  5. using namespace std;
  6. int gPass = 0;
  7. int gFail = 0;
  8. // Utility functions:
  9. template< class T >
  10. bool XmlTest( const char* testString, T expected, T found, bool noEcho = false )
  11. {
  12. if ( expected == found )
  13. cout << "[pass]";
  14. else
  15. cout << "[fail]";
  16. if ( noEcho )
  17. cout << " " << testString;
  18. else
  19. cout << " " << testString << " [" << expected << "][" << found << "]";
  20. cout << "\n";
  21. bool pass = ( expected == found );
  22. if ( pass )
  23. ++gPass;
  24. else
  25. ++gFail;
  26. return pass;
  27. }
  28. //
  29. // This file demonstrates some basic functionality of TinyXml.
  30. // Note that the example is very contrived. It presumes you know
  31. // what is in the XML file. But it does test the basic operations,
  32. // and show how to add and remove nodes.
  33. //
  34. int main()
  35. {
  36. //
  37. // We start with the 'demoStart' todo list. Process it. And
  38. // should hopefully end up with the todo list as illustrated.
  39. //
  40. const char* demoStart =
  41. "<?xml version=\"1.0\" standalone='no' >\n"
  42. "<!-- Our to do list data -->"
  43. "<ToDo>\n"
  44. "<!-- Do I need a secure PDA? -->\n"
  45. "<Item priority=\"1\" distance='close'> Go to the <bold>Toy store!</bold></Item>"
  46. "<Item priority=\"2\" distance='none'> Do bills </Item>"
  47. "<Item priority=\"2\" distance='far &amp; back'> Look for Evil Dinosaurs! </Item>"
  48. "</ToDo>";
  49. /* What the todo list should look like after processing.
  50. In stream (no formatting) representation. */
  51. const char* demoEnd =
  52. "<?xml version=\"1.0\" standalone=\"no\" ?>"
  53. "<!-- Our to do list data -->"
  54. "<ToDo>"
  55. "<!-- Do I need a secure PDA? -->"
  56. "<Item priority=\"2\" distance=\"close\">Go to the"
  57. "<bold>Toy store!"
  58. "</bold>"
  59. "</Item>"
  60. "<Item priority=\"1\" distance=\"far\">Talk to:"
  61. "<Meeting where=\"School\">"
  62. "<Attendee name=\"Marple\" position=\"teacher\" />"
  63. "<Attendee name=\"Vo&#x82;\" position=\"counselor\" />"
  64. "</Meeting>"
  65. "<Meeting where=\"Lunch\" />"
  66. "</Item>"
  67. "<Item priority=\"2\" distance=\"here\">Do bills"
  68. "</Item>"
  69. "</ToDo>";
  70. // The example parses from the character string (above):
  71. {
  72. // Write to a file and read it back, to check file I/O.
  73. TiXmlDocument doc( "demotest.xml" );
  74. doc.Parse( demoStart );
  75. if ( doc.Error() )
  76. {
  77. printf( "Error in %s: %s\n", doc.Value().c_str(), doc.ErrorDesc().c_str() );
  78. exit( 1 );
  79. }
  80. doc.SaveFile();
  81. }
  82. TiXmlDocument doc( "demotest.xml" );
  83. bool loadOkay = doc.LoadFile();
  84. if ( !loadOkay )
  85. {
  86. printf( "Could not load test file 'demotest.xml'. Error='%s'. Exiting.\n", doc.ErrorDesc().c_str() );
  87. exit( 1 );
  88. }
  89. printf( "** Demo doc read from disk: ** \n\n" );
  90. doc.Print( stdout );
  91. TiXmlNode* node = 0;
  92. TiXmlElement* todoElement = 0;
  93. TiXmlElement* itemElement = 0;
  94. // --------------------------------------------------------
  95. // An example of changing existing attributes, and removing
  96. // an element from the document.
  97. // --------------------------------------------------------
  98. // Get the "ToDo" element.
  99. // It is a child of the document, and can be selected by name.
  100. node = doc.FirstChild( "ToDo" );
  101. assert( node );
  102. todoElement = node->ToElement();
  103. assert( todoElement );
  104. // Going to the toy store is now our second priority...
  105. // So set the "priority" attribute of the first item in the list.
  106. node = todoElement->FirstChildElement(); // This skips the "PDA" comment.
  107. assert( node );
  108. itemElement = node->ToElement();
  109. assert( itemElement );
  110. itemElement->SetAttribute( "priority", 2 );
  111. // Change the distance to "doing bills" from
  112. // "none" to "here". It's the next sibling element.
  113. itemElement = itemElement->NextSiblingElement();
  114. assert( itemElement );
  115. itemElement->SetAttribute( "distance", "here" );
  116. // Remove the "Look for Evil Dinosours!" item.
  117. // It is 1 more sibling away. We ask the parent to remove
  118. // a particular child.
  119. itemElement = itemElement->NextSiblingElement();
  120. todoElement->RemoveChild( itemElement );
  121. itemElement = 0;
  122. // --------------------------------------------------------
  123. // What follows is an example of created elements and text
  124. // nodes and adding them to the document.
  125. // --------------------------------------------------------
  126. // Add some meetings.
  127. TiXmlElement item( "Item" );
  128. item.SetAttribute( "priority", "1" );
  129. item.SetAttribute( "distance", "far" );
  130. TiXmlText text( "Talk to:" );
  131. TiXmlElement meeting1( "Meeting" );
  132. meeting1.SetAttribute( "where", "School" );
  133. TiXmlElement meeting2( "Meeting" );
  134. meeting2.SetAttribute( "where", "Lunch" );
  135. TiXmlElement attendee1( "Attendee" );
  136. attendee1.SetAttribute( "name", "Marple" );
  137. attendee1.SetAttribute( "position", "teacher" );
  138. TiXmlElement attendee2( "Attendee" );
  139. attendee2.SetAttribute( "name", "Vo&#x82;" );
  140. attendee2.SetAttribute( "position", "counselor" );
  141. // Assemble the nodes we've created:
  142. meeting1.InsertEndChild( attendee1 );
  143. meeting1.InsertEndChild( attendee2 );
  144. item.InsertEndChild( text );
  145. item.InsertEndChild( meeting1 );
  146. item.InsertEndChild( meeting2 );
  147. // And add the node to the existing list after the first child.
  148. node = todoElement->FirstChild( "Item" );
  149. assert( node );
  150. itemElement = node->ToElement();
  151. assert( itemElement );
  152. todoElement->InsertAfterChild( itemElement, item );
  153. printf( "\n** Demo doc processed: ** \n\n" );
  154. doc.Print( stdout );
  155. printf( "** Demo doc processed to stream: ** \n\n" );
  156. cout << doc << endl << endl;
  157. // --------------------------------------------------------
  158. // Different tests...do we have what we expect?
  159. // --------------------------------------------------------
  160. int count = 0;
  161. TiXmlElement* element;
  162. //////////////////////////////////////////////////////
  163. cout << "** Basic structure. **\n";
  164. ostringstream outputStream( ostringstream::out );
  165. outputStream << doc;
  166. XmlTest( "Output stream correct.", string( demoEnd ), outputStream.str(), true );
  167. node = doc.RootElement();
  168. XmlTest( "Root element exists.", true, ( node != 0 && node->ToElement() ) );
  169. XmlTest( "Root element value is 'ToDo'.", string( "ToDo" ), node->Value() );
  170. node = node->FirstChild();
  171. XmlTest( "First child exists & is a comment.", true, ( node != 0 && node->ToComment() ) );
  172. node = node->NextSibling();
  173. XmlTest( "Sibling element exists & is an element.", true, ( node != 0 && node->ToElement() ) );
  174. XmlTest( "Value is 'Item'.", string( "Item" ), node->Value() );
  175. node = node->FirstChild();
  176. XmlTest( "First child exists.", true, ( node != 0 && node->ToText() ) );
  177. XmlTest( "Value is 'Go to the'.", string( "Go to the" ), node->Value() );
  178. //////////////////////////////////////////////////////
  179. cout << "\n** Iterators. **" << "\n";
  180. // Walk all the top level nodes of the document.
  181. count = 0;
  182. for( node = doc.FirstChild();
  183. node;
  184. node = node->NextSibling() )
  185. {
  186. count++;
  187. }
  188. XmlTest( "Top level nodes, using First / Next.", 3, count );
  189. count = 0;
  190. for( node = doc.LastChild();
  191. node;
  192. node = node->PreviousSibling() )
  193. {
  194. count++;
  195. }
  196. XmlTest( "Top level nodes, using Last / Previous.", 3, count );
  197. // Walk all the top level nodes of the document,
  198. // using a different sytax.
  199. count = 0;
  200. for( node = doc.IterateChildren( 0 );
  201. node;
  202. node = doc.IterateChildren( node ) )
  203. {
  204. count++;
  205. }
  206. XmlTest( "Top level nodes, using IterateChildren.", 3, count );
  207. // Walk all the elements in a node.
  208. count = 0;
  209. for( element = todoElement->FirstChildElement();
  210. element;
  211. element = element->NextSiblingElement() )
  212. {
  213. count++;
  214. }
  215. XmlTest( "Children of the 'ToDo' element, using First / Next.",
  216. 3, count );
  217. // Walk all the elements in a node by value.
  218. count = 0;
  219. for( node = todoElement->FirstChild( "Item" );
  220. node;
  221. node = node->NextSibling( "Item" ) )
  222. {
  223. count++;
  224. }
  225. XmlTest( "'Item' children of the 'ToDo' element, using First/Next.", 3, count );
  226. count = 0;
  227. for( node = todoElement->LastChild( "Item" );
  228. node;
  229. node = node->PreviousSibling( "Item" ) )
  230. {
  231. count++;
  232. }
  233. XmlTest( "'Item' children of the 'ToDo' element, using Last/Previous.", 3, count );
  234. //////////////////////////////////////////////////////
  235. cout << "\n** Parsing. **\n";
  236. istringstream parse0( "<Element0 attribute0='foo0' attribute1= noquotes attribute2 = '&gt;' />" );
  237. TiXmlElement element0( "default" );
  238. parse0 >> element0;
  239. XmlTest( "Element parsed, value is 'Element0'.", string( "Element0" ), element0.Value() );
  240. XmlTest( "Reads attribute 'attribute0=\"foo0\"'.", string( "foo0" ), *( element0.Attribute( "attribute0" ) ) );
  241. XmlTest( "Reads incorrectly formatted 'attribute1=noquotes'.", string( "noquotes" ), *( element0.Attribute( "attribute1" ) ) );
  242. XmlTest( "Read attribute with entity value '>'.", string( ">" ), *( element0.Attribute( "attribute2" ) ) );
  243. //////////////////////////////////////////////////////
  244. cout << "\n** Streaming. **\n";
  245. // Round trip check: stream in, then stream back out to verify. The stream
  246. // out has already been checked, above. We use the output
  247. istringstream inputStringStream( outputStream.str() );
  248. TiXmlDocument document0;
  249. inputStringStream >> document0;
  250. ostringstream outputStream0( ostringstream::out );
  251. outputStream0 << document0;
  252. XmlTest( "Stream round trip correct.", string( demoEnd ), outputStream0.str(), true );
  253. //////////////////////////////////////////////////////
  254. cout << "\n** Parsing, no Condense Whitespace **\n";
  255. TiXmlBase::SetCondenseWhiteSpace( false );
  256. istringstream parse1( "<start>This is \ntext</start>" );
  257. TiXmlElement text1( "text" );
  258. parse1 >> text1;
  259. XmlTest( "Condense white space OFF.", string( "This is \ntext" ),
  260. text1.FirstChild()->Value(),
  261. true );
  262. cout << endl << "Pass " << gPass << ", Fail " << gFail << endl;
  263. return 0;
  264. }