blob: 1ec46c13d5ee7e0f60de48f188d5696a8cdccbd8 [file] [log] [blame]
Upstreambc0ee9a1970-01-12 13:46:40 +00001/*
2 Test program for TinyXML.
3*/
4
5
6#include "tinyxml.h"
7
8#ifdef TIXML_USE_STL
9 #include <iostream>
10 #include <sstream>
11 using namespace std;
12#else
13 #include <stdio.h>
14#endif
15
16#if defined( WIN32 ) && defined( TUNE )
Karsten Tausched1438212022-10-06 15:20:50 +020017 #include <crtdbg.h>
18 _CrtMemState startMemState;
19 _CrtMemState endMemState;
Upstreambc0ee9a1970-01-12 13:46:40 +000020#endif
21
22static int gPass = 0;
23static int gFail = 0;
24
25
26bool XmlTest (const char* testString, const char* expected, const char* found, bool noEcho = false)
27{
28 bool pass = !strcmp( expected, found );
29 if ( pass )
30 printf ("[pass]");
31 else
32 printf ("[fail]");
33
34 if ( noEcho )
35 printf (" %s\n", testString);
36 else
37 printf (" %s [%s][%s]\n", testString, expected, found);
38
39 if ( pass )
40 ++gPass;
41 else
42 ++gFail;
43 return pass;
44}
45
46
47bool XmlTest( const char* testString, int expected, int found, bool noEcho = false )
48{
49 bool pass = ( expected == found );
50 if ( pass )
51 printf ("[pass]");
52 else
53 printf ("[fail]");
54
55 if ( noEcho )
56 printf (" %s\n", testString);
57 else
58 printf (" %s [%d][%d]\n", testString, expected, found);
59
60 if ( pass )
61 ++gPass;
62 else
63 ++gFail;
64 return pass;
65}
66
67
68//
69// This file demonstrates some basic functionality of TinyXml.
70// Note that the example is very contrived. It presumes you know
71// what is in the XML file. But it does test the basic operations,
72// and show how to add and remove nodes.
73//
74
75int main()
76{
77 //
78 // We start with the 'demoStart' todo list. Process it. And
79 // should hopefully end up with the todo list as illustrated.
80 //
81 const char* demoStart =
82 "<?xml version=\"1.0\" standalone='no' >\n"
83 "<!-- Our to do list data -->"
84 "<ToDo>\n"
85 "<!-- Do I need a secure PDA? -->\n"
86 "<Item priority=\"1\" distance='close'> Go to the <bold>Toy store!</bold></Item>"
87 "<Item priority=\"2\" distance='none'> Do bills </Item>"
88 "<Item priority=\"2\" distance='far &amp; back'> Look for Evil Dinosaurs! </Item>"
89 "</ToDo>";
90
91#ifdef TIXML_USE_STL
92 /* What the todo list should look like after processing.
93 In stream (no formatting) representation. */
94 const char* demoEnd =
95 "<?xml version=\"1.0\" standalone=\"no\" ?>"
96 "<!-- Our to do list data -->"
97 "<ToDo>"
98 "<!-- Do I need a secure PDA? -->"
99 "<Item priority=\"2\" distance=\"close\">Go to the"
100 "<bold>Toy store!"
101 "</bold>"
102 "</Item>"
103 "<Item priority=\"1\" distance=\"far\">Talk to:"
104 "<Meeting where=\"School\">"
105 "<Attendee name=\"Marple\" position=\"teacher\" />"
106 "<Attendee name=\"Voel\" position=\"counselor\" />"
107 "</Meeting>"
108 "<Meeting where=\"Lunch\" />"
109 "</Item>"
110 "<Item priority=\"2\" distance=\"here\">Do bills"
111 "</Item>"
112 "</ToDo>";
113#endif
114
115 // The example parses from the character string (above):
116 #if defined( WIN32 ) && defined( TUNE )
Karsten Tausched1438212022-10-06 15:20:50 +0200117 _CrtMemCheckpoint( &startMemState );
Upstreambc0ee9a1970-01-12 13:46:40 +0000118 #endif
119
120 {
121 // Write to a file and read it back, to check file I/O.
122
123 TiXmlDocument doc( "demotest.xml" );
124 doc.Parse( demoStart );
125
126 if ( doc.Error() )
127 {
128 printf( "Error in %s: %s\n", doc.Value(), doc.ErrorDesc() );
129 exit( 1 );
130 }
131 doc.SaveFile();
132 }
133
134 TiXmlDocument doc( "demotest.xml" );
135 bool loadOkay = doc.LoadFile();
136
137 if ( !loadOkay )
138 {
139 printf( "Could not load test file 'demotest.xml'. Error='%s'. Exiting.\n", doc.ErrorDesc() );
140 exit( 1 );
141 }
142
143 printf( "** Demo doc read from disk: ** \n\n" );
144 doc.Print( stdout );
145
146 TiXmlNode* node = 0;
147 TiXmlElement* todoElement = 0;
148 TiXmlElement* itemElement = 0;
149
150
151 // --------------------------------------------------------
152 // An example of changing existing attributes, and removing
153 // an element from the document.
154 // --------------------------------------------------------
155
156 // Get the "ToDo" element.
157 // It is a child of the document, and can be selected by name.
158 node = doc.FirstChild( "ToDo" );
159 assert( node );
160 todoElement = node->ToElement();
161 assert( todoElement );
162
163 // Going to the toy store is now our second priority...
164 // So set the "priority" attribute of the first item in the list.
165 node = todoElement->FirstChildElement(); // This skips the "PDA" comment.
166 assert( node );
167 itemElement = node->ToElement();
168 assert( itemElement );
169 itemElement->SetAttribute( "priority", 2 );
170
171 // Change the distance to "doing bills" from
172 // "none" to "here". It's the next sibling element.
173 itemElement = itemElement->NextSiblingElement();
174 assert( itemElement );
175 itemElement->SetAttribute( "distance", "here" );
176
177 // Remove the "Look for Evil Dinosaurs!" item.
178 // It is 1 more sibling away. We ask the parent to remove
179 // a particular child.
180 itemElement = itemElement->NextSiblingElement();
181 todoElement->RemoveChild( itemElement );
182
183 itemElement = 0;
184
185 // --------------------------------------------------------
186 // What follows is an example of created elements and text
187 // nodes and adding them to the document.
188 // --------------------------------------------------------
189
190 // Add some meetings.
191 TiXmlElement item( "Item" );
192 item.SetAttribute( "priority", "1" );
193 item.SetAttribute( "distance", "far" );
194
195 TiXmlText text( "Talk to:" );
196
197 TiXmlElement meeting1( "Meeting" );
198 meeting1.SetAttribute( "where", "School" );
199
200 TiXmlElement meeting2( "Meeting" );
201 meeting2.SetAttribute( "where", "Lunch" );
202
203 TiXmlElement attendee1( "Attendee" );
204 attendee1.SetAttribute( "name", "Marple" );
205 attendee1.SetAttribute( "position", "teacher" );
206
207 TiXmlElement attendee2( "Attendee" );
208 attendee2.SetAttribute( "name", "Voel" );
209 attendee2.SetAttribute( "position", "counselor" );
210
211 // Assemble the nodes we've created:
212 meeting1.InsertEndChild( attendee1 );
213 meeting1.InsertEndChild( attendee2 );
214
215 item.InsertEndChild( text );
216 item.InsertEndChild( meeting1 );
217 item.InsertEndChild( meeting2 );
218
219 // And add the node to the existing list after the first child.
220 node = todoElement->FirstChild( "Item" );
221 assert( node );
222 itemElement = node->ToElement();
223 assert( itemElement );
224
225 todoElement->InsertAfterChild( itemElement, item );
226
227 printf( "\n** Demo doc processed: ** \n\n" );
228 doc.Print( stdout );
229
230
231#ifdef TIXML_USE_STL
232 printf( "** Demo doc processed to stream: ** \n\n" );
233 cout << doc << endl << endl;
234#endif
235
236 // --------------------------------------------------------
237 // Different tests...do we have what we expect?
238 // --------------------------------------------------------
239
240 int count = 0;
241 TiXmlElement* element;
242
243 //////////////////////////////////////////////////////
244
245#ifdef TIXML_USE_STL
246 cout << "** Basic structure. **\n";
247 ostringstream outputStream( ostringstream::out );
248 outputStream << doc;
249 XmlTest( "Output stream correct.", string( demoEnd ).c_str(),
250 outputStream.str().c_str(), true );
251#endif
252
253 node = doc.RootElement();
254 XmlTest( "Root element exists.", true, ( node != 0 && node->ToElement() ) );
255 XmlTest ( "Root element value is 'ToDo'.", "ToDo", node->Value());
256
257 node = node->FirstChild();
258 XmlTest( "First child exists & is a comment.", true, ( node != 0 && node->ToComment() ) );
259 node = node->NextSibling();
260 XmlTest( "Sibling element exists & is an element.", true, ( node != 0 && node->ToElement() ) );
261 XmlTest ( "Value is 'Item'.", "Item", node->Value() );
262
263 node = node->FirstChild();
264 XmlTest ( "First child exists.", true, ( node != 0 && node->ToText() ) );
265 XmlTest ( "Value is 'Go to the'.", "Go to the", node->Value() );
266
267
268 //////////////////////////////////////////////////////
269 printf ("\n** Iterators. **\n");
270
271 // Walk all the top level nodes of the document.
272 count = 0;
273 for( node = doc.FirstChild();
274 node;
275 node = node->NextSibling() )
276 {
277 count++;
278 }
279 XmlTest( "Top level nodes, using First / Next.", 3, count );
280
281 count = 0;
282 for( node = doc.LastChild();
283 node;
284 node = node->PreviousSibling() )
285 {
286 count++;
287 }
288 XmlTest( "Top level nodes, using Last / Previous.", 3, count );
289
290 // Walk all the top level nodes of the document,
291 // using a different syntax.
292 count = 0;
293 for( node = doc.IterateChildren( 0 );
294 node;
295 node = doc.IterateChildren( node ) )
296 {
297 count++;
298 }
299 XmlTest( "Top level nodes, using IterateChildren.", 3, count );
300
301 // Walk all the elements in a node.
302 count = 0;
303 for( element = todoElement->FirstChildElement();
304 element;
305 element = element->NextSiblingElement() )
306 {
307 count++;
308 }
309 XmlTest( "Children of the 'ToDo' element, using First / Next.",
310 3, count );
311
312 // Walk all the elements in a node by value.
313 count = 0;
314 for( node = todoElement->FirstChild( "Item" );
315 node;
316 node = node->NextSibling( "Item" ) )
317 {
318 count++;
319 }
320 XmlTest( "'Item' children of the 'ToDo' element, using First/Next.", 3, count );
321
322 count = 0;
323 for( node = todoElement->LastChild( "Item" );
324 node;
325 node = node->PreviousSibling( "Item" ) )
326 {
327 count++;
328 }
329 XmlTest( "'Item' children of the 'ToDo' element, using Last/Previous.", 3, count );
330
331#ifdef TIXML_USE_STL
332 {
333 cout << "\n** Parsing. **\n";
334 istringstream parse0( "<Element0 attribute0='foo0' attribute1= noquotes attribute2 = '&gt;' />" );
335 TiXmlElement element0( "default" );
336 parse0 >> element0;
337
338 XmlTest ( "Element parsed, value is 'Element0'.", "Element0", element0.Value() );
339 XmlTest ( "Reads attribute 'attribute0=\"foo0\"'.", "foo0", element0.Attribute( "attribute0" ));
340 XmlTest ( "Reads incorrectly formatted 'attribute1=noquotes'.", "noquotes", element0.Attribute( "attribute1" ) );
341 XmlTest ( "Read attribute with entity value '>'.", ">", element0.Attribute( "attribute2" ) );
342 }
343#endif
344
345 {
346 const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
347 "<passages count=\"006\" formatversion=\"20020620\">\n"
348 " <wrong error>\n"
349 "</passages>";
350
351 TiXmlDocument doc;
352 doc.Parse( error );
353 XmlTest( "Error row", doc.ErrorRow(), 3 );
354 XmlTest( "Error column", doc.ErrorCol(), 17 );
355 //printf( "error=%d id='%s' row %d col%d\n", (int) doc.Error(), doc.ErrorDesc(), doc.ErrorRow()+1, doc.ErrorCol() + 1 );
356
357 }
358 {
359 const char* str = "\t<?xml version=\"1.0\" standalone=\"no\" ?>\t<room doors='2'>\n"
360 " <!-- Silly example -->\n"
361 " <door wall='north'>A great door!</door>\n"
362 "\t<door wall='east'/>"
363 "</room>";
364
365 TiXmlDocument doc;
366 doc.Parse( str );
367
368 TiXmlHandle docHandle( &doc );
369 TiXmlHandle roomHandle = docHandle.FirstChildElement( "room" );
370 TiXmlHandle commentHandle = docHandle.FirstChildElement( "room" ).FirstChild();
371 TiXmlHandle textHandle = docHandle.FirstChildElement( "room" ).ChildElement( "door", 0 ).FirstChild();
372 TiXmlHandle door0Handle = docHandle.FirstChildElement( "room" ).ChildElement( 0 );
373 TiXmlHandle door1Handle = docHandle.FirstChildElement( "room" ).ChildElement( 1 );
374
375 assert( docHandle.Node() );
376 assert( roomHandle.Element() );
377 assert( commentHandle.Node() );
378 assert( textHandle.Text() );
379 assert( door0Handle.Element() );
380 assert( door1Handle.Element() );
381
382 TiXmlDeclaration* declaration = doc.FirstChild()->ToDeclaration();
383 assert( declaration );
384 TiXmlElement* room = roomHandle.Element();
385 assert( room );
386 TiXmlAttribute* doors = room->FirstAttribute();
387 assert( doors );
388 TiXmlText* text = textHandle.Text();
389 TiXmlComment* comment = commentHandle.Node()->ToComment();
390 assert( comment );
391 TiXmlElement* door0 = door0Handle.Element();
392 TiXmlElement* door1 = door1Handle.Element();
393
394 XmlTest( "Location tracking: Declaration row", declaration->Row(), 1 );
395 XmlTest( "Location tracking: Declaration col", declaration->Column(), 5 );
396 XmlTest( "Location tracking: room row", room->Row(), 1 );
397 XmlTest( "Location tracking: room col", room->Column(), 45 );
398 XmlTest( "Location tracking: doors row", doors->Row(), 1 );
399 XmlTest( "Location tracking: doors col", doors->Column(), 51 );
400 XmlTest( "Location tracking: Comment row", comment->Row(), 2 );
401 XmlTest( "Location tracking: Comment col", comment->Column(), 3 );
402 XmlTest( "Location tracking: text row", text->Row(), 3 );
403 XmlTest( "Location tracking: text col", text->Column(), 24 );
404 XmlTest( "Location tracking: door0 row", door0->Row(), 3 );
405 XmlTest( "Location tracking: door0 col", door0->Column(), 5 );
406 XmlTest( "Location tracking: door1 row", door1->Row(), 4 );
407 XmlTest( "Location tracking: door1 col", door1->Column(), 5 );
408 }
409 {
410 const char* str = "\t<?xml version=\"1.0\" standalone=\"no\" ?>\t<room doors='2'>\n"
411 "</room>";
412
413 TiXmlDocument doc;
414 doc.SetTabSize( 8 );
415 doc.Parse( str );
416
417 TiXmlHandle docHandle( &doc );
418 TiXmlHandle roomHandle = docHandle.FirstChildElement( "room" );
419
420 assert( docHandle.Node() );
421 assert( roomHandle.Element() );
422
423 TiXmlElement* room = roomHandle.Element();
424 assert( room );
425 TiXmlAttribute* doors = room->FirstAttribute();
426 assert( doors );
427
428 XmlTest( "Location tracking: Tab 8: room row", room->Row(), 1 );
429 XmlTest( "Location tracking: Tab 8: room col", room->Column(), 49 );
430 XmlTest( "Location tracking: Tab 8: doors row", doors->Row(), 1 );
431 XmlTest( "Location tracking: Tab 8: doors col", doors->Column(), 55 );
432 }
433
434 {
435 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
436
437 TiXmlDocument doc;
438 doc.Parse( str );
439
440 TiXmlElement* ele = doc.FirstChildElement();
441
442 int iVal, result;
443 double dVal;
444
445 result = ele->QueryDoubleAttribute( "attr0", &dVal );
446 XmlTest( "Query attribute: int as double", result, TIXML_SUCCESS );
447 XmlTest( "Query attribute: int as double", (int)dVal, 1 );
448 result = ele->QueryDoubleAttribute( "attr1", &dVal );
449 XmlTest( "Query attribute: double as double", (int)dVal, 2 );
450 result = ele->QueryIntAttribute( "attr1", &iVal );
451 XmlTest( "Query attribute: double as int", result, TIXML_SUCCESS );
452 XmlTest( "Query attribute: double as int", iVal, 2 );
453 result = ele->QueryIntAttribute( "attr2", &iVal );
454 XmlTest( "Query attribute: not a number", result, TIXML_WRONG_TYPE );
455 result = ele->QueryIntAttribute( "bar", &iVal );
456 XmlTest( "Query attribute: does not exist", result, TIXML_NO_ATTRIBUTE );
457 }
458
459#ifdef TIXML_USE_STL
460 {
461 //////////////////////////////////////////////////////
462 cout << "\n** Streaming. **\n";
463
464 // Round trip check: stream in, then stream back out to verify. The stream
465 // out has already been checked, above. We use the output
466
467 istringstream inputStringStream( outputStream.str() );
468 TiXmlDocument document0;
469
470 inputStringStream >> document0;
471
472 ostringstream outputStream0( ostringstream::out );
473 outputStream0 << document0;
474
475 XmlTest( "Stream round trip correct.", string( demoEnd ).c_str(),
476 outputStream0.str().c_str(), true );
477
478 std::string str;
479 str << document0;
480
481 XmlTest( "String printing correct.", string( demoEnd ).c_str(),
482 str.c_str(), true );
483 }
484#endif
485
486 // --------------------------------------------------------
487 // UTF-8 testing. It is important to test:
488 // 1. Making sure name, value, and text read correctly
489 // 2. Row, Col functionality
490 // 3. Correct output
491 // --------------------------------------------------------
492 printf ("\n** UTF-8 **\n");
493 {
494 TiXmlDocument doc( "utf8test.xml" );
495 doc.LoadFile();
496 if ( doc.Error() && doc.ErrorId() == TiXmlBase::TIXML_ERROR_OPENING_FILE ) {
497 printf( "WARNING: File 'utf8test.xml' not found.\n"
498 "(Are you running the test from the wrong directory?)\n"
499 "Could not test UTF-8 functionality.\n" );
500 }
501 else
502 {
503 TiXmlHandle docH( &doc );
504 // Get the attribute "value" from the "Russian" element and check it.
505 TiXmlElement* element = docH.FirstChildElement( "document" ).FirstChildElement( "Russian" ).Element();
506 const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
507 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
508
509 XmlTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ), true );
510 XmlTest( "UTF-8: Russian value row.", 4, element->Row() );
511 XmlTest( "UTF-8: Russian value column.", 5, element->Column() );
512
513 const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U,
514 0xd1U, 0x81U, 0xd1U, 0x81U,
515 0xd0U, 0xbaU, 0xd0U, 0xb8U,
516 0xd0U, 0xb9U, 0 };
517 const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
518
519 TiXmlText* text = docH.FirstChildElement( "document" ).FirstChildElement( (const char*) russianElementName ).Child( 0 ).Text();
520 XmlTest( "UTF-8: Browsing russian element name.",
521 russianText,
522 text->Value(),
523 true );
524 XmlTest( "UTF-8: Russian element name row.", 7, text->Row() );
525 XmlTest( "UTF-8: Russian element name column.", 47, text->Column() );
526
527 TiXmlDeclaration* dec = docH.Child( 0 ).Node()->ToDeclaration();
528 XmlTest( "UTF-8: Declaration column.", 1, dec->Column() );
529 XmlTest( "UTF-8: Document column.", 1, doc.Column() );
530
531 // Now try for a round trip.
532 doc.SaveFile( "utf8testout.xml" );
533
534 // Check the round trip.
535 char savedBuf[256];
536 char verifyBuf[256];
537 int okay = 1;
538
539 FILE* saved = fopen( "utf8testout.xml", "r" );
540 FILE* verify = fopen( "utf8testverify.xml", "r" );
541 if ( saved && verify )
542 {
543 while ( fgets( verifyBuf, 256, verify ) )
544 {
545 fgets( savedBuf, 256, saved );
546 if ( strcmp( verifyBuf, savedBuf ) )
547 {
548 okay = 0;
549 break;
550 }
551 }
552 fclose( saved );
553 fclose( verify );
554 }
555 XmlTest( "UTF-8: Verified multi-language round trip.", 1, okay );
556
557 // On most Western machines, this is an element that contains
558 // the word "resume" with the correct accents, in a latin encoding.
559 // It will be something else completely on non-wester machines,
560 // which is why TinyXml is switching to UTF-8.
561 const char latin[] = "<element>r\x82sum\x82</element>";
562
563 TiXmlDocument latinDoc;
564 latinDoc.Parse( latin, 0, TIXML_ENCODING_LEGACY );
565
566 text = latinDoc.FirstChildElement()->FirstChild()->ToText();
567 XmlTest( "Legacy encoding: Verify text element.", "r\x82sum\x82", text->Value() );
568 }
569 }
570
571 //////////////////////
572 // Copy and assignment
573 //////////////////////
574 printf ("\n** Copy and Assignment **\n");
575 {
576 TiXmlElement element( "foo" );
577 element.Parse( "<element name='value' />", 0, TIXML_ENCODING_UNKNOWN );
578
579 TiXmlElement elementCopy( element );
580 TiXmlElement elementAssign( "foo" );
581 elementAssign.Parse( "<incorrect foo='bar'/>", 0, TIXML_ENCODING_UNKNOWN );
582 elementAssign = element;
583
584 XmlTest( "Copy/Assign: element copy #1.", "element", elementCopy.Value() );
585 XmlTest( "Copy/Assign: element copy #2.", "value", elementCopy.Attribute( "name" ) );
586 XmlTest( "Copy/Assign: element assign #1.", "element", elementAssign.Value() );
587 XmlTest( "Copy/Assign: element assign #2.", "value", elementAssign.Attribute( "name" ) );
Karsten Tausched1438212022-10-06 15:20:50 +0200588 XmlTest( "Copy/Assign: element assign #3.", true, ( 0 == elementAssign.Attribute( "foo" )) );
Upstreambc0ee9a1970-01-12 13:46:40 +0000589
590 TiXmlComment comment;
591 comment.Parse( "<!--comment-->", 0, TIXML_ENCODING_UNKNOWN );
592 TiXmlComment commentCopy( comment );
593 TiXmlComment commentAssign;
594 commentAssign = commentCopy;
595 XmlTest( "Copy/Assign: comment copy.", "comment", commentCopy.Value() );
596 XmlTest( "Copy/Assign: comment assign.", "comment", commentAssign.Value() );
597
598 TiXmlUnknown unknown;
599 unknown.Parse( "<[unknown]>", 0, TIXML_ENCODING_UNKNOWN );
600 TiXmlUnknown unknownCopy( unknown );
601 TiXmlUnknown unknownAssign;
602 unknownAssign.Parse( "incorrect", 0, TIXML_ENCODING_UNKNOWN );
603 unknownAssign = unknownCopy;
604 XmlTest( "Copy/Assign: unknown copy.", "[unknown]", unknownCopy.Value() );
605 XmlTest( "Copy/Assign: unknown assign.", "[unknown]", unknownAssign.Value() );
606
607 TiXmlText text( "TextNode" );
608 TiXmlText textCopy( text );
609 TiXmlText textAssign( "incorrect" );
610 textAssign = text;
611 XmlTest( "Copy/Assign: text copy.", "TextNode", textCopy.Value() );
612 XmlTest( "Copy/Assign: text assign.", "TextNode", textAssign.Value() );
613
614 TiXmlDeclaration dec;
615 dec.Parse( "<?xml version='1.0' encoding='UTF-8'?>", 0, TIXML_ENCODING_UNKNOWN );
616 TiXmlDeclaration decCopy( dec );
617 TiXmlDeclaration decAssign;
618 decAssign = dec;
619
620 XmlTest( "Copy/Assign: declaration copy.", "UTF-8", decCopy.Encoding() );
621 XmlTest( "Copy/Assign: text assign.", "UTF-8", decAssign.Encoding() );
622
623 TiXmlDocument doc;
624 elementCopy.InsertEndChild( textCopy );
625 doc.InsertEndChild( decAssign );
626 doc.InsertEndChild( elementCopy );
627 doc.InsertEndChild( unknownAssign );
628
629 TiXmlDocument docCopy( doc );
630 TiXmlDocument docAssign;
631 docAssign = docCopy;
632
633 #ifdef TIXML_USE_STL
634 std::string original, copy, assign;
635 original << doc;
636 copy << docCopy;
637 assign << docAssign;
638 XmlTest( "Copy/Assign: document copy.", original.c_str(), copy.c_str(), true );
639 XmlTest( "Copy/Assign: document assign.", original.c_str(), assign.c_str(), true );
640
641 #endif
642 }
643
644 //////////////////////////////////////////////////////
645#ifdef TIXML_USE_STL
646 printf ("\n** Parsing, no Condense Whitespace **\n");
647 TiXmlBase::SetCondenseWhiteSpace( false );
Karsten Tausched1438212022-10-06 15:20:50 +0200648 {
649 istringstream parse1( "<start>This is \ntext</start>" );
650 TiXmlElement text1( "text" );
651 parse1 >> text1;
Upstreambc0ee9a1970-01-12 13:46:40 +0000652
Karsten Tausched1438212022-10-06 15:20:50 +0200653 XmlTest ( "Condense white space OFF.", "This is \ntext",
654 text1.FirstChild()->Value(),
655 true );
656 }
Upstreambc0ee9a1970-01-12 13:46:40 +0000657 TiXmlBase::SetCondenseWhiteSpace( true );
658#endif
659
660 //////////////////////////////////////////////////////
661 // GetText();
662 {
663 const char* str = "<foo>This is text</foo>";
664 TiXmlDocument doc;
665 doc.Parse( str );
666 const TiXmlElement* element = doc.RootElement();
667
668 XmlTest( "GetText() normal use.", "This is text", element->GetText() );
669
670 str = "<foo><b>This is text</b></foo>";
671 doc.Clear();
672 doc.Parse( str );
673 element = doc.RootElement();
674
675 XmlTest( "GetText() contained element.", element->GetText() == 0, true );
676
677 str = "<foo>This is <b>text</b></foo>";
678 doc.Clear();
679 TiXmlBase::SetCondenseWhiteSpace( false );
680 doc.Parse( str );
681 TiXmlBase::SetCondenseWhiteSpace( true );
682 element = doc.RootElement();
683
684 XmlTest( "GetText() partial.", "This is ", element->GetText() );
685 }
686
687
688 //////////////////////////////////////////////////////
689 // CDATA
690 {
691 const char* str = "<xmlElement>"
692 "<![CDATA["
693 "I am > the rules!\n"
694 "...since I make symbolic puns"
695 "]]>"
696 "</xmlElement>";
697 TiXmlDocument doc;
698 doc.Parse( str );
Karsten Tauschec2c86482022-10-06 15:19:09 +0200699 doc.Print();
Upstreambc0ee9a1970-01-12 13:46:40 +0000700
701 XmlTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(),
702 "I am > the rules!\n...since I make symbolic puns",
703 true );
704
705 #ifdef TIXML_USE_STL
706 //cout << doc << '\n';
707
708 doc.Clear();
709
710 istringstream parse0( str );
711 parse0 >> doc;
712 //cout << doc << '\n';
713
714 XmlTest( "CDATA stream.", doc.FirstChildElement()->FirstChild()->Value(),
715 "I am > the rules!\n...since I make symbolic puns",
716 true );
717 #endif
718
719 TiXmlDocument doc1 = doc;
720 //doc.Print();
721
722 XmlTest( "CDATA copy.", doc1.FirstChildElement()->FirstChild()->Value(),
723 "I am > the rules!\n...since I make symbolic puns",
724 true );
725 }
726
727
728 //////////////////////////////////////////////////////
729 printf ("\n** Bug regression tests **\n");
730
731 // InsertBeforeChild and InsertAfterChild causes crash.
732 {
733 TiXmlElement parent( "Parent" );
734 TiXmlElement childText0( "childText0" );
735 TiXmlElement childText1( "childText1" );
736 TiXmlNode* childNode0 = parent.InsertEndChild( childText0 );
737 TiXmlNode* childNode1 = parent.InsertBeforeChild( childNode0, childText1 );
738
739 XmlTest( "Test InsertBeforeChild on empty node.", ( childNode1 == parent.FirstChild() ), true );
740 }
741
742 {
743 // InsertBeforeChild and InsertAfterChild causes crash.
744 TiXmlElement parent( "Parent" );
745 TiXmlElement childText0( "childText0" );
746 TiXmlElement childText1( "childText1" );
747 TiXmlNode* childNode0 = parent.InsertEndChild( childText0 );
748 TiXmlNode* childNode1 = parent.InsertAfterChild( childNode0, childText1 );
749
750 XmlTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent.LastChild() ), true );
751 }
752
753 // Reports of missing constructors, irregular string problems.
754 {
755 // Missing constructor implementation. No test -- just compiles.
756 TiXmlText text( "Missing" );
757
758 #ifdef TIXML_USE_STL
759 // Missing implementation:
760 TiXmlDocument doc;
761 string name = "missing";
762 doc.LoadFile( name );
763
764 TiXmlText textSTL( name );
765 #else
766 // verifying some basic string functions:
767 TiXmlString a;
768 TiXmlString b( "Hello" );
769 TiXmlString c( "ooga" );
770
771 c = " World!";
772 a = b;
773 a += c;
774 a = a;
775
776 XmlTest( "Basic TiXmlString test. ", "Hello World!", a.c_str() );
777 #endif
778 }
779
780 // Long filenames crashing STL version
781 {
782 TiXmlDocument doc( "midsummerNightsDreamWithAVeryLongFilenameToConfuseTheStringHandlingRoutines.xml" );
783 bool loadOkay = doc.LoadFile();
784 loadOkay = true; // get rid of compiler warning.
785 // Won't pass on non-dev systems. Just a "no crash" check.
786 //XmlTest( "Long filename. ", true, loadOkay );
787 }
788
789 {
790 // Entities not being written correctly.
791 // From Lynn Allen
792
793 const char* passages =
794 "<?xml version=\"1.0\" standalone=\"no\" ?>"
795 "<passages count=\"006\" formatversion=\"20020620\">"
796 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
797 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
798 "</passages>";
799
800 TiXmlDocument doc( "passages.xml" );
801 doc.Parse( passages );
802 TiXmlElement* psg = doc.RootElement()->FirstChildElement();
803 const char* context = psg->Attribute( "context" );
804 const char* expected = "Line 5 has \"quotation marks\" and 'apostrophe marks'. It also has <, >, and &, as well as a fake copyright \xC2\xA9.";
805
806 XmlTest( "Entity transformation: read. ", expected, context, true );
807
808 FILE* textfile = fopen( "textfile.txt", "w" );
809 if ( textfile )
810 {
811 psg->Print( textfile, 0 );
812 fclose( textfile );
813 }
814 textfile = fopen( "textfile.txt", "r" );
815 assert( textfile );
816 if ( textfile )
817 {
818 char buf[ 1024 ];
819 fgets( buf, 1024, textfile );
820 XmlTest( "Entity transformation: write. ",
821 "<psg context=\'Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
822 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.' />",
823 buf,
824 true );
825 }
826 fclose( textfile );
827 }
828
829 {
830 FILE* textfile = fopen( "test5.xml", "w" );
831 if ( textfile )
832 {
833 fputs("<?xml version='1.0'?><a.elem xmi.version='2.0'/>", textfile);
834 fclose(textfile);
835
836 TiXmlDocument doc;
837 doc.LoadFile( "test5.xml" );
838 XmlTest( "dot in element attributes and names", doc.Error(), 0);
839 }
840 }
841
842 {
843 FILE* textfile = fopen( "test6.xml", "w" );
844 if ( textfile )
845 {
846 fputs("<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>", textfile );
847 fclose(textfile);
848
849 TiXmlDocument doc;
850 bool result = doc.LoadFile( "test6.xml" );
851 XmlTest( "Entity with one digit.", result, true );
852
853 TiXmlText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
854 XmlTest( "Entity with one digit.",
855 text->Value(), "1.1 Start easy ignore fin thickness\n" );
856 }
857 }
858
859 {
860 // DOCTYPE not preserved (950171)
861 //
862 const char* doctype =
863 "<?xml version=\"1.0\" ?>"
864 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
865 "<!ELEMENT title (#PCDATA)>"
866 "<!ELEMENT books (title,authors)>"
867 "<element />";
868
869 TiXmlDocument doc;
870 doc.Parse( doctype );
871 doc.SaveFile( "test7.xml" );
872 doc.Clear();
873 doc.LoadFile( "test7.xml" );
874
875 TiXmlHandle docH( &doc );
876 TiXmlUnknown* unknown = docH.Child( 1 ).Unknown();
877 XmlTest( "Correct value of unknown.", "!DOCTYPE PLAY SYSTEM 'play.dtd'", unknown->Value() );
878 #ifdef TIXML_USE_STL
879 TiXmlNode* node = docH.Child( 2 ).Node();
880 std::string str;
881 str << (*node);
882 XmlTest( "Correct streaming of unknown.", "<!ELEMENT title (#PCDATA)>", str.c_str() );
883 #endif
884 }
885
886 {
887 // [ 791411 ] Formatting bug
888 // Comments do not stream out correctly.
889 const char* doctype =
890 "<!-- Somewhat<evil> -->";
891 TiXmlDocument doc;
892 doc.Parse( doctype );
893
894 TiXmlHandle docH( &doc );
895 TiXmlComment* comment = docH.Child( 0 ).Node()->ToComment();
896
897 XmlTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
898 #ifdef TIXML_USE_STL
899 std::string str;
900 str << (*comment);
901 XmlTest( "Comment streaming.", "<!-- Somewhat<evil> -->", str.c_str() );
902 #endif
903 }
904
905 {
906 // [ 870502 ] White space issues
907 TiXmlDocument doc;
908 TiXmlText* text;
909 TiXmlHandle docH( &doc );
910
911 const char* doctype0 = "<element> This has leading and trailing space </element>";
912 const char* doctype1 = "<element>This has internal space</element>";
913 const char* doctype2 = "<element> This has leading, trailing, and internal space </element>";
914
915 TiXmlBase::SetCondenseWhiteSpace( false );
916 doc.Clear();
917 doc.Parse( doctype0 );
918 text = docH.FirstChildElement( "element" ).Child( 0 ).Text();
919 XmlTest( "White space kept.", " This has leading and trailing space ", text->Value() );
920
921 doc.Clear();
922 doc.Parse( doctype1 );
923 text = docH.FirstChildElement( "element" ).Child( 0 ).Text();
924 XmlTest( "White space kept.", "This has internal space", text->Value() );
925
926 doc.Clear();
927 doc.Parse( doctype2 );
928 text = docH.FirstChildElement( "element" ).Child( 0 ).Text();
929 XmlTest( "White space kept.", " This has leading, trailing, and internal space ", text->Value() );
930
931 TiXmlBase::SetCondenseWhiteSpace( true );
932 doc.Clear();
933 doc.Parse( doctype0 );
934 text = docH.FirstChildElement( "element" ).Child( 0 ).Text();
935 XmlTest( "White space condensed.", "This has leading and trailing space", text->Value() );
936
937 doc.Clear();
938 doc.Parse( doctype1 );
939 text = docH.FirstChildElement( "element" ).Child( 0 ).Text();
940 XmlTest( "White space condensed.", "This has internal space", text->Value() );
941
942 doc.Clear();
943 doc.Parse( doctype2 );
944 text = docH.FirstChildElement( "element" ).Child( 0 ).Text();
945 XmlTest( "White space condensed.", "This has leading, trailing, and internal space", text->Value() );
946 }
947
948 {
949 // Double attributes
950 const char* doctype = "<element attr='red' attr='blue' />";
951
952 TiXmlDocument doc;
953 doc.Parse( doctype );
954
955 XmlTest( "Parsing repeated attributes.", 0, (int)doc.Error() ); // not an error to tinyxml
956 XmlTest( "Parsing repeated attributes.", "blue", doc.FirstChildElement( "element" )->Attribute( "attr" ) );
957 }
958
959 {
960 // Embedded null in stream.
961 const char* doctype = "<element att\0r='red' attr='blue' />";
962
963 TiXmlDocument doc;
964 doc.Parse( doctype );
965 XmlTest( "Embedded null throws error.", true, doc.Error() );
966
967 #ifdef TIXML_USE_STL
968 istringstream strm( doctype );
969 doc.Clear();
970 doc.ClearError();
971 strm >> doc;
972 XmlTest( "Embedded null throws error.", true, doc.Error() );
973 #endif
974 }
975
976 {
977 // Legacy mode test. (This test may only pass on a western system)
978 const char* str =
979 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>"
980 "<ä>"
981 "CöntäntßäöüÄÖÜ"
982 "</ä>";
983
984 TiXmlDocument doc;
985 doc.Parse( str );
986
987 //doc.Print( stdout, 0 );
988
989 TiXmlHandle docHandle( &doc );
990 TiXmlHandle aHandle = docHandle.FirstChildElement( "ä" );
991 TiXmlHandle tHandle = aHandle.Child( 0 );
992 assert( aHandle.Element() );
993 assert( tHandle.Text() );
994 XmlTest( "ISO-8859-1 Parsing.", "CöntäntßäöüÄÖÜ", tHandle.Text()->Value() );
995 }
996
997 {
998 // Empty documents should return TIXML_ERROR_PARSING_EMPTY, bug 1070717
999 const char* str = " ";
1000 TiXmlDocument doc;
1001 doc.Parse( str );
1002 XmlTest( "Empty document error TIXML_ERROR_DOCUMENT_EMPTY", TiXmlBase::TIXML_ERROR_DOCUMENT_EMPTY, doc.ErrorId() );
1003 }
1004 #ifndef TIXML_USE_STL
1005 {
1006 // String equality. [ 1006409 ] string operator==/!= no worky in all cases
1007 TiXmlString temp;
1008 XmlTest( "Empty tinyxml string compare equal", ( temp == "" ), true );
1009
1010 TiXmlString foo;
1011 TiXmlString bar( "" );
1012 XmlTest( "Empty tinyxml string compare equal", ( foo == bar ), true );
1013 }
1014
1015 #endif
1016 {
1017 // Bug [ 1195696 ] from marlonism
1018 TiXmlBase::SetCondenseWhiteSpace(false);
1019 TiXmlDocument xml;
1020 xml.Parse("<text><break/>This hangs</text>");
1021 XmlTest( "Test safe error return.", xml.Error(), false );
1022 }
1023
1024 {
1025 // Bug [ 1243992 ] - another infinite loop
1026 TiXmlDocument doc;
1027 doc.SetCondenseWhiteSpace(false);
1028 doc.Parse("<p><pb></pb>test</p>");
1029 }
1030 {
1031 // Low entities
1032 TiXmlDocument xml;
1033 xml.Parse( "<test>&#x0e;</test>" );
1034 const char result[] = { 0x0e, 0 };
1035 XmlTest( "Low entities.", xml.FirstChildElement()->GetText(), result );
1036 xml.Print();
1037 }
1038
1039 #if defined( WIN32 ) && defined( TUNE )
Karsten Tausched1438212022-10-06 15:20:50 +02001040 _CrtMemCheckpoint( &endMemState );
1041 //_CrtMemDumpStatistics( &endMemState );
1042
1043 _CrtMemState diffMemState;
1044 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
1045 _CrtMemDumpStatistics( &diffMemState );
Upstreambc0ee9a1970-01-12 13:46:40 +00001046 #endif
1047
1048 printf ("\nPass %d, Fail %d\n", gPass, gFail);
1049 return gFail;
1050}
1051
1052