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