/ticpp/tutorial_gettingStarted.txt

http://cssmatch-plugin.googlecode.com/ · Plain Text · 835 lines · 675 code · 160 blank · 0 comment · 0 complexity · a733faf286e2eca40e7be289af1b43e1 MD5 · raw file

  1. /** @page tutorial0 TinyXML Tutorial
  2. <h1> What is this? </h1>
  3. This tutorial has a few tips and suggestions on how to use TinyXML
  4. effectively.
  5. I've also tried to include some C++ tips like how to convert strings to
  6. integers and vice versa. This isn't anything to do with TinyXML itself, but
  7. it may helpful for your project so I've put it in anyway.
  8. If you don't know basic C++ concepts this tutorial won't be useful.
  9. Likewise if you don't know what a DOM is, look elsewhere first.
  10. <h1> Before we start </h1>
  11. Some example XML datasets/files will be used.
  12. example1.xml:
  13. @verbatim
  14. <?xml version="1.0" ?>
  15. <Hello>World</Hello>
  16. @endverbatim
  17. example2.xml:
  18. @verbatim
  19. <?xml version="1.0" ?>
  20. <poetry>
  21. <verse>
  22. Alas
  23. Great World
  24. Alas (again)
  25. </verse>
  26. </poetry>
  27. @endverbatim
  28. example3.xml:
  29. @verbatim
  30. <?xml version="1.0" ?>
  31. <shapes>
  32. <circle name="int-based" x="20" y="30" r="50" />
  33. <point name="float-based" x="3.5" y="52.1" />
  34. </shapes>
  35. @endverbatim
  36. example4.xml
  37. @verbatim
  38. <?xml version="1.0" ?>
  39. <MyApp>
  40. <!-- Settings for MyApp -->
  41. <Messages>
  42. <Welcome>Welcome to MyApp</Welcome>
  43. <Farewell>Thank you for using MyApp</Farewell>
  44. </Messages>
  45. <Windows>
  46. <Window name="MainFrame" x="5" y="15" w="400" h="250" />
  47. </Windows>
  48. <Connection ip="192.168.0.1" timeout="123.456000" />
  49. </MyApp>
  50. @endverbatim
  51. <h1> Getting Started </h1>
  52. <h2> Load XML from a file </h2>
  53. The simplest way to load a file into a TinyXML DOM is:
  54. @verbatim
  55. TiXmlDocument doc( "demo.xml" );
  56. doc.LoadFile();
  57. @endverbatim
  58. A more real-world usage is shown below. This will load the file and display
  59. the contents to STDOUT:
  60. @verbatim
  61. // load the named file and dump its structure to STDOUT
  62. void dump_to_stdout(const char* pFilename)
  63. {
  64. TiXmlDocument doc(pFilename);
  65. bool loadOkay = doc.LoadFile();
  66. if (loadOkay)
  67. {
  68. printf("\n%s:\n", pFilename);
  69. dump_to_stdout( &doc ); // defined later in the tutorial
  70. }
  71. else
  72. {
  73. printf("Failed to load file \"%s\"\n", pFilename);
  74. }
  75. }
  76. @endverbatim
  77. A simple demonstration of this function is to use a main like this:
  78. @verbatim
  79. int main(void)
  80. {
  81. dump_to_stdout("example1.xml");
  82. return 0;
  83. }
  84. @endverbatim
  85. Recall that Example 1 XML is:
  86. @verbatim
  87. <?xml version="1.0" ?>
  88. <Hello>World</Hello>
  89. @endverbatim
  90. Running the program with this XML will display this in the console/DOS window:
  91. @verbatim
  92. DOCUMENT
  93. + DECLARATION
  94. + ELEMENT Hello
  95. + TEXT[World]
  96. @endverbatim
  97. The ``dump_to_stdout`` function is defined later in this tutorial and is
  98. useful if you want to understand recursive traversal of a DOM.
  99. <h2> Building Documents Programatically </h2>
  100. This is how to build Example 1 pragmatically:
  101. @verbatim
  102. void build_simple_doc( )
  103. {
  104. // Make xml: <?xml ..><Hello>World</Hello>
  105. TiXmlDocument doc;
  106. TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "" );
  107. TiXmlElement * element = new TiXmlElement( "Hello" );
  108. TiXmlText * text = new TiXmlText( "World" );
  109. element->LinkEndChild( text );
  110. doc.LinkEndChild( decl );
  111. doc.LinkEndChild( element );
  112. doc.SaveFile( "madeByHand.xml" );
  113. }
  114. @endverbatim
  115. This can be loaded and displayed on the console with:
  116. @verbatim
  117. dump_to_stdout("madeByHand.xml"); // this func defined later in the tutorial
  118. @endverbatim
  119. and you'll see it is identical to Example 1:
  120. @verbatim
  121. madeByHand.xml:
  122. Document
  123. + Declaration
  124. + Element [Hello]
  125. + Text: [World]
  126. @endverbatim
  127. This code produces exactly the same XML DOM but it shows a different ordering
  128. to node creation and linking:
  129. @verbatim
  130. void write_simple_doc2( )
  131. {
  132. // same as write_simple_doc1 but add each node
  133. // as early as possible into the tree.
  134. TiXmlDocument doc;
  135. TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "" );
  136. doc.LinkEndChild( decl );
  137. TiXmlElement * element = new TiXmlElement( "Hello" );
  138. doc.LinkEndChild( element );
  139. TiXmlText * text = new TiXmlText( "World" );
  140. element->LinkEndChild( text );
  141. doc.SaveFile( "madeByHand2.xml" );
  142. }
  143. @endverbatim
  144. Both of these produce the same XML, namely:
  145. @verbatim
  146. <?xml version="1.0" ?>
  147. <Hello>World</Hello>
  148. @endverbatim
  149. Or in structure form:
  150. @verbatim
  151. DOCUMENT
  152. + DECLARATION
  153. + ELEMENT Hello
  154. + TEXT[World]
  155. @endverbatim
  156. <h2> Attributes </h2>
  157. Given an existing node, settings attributes is easy:
  158. @verbatim
  159. window = new TiXmlElement( "Demo" );
  160. window->SetAttribute("name", "Circle");
  161. window->SetAttribute("x", 5);
  162. window->SetAttribute("y", 15);
  163. window->SetDoubleAttribute("radius", 3.14159);
  164. @endverbatim
  165. You can it also work with the TiXmlAttribute objects if you want.
  166. The following code shows one way (not the only way) to get all attributes of an
  167. element, print the name and string value, and if the value can be converted
  168. to an integer or double, print that value too:
  169. @verbatim
  170. // print all attributes of pElement.
  171. // returns the number of attributes printed
  172. int dump_attribs_to_stdout(TiXmlElement* pElement, unsigned int indent)
  173. {
  174. if ( !pElement ) return 0;
  175. TiXmlAttribute* pAttrib=pElement->FirstAttribute();
  176. int i=0;
  177. int ival;
  178. double dval;
  179. const char* pIndent=getIndent(indent);
  180. printf("\n");
  181. while (pAttrib)
  182. {
  183. printf( "%s%s: value=[%s]", pIndent, pAttrib->Name(), pAttrib->Value());
  184. if (pAttrib->QueryIntValue(&ival)==TIXML_SUCCESS) printf( " int=%d", ival);
  185. if (pAttrib->QueryDoubleValue(&dval)==TIXML_SUCCESS) printf( " d=%1.1f", dval);
  186. printf( "\n" );
  187. i++;
  188. pAttrib=pAttrib->Next();
  189. }
  190. return i;
  191. }
  192. @endverbatim
  193. <h2> Writing a document to a file </h2>
  194. Writing a pre-built DOM to a file is trivial:
  195. @verbatim
  196. doc.SaveFile( saveFilename );
  197. @endverbatim
  198. Recall, for example, example 4:
  199. @verbatim
  200. <?xml version="1.0" ?>
  201. <MyApp>
  202. <!-- Settings for MyApp -->
  203. <Messages>
  204. <Welcome>Welcome to MyApp</Welcome>
  205. <Farewell>Thank you for using MyApp</Farewell>
  206. </Messages>
  207. <Windows>
  208. <Window name="MainFrame" x="5" y="15" w="400" h="250" />
  209. </Windows>
  210. <Connection ip="192.168.0.1" timeout="123.456000" />
  211. </MyApp>
  212. @endverbatim
  213. The following function builds this DOM and writes the file "appsettings.xml":
  214. @verbatim
  215. void write_app_settings_doc( )
  216. {
  217. TiXmlDocument doc;
  218. TiXmlElement* msg;
  219. TiXmlDeclaration* decl = new TiXmlDeclaration( "1.0", "", "" );
  220. doc.LinkEndChild( decl );
  221. TiXmlElement * root = new TiXmlElement( "MyApp" );
  222. doc.LinkEndChild( root );
  223. TiXmlComment * comment = new TiXmlComment();
  224. comment->SetValue(" Settings for MyApp " );
  225. root->LinkEndChild( comment );
  226. TiXmlElement * msgs = new TiXmlElement( "Messages" );
  227. root->LinkEndChild( msgs );
  228. msg = new TiXmlElement( "Welcome" );
  229. msg->LinkEndChild( new TiXmlText( "Welcome to MyApp" ));
  230. msgs->LinkEndChild( msg );
  231. msg = new TiXmlElement( "Farewell" );
  232. msg->LinkEndChild( new TiXmlText( "Thank you for using MyApp" ));
  233. msgs->LinkEndChild( msg );
  234. TiXmlElement * windows = new TiXmlElement( "Windows" );
  235. root->LinkEndChild( windows );
  236. TiXmlElement * window;
  237. window = new TiXmlElement( "Window" );
  238. windows->LinkEndChild( window );
  239. window->SetAttribute("name", "MainFrame");
  240. window->SetAttribute("x", 5);
  241. window->SetAttribute("y", 15);
  242. window->SetAttribute("w", 400);
  243. window->SetAttribute("h", 250);
  244. TiXmlElement * cxn = new TiXmlElement( "Connection" );
  245. root->LinkEndChild( cxn );
  246. cxn->SetAttribute("ip", "192.168.0.1");
  247. cxn->SetDoubleAttribute("timeout", 123.456); // floating point attrib
  248. dump_to_stdout( &doc );
  249. doc.SaveFile( "appsettings.xml" );
  250. }
  251. @endverbatim
  252. The dump_to_stdout function will show this structure:
  253. @verbatim
  254. Document
  255. + Declaration
  256. + Element [MyApp]
  257. (No attributes)
  258. + Comment: [ Settings for MyApp ]
  259. + Element [Messages]
  260. (No attributes)
  261. + Element [Welcome]
  262. (No attributes)
  263. + Text: [Welcome to MyApp]
  264. + Element [Farewell]
  265. (No attributes)
  266. + Text: [Thank you for using MyApp]
  267. + Element [Windows]
  268. (No attributes)
  269. + Element [Window]
  270. + name: value=[MainFrame]
  271. + x: value=[5] int=5 d=5.0
  272. + y: value=[15] int=15 d=15.0
  273. + w: value=[400] int=400 d=400.0
  274. + h: value=[250] int=250 d=250.0
  275. 5 attributes
  276. + Element [Connection]
  277. + ip: value=[192.168.0.1] int=192 d=192.2
  278. + timeout: value=[123.456000] int=123 d=123.5
  279. 2 attributes
  280. @endverbatim
  281. I was surprised that TinyXml, by default, writes the XML in what other
  282. APIs call a "pretty" format - it modifies the whitespace of text of elements
  283. that contain other nodes so that writing the tree includes an indication of
  284. nesting level.
  285. I haven't looked yet to see if there is a way to turn off indenting when
  286. writing a file - its bound to be easy.
  287. [Lee: It's easy in STL mode, just use cout << myDoc. Non-STL mode is
  288. always in "pretty" format. Adding a switch would be a nice feature and
  289. has been requested.]
  290. <h1> XML to/from C++ objects </h1>
  291. <h2> Intro </h2>
  292. This example assumes you're loading and saving your app settings in an
  293. XML file, e.g. something like example4.xml.
  294. There are a number of ways to do this. For example, look into the TinyBind
  295. project at http://sourceforge.net/projects/tinybind
  296. This section shows a plain-old approach to loading and saving a basic object
  297. structure using XML.
  298. <h2> Set up your object classes </h2>
  299. Start off with some basic classes like these:
  300. @verbatim
  301. #include <string>
  302. #include <map>
  303. using namespace std;
  304. typedef std::map<std::string,std::string> MessageMap;
  305. // a basic window abstraction - demo purposes only
  306. class WindowSettings
  307. {
  308. public:
  309. int x,y,w,h;
  310. string name;
  311. WindowSettings()
  312. : x(0), y(0), w(100), h(100), name("Untitled")
  313. {
  314. }
  315. WindowSettings(int x, int y, int w, int h, const string& name)
  316. {
  317. this->x=x;
  318. this->y=y;
  319. this->w=w;
  320. this->h=h;
  321. this->name=name;
  322. }
  323. };
  324. class ConnectionSettings
  325. {
  326. public:
  327. string ip;
  328. double timeout;
  329. };
  330. class AppSettings
  331. {
  332. public:
  333. string m_name;
  334. MessageMap m_messages;
  335. list<WindowSettings> m_windows;
  336. ConnectionSettings m_connection;
  337. AppSettings() {}
  338. void save(const char* pFilename);
  339. void load(const char* pFilename);
  340. // just to show how to do it
  341. void setDemoValues()
  342. {
  343. m_name="MyApp";
  344. m_messages.clear();
  345. m_messages["Welcome"]="Welcome to "+m_name;
  346. m_messages["Farewell"]="Thank you for using "+m_name;
  347. m_windows.clear();
  348. m_windows.push_back(WindowSettings(15,15,400,250,"Main"));
  349. m_connection.ip="Unknown";
  350. m_connection.timeout=123.456;
  351. }
  352. };
  353. @endverbatim
  354. This is a basic main() that shows how to create a default settings object tree,
  355. save it and load it again:
  356. @verbatim
  357. int main(void)
  358. {
  359. AppSettings settings;
  360. settings.save("appsettings2.xml");
  361. settings.load("appsettings2.xml");
  362. return 0;
  363. }
  364. @endverbatim
  365. The following main() shows creation, modification, saving and then loading of a
  366. settings structure:
  367. @verbatim
  368. int main(void)
  369. {
  370. // block: customise and save settings
  371. {
  372. AppSettings settings;
  373. settings.m_name="HitchHikerApp";
  374. settings.m_messages["Welcome"]="Don't Panic";
  375. settings.m_messages["Farewell"]="Thanks for all the fish";
  376. settings.m_windows.push_back(WindowSettings(15,25,300,250,"BookFrame"));
  377. settings.m_connection.ip="192.168.0.77";
  378. settings.m_connection.timeout=42.0;
  379. settings.save("appsettings2.xml");
  380. }
  381. // block: load settings
  382. {
  383. AppSettings settings;
  384. settings.load("appsettings2.xml");
  385. printf("%s: %s\n", settings.m_name.c_str(),
  386. settings.m_messages["Welcome"].c_str());
  387. WindowSettings & w=settings.m_windows.front();
  388. printf("%s: Show window '%s' at %d,%d (%d x %d)\n",
  389. settings.m_name.c_str(), w.name.c_str(), w.x, w.y, w.w, w.h);
  390. printf("%s: %s\n", settings.m_name.c_str(), settings.m_messages["Farewell"].c_str());
  391. }
  392. return 0;
  393. }
  394. @endverbatim
  395. When the save() and load() are completed (see below), running this main()
  396. displays on the console:
  397. @verbatim
  398. HitchHikerApp: Don't Panic
  399. HitchHikerApp: Show window 'BookFrame' at 15,25 (300 x 100)
  400. HitchHikerApp: Thanks for all the fish
  401. @endverbatim
  402. <h2> Encode C++ state as XML </h2>
  403. There are lots of different ways to approach saving this to a file.
  404. Here's one:
  405. @verbatim
  406. void AppSettings::save(const char* pFilename)
  407. {
  408. TiXmlDocument doc;
  409. TiXmlElement* msg;
  410. TiXmlComment * comment;
  411. string s;
  412. TiXmlDeclaration* decl = new TiXmlDeclaration( "1.0", "", "" );
  413. doc.LinkEndChild( decl );
  414. TiXmlElement * root = new TiXmlElement(m_name.c_str());
  415. doc.LinkEndChild( root );
  416. comment = new TiXmlComment();
  417. s=" Settings for "+m_name+" ";
  418. comment->SetValue(s.c_str());
  419. root->LinkEndChild( comment );
  420. // block: messages
  421. {
  422. MessageMap::iterator iter;
  423. TiXmlElement * msgs = new TiXmlElement( "Messages" );
  424. root->LinkEndChild( msgs );
  425. for (iter=m_messages.begin(); iter != m_messages.end(); iter++)
  426. {
  427. const string & key=(*iter).first;
  428. const string & value=(*iter).second;
  429. msg = new TiXmlElement(key.c_str());
  430. msg->LinkEndChild( new TiXmlText(value.c_str()));
  431. msgs->LinkEndChild( msg );
  432. }
  433. }
  434. // block: windows
  435. {
  436. TiXmlElement * windowsNode = new TiXmlElement( "Windows" );
  437. root->LinkEndChild( windowsNode );
  438. list<WindowSettings>::iterator iter;
  439. for (iter=m_windows.begin(); iter != m_windows.end(); iter++)
  440. {
  441. const WindowSettings& w=*iter;
  442. TiXmlElement * window;
  443. window = new TiXmlElement( "Window" );
  444. windowsNode->LinkEndChild( window );
  445. window->SetAttribute("name", w.name.c_str());
  446. window->SetAttribute("x", w.x);
  447. window->SetAttribute("y", w.y);
  448. window->SetAttribute("w", w.w);
  449. window->SetAttribute("h", w.h);
  450. }
  451. }
  452. // block: connection
  453. {
  454. TiXmlElement * cxn = new TiXmlElement( "Connection" );
  455. root->LinkEndChild( cxn );
  456. cxn->SetAttribute("ip", m_connection.ip.c_str());
  457. cxn->SetDoubleAttribute("timeout", m_connection.timeout);
  458. }
  459. doc.SaveFile(pFilename);
  460. }
  461. @endverbatim
  462. Running this with the modified main produces this file:
  463. @verbatim
  464. <?xml version="1.0" ?>
  465. <HitchHikerApp>
  466. <!-- Settings for HitchHikerApp -->
  467. <Messages>
  468. <Farewell>Thanks for all the fish</Farewell>
  469. <Welcome>Don&apos;t Panic</Welcome>
  470. </Messages>
  471. <Windows>
  472. <Window name="BookFrame" x="15" y="25" w="300" h="250" />
  473. </Windows>
  474. <Connection ip="192.168.0.77" timeout="42.000000" />
  475. </HitchHikerApp>
  476. @endverbatim
  477. <h2> Decoding state from XML </h2>
  478. As with encoding objects, there are a number of approaches to decoding XML
  479. into your own C++ object structure. The following approach uses TiXmlHandles.
  480. @verbatim
  481. void AppSettings::load(const char* pFilename)
  482. {
  483. TiXmlDocument doc(pFilename);
  484. if (!doc.LoadFile()) return;
  485. TiXmlHandle hDoc(&doc);
  486. TiXmlElement* pElem;
  487. TiXmlHandle hRoot(0);
  488. // block: name
  489. {
  490. pElem=hDoc.FirstChildElement().Element();
  491. // should always have a valid root but handle gracefully if it does
  492. if (!pElem) return;
  493. m_name=pElem->Value();
  494. // save this for later
  495. hRoot=TiXmlHandle(pElem);
  496. }
  497. // block: string table
  498. {
  499. m_messages.clear(); // trash existing table
  500. pElem=hRoot.FirstChild( "Messages" ).FirstChild().Element();
  501. for( pElem; pElem; pElem=pElem->NextSiblingElement())
  502. {
  503. const char *pKey=pElem->Value();
  504. const char *pText=pElem->GetText();
  505. if (pKey && pText)
  506. {
  507. m_messages[pKey]=pText;
  508. }
  509. }
  510. }
  511. // block: windows
  512. {
  513. m_windows.clear(); // trash existing list
  514. TiXmlElement* pWindowNode=hRoot.FirstChild( "Windows" ).FirstChild().Element();
  515. for( pWindowNode; pWindowNode; pWindowNode=pWindowNode->NextSiblingElement())
  516. {
  517. WindowSettings w;
  518. const char *pName=pWindowNode->Attribute("name");
  519. if (pName) w.name=pName;
  520. pWindowNode->QueryIntAttribute("x", &w.x); // If this fails, original value is left as-is
  521. pWindowNode->QueryIntAttribute("y", &w.y);
  522. pWindowNode->QueryIntAttribute("w", &w.w);
  523. pWindowNode->QueryIntAttribute("hh", &w.h);
  524. m_windows.push_back(w);
  525. }
  526. }
  527. // block: connection
  528. {
  529. pElem=hRoot.FirstChild("Connection").Element();
  530. if (pElem)
  531. {
  532. m_connection.ip=pElem->Attribute("ip");
  533. pElem->QueryDoubleAttribute("timeout",&m_connection.timeout);
  534. }
  535. }
  536. }
  537. @endverbatim
  538. <h1> Full listing for dump_to_stdout </h1>
  539. Below is a copy-and-paste demo program for loading arbitrary XML files and
  540. dumping the structure to STDOUT using the recursive traversal listed above.
  541. @verbatim
  542. // tutorial demo program
  543. #include "stdafx.h"
  544. #include "tinyxml.h"
  545. // ----------------------------------------------------------------------
  546. // STDOUT dump and indenting utility functions
  547. // ----------------------------------------------------------------------
  548. const unsigned int NUM_INDENTS_PER_SPACE=2;
  549. const char * getIndent( unsigned int numIndents )
  550. {
  551. static const char * pINDENT=" + ";
  552. static const unsigned int LENGTH=strlen( pINDENT );
  553. unsigned int n=numIndents*NUM_INDENTS_PER_SPACE;
  554. if ( n > LENGTH ) n = LENGTH;
  555. return &pINDENT[ LENGTH-n ];
  556. }
  557. // same as getIndent but no "+" at the end
  558. const char * getIndentAlt( unsigned int numIndents )
  559. {
  560. static const char * pINDENT=" ";
  561. static const unsigned int LENGTH=strlen( pINDENT );
  562. unsigned int n=numIndents*NUM_INDENTS_PER_SPACE;
  563. if ( n > LENGTH ) n = LENGTH;
  564. return &pINDENT[ LENGTH-n ];
  565. }
  566. int dump_attribs_to_stdout(TiXmlElement* pElement, unsigned int indent)
  567. {
  568. if ( !pElement ) return 0;
  569. TiXmlAttribute* pAttrib=pElement->FirstAttribute();
  570. int i=0;
  571. int ival;
  572. double dval;
  573. const char* pIndent=getIndent(indent);
  574. printf("\n");
  575. while (pAttrib)
  576. {
  577. printf( "%s%s: value=[%s]", pIndent, pAttrib->Name(), pAttrib->Value());
  578. if (pAttrib->QueryIntValue(&ival)==TIXML_SUCCESS) printf( " int=%d", ival);
  579. if (pAttrib->QueryDoubleValue(&dval)==TIXML_SUCCESS) printf( " d=%1.1f", dval);
  580. printf( "\n" );
  581. i++;
  582. pAttrib=pAttrib->Next();
  583. }
  584. return i;
  585. }
  586. void dump_to_stdout( TiXmlNode* pParent, unsigned int indent = 0 )
  587. {
  588. if ( !pParent ) return;
  589. TiXmlNode* pChild;
  590. TiXmlText* pText;
  591. int t = pParent->Type();
  592. printf( "%s", getIndent(indent));
  593. int num;
  594. switch ( t )
  595. {
  596. case TiXmlNode::DOCUMENT:
  597. printf( "Document" );
  598. break;
  599. case TiXmlNode::ELEMENT:
  600. printf( "Element [%s]", pParent->Value() );
  601. num=dump_attribs_to_stdout(pParent->ToElement(), indent+1);
  602. switch(num)
  603. {
  604. case 0: printf( " (No attributes)"); break;
  605. case 1: printf( "%s1 attribute", getIndentAlt(indent)); break;
  606. default: printf( "%s%d attributes", getIndentAlt(indent), num); break;
  607. }
  608. break;
  609. case TiXmlNode::COMMENT:
  610. printf( "Comment: [%s]", pParent->Value());
  611. break;
  612. case TiXmlNode::UNKNOWN:
  613. printf( "Unknown" );
  614. break;
  615. case TiXmlNode::TEXT:
  616. pText = pParent->ToText();
  617. printf( "Text: [%s]", pText->Value() );
  618. break;
  619. case TiXmlNode::DECLARATION:
  620. printf( "Declaration" );
  621. break;
  622. default:
  623. break;
  624. }
  625. printf( "\n" );
  626. for ( pChild = pParent->FirstChild(); pChild != 0; pChild = pChild->NextSibling())
  627. {
  628. dump_to_stdout( pChild, indent+1 );
  629. }
  630. }
  631. // load the named file and dump its structure to STDOUT
  632. void dump_to_stdout(const char* pFilename)
  633. {
  634. TiXmlDocument doc(pFilename);
  635. bool loadOkay = doc.LoadFile();
  636. if (loadOkay)
  637. {
  638. printf("\n%s:\n", pFilename);
  639. dump_to_stdout( &doc ); // defined later in the tutorial
  640. }
  641. else
  642. {
  643. printf("Failed to load file \"%s\"\n", pFilename);
  644. }
  645. }
  646. // ----------------------------------------------------------------------
  647. // main() for printing files named on the command line
  648. // ----------------------------------------------------------------------
  649. int main(int argc, char* argv[])
  650. {
  651. for (int i=1; i<argc; i++)
  652. {
  653. dump_to_stdout(argv[i]);
  654. }
  655. return 0;
  656. }
  657. @endverbatim
  658. Run this from the command line or a DOS window, e.g.:
  659. @verbatim
  660. C:\dev\tinyxml> Debug\tinyxml_1.exe example1.xml
  661. example1.xml:
  662. Document
  663. + Declaration
  664. + Element [Hello]
  665. (No attributes)
  666. + Text: [World]
  667. @endverbatim
  668. <i> Authors and Changes
  669. <ul>
  670. <li> Written by Ellers, April, May, June 2005 </li>
  671. <li> Minor edits and integration into doc system, Lee Thomason September 2005 </li>
  672. <li> Updated by Ellers, October 2005 </li>
  673. </ul>
  674. </i>
  675. */