xref: /third_party/lame/ACM/tinyxml/xmltest.cpp (revision 159b3361)
1#include "tinyxml.h"
2#include <iostream>
3#include <sstream>
4#include <strstream>
5using namespace std;
6
7int gPass = 0;
8int gFail = 0;
9
10// Utility functions:
11template< class T >
12bool 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
41int 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