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