blob: 99171a3efa7b6850f27977c8453d0f3fe4b50638 [file] [log] [blame]
Lee Thomason5b0a6772012-11-19 13:54:42 -08001#if defined( _MSC_VER )
Serhat Eser Erdemca5d6842014-04-17 14:06:15 +02002 #if !defined( _CRT_SECURE_NO_WARNINGS )
3 #define _CRT_SECURE_NO_WARNINGS // This test file is not intended to be secure.
4 #endif
Lee Thomason5b0a6772012-11-19 13:54:42 -08005#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08006
Lee Thomason5b0a6772012-11-19 13:54:42 -08007#include "tinyxml2.h"
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -07008#include <cstdlib>
9#include <cstring>
10#include <ctime>
U-Lama\Leee13c3e62011-12-28 14:36:55 -080011
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080012#if defined( _MSC_VER )
Lee Thomason1ff38e02012-02-14 18:18:16 -080013 #include <crtdbg.h>
Lee Thomason6f381b72012-03-02 12:59:39 -080014 #define WIN32_LEAN_AND_MEAN
15 #include <windows.h>
Lee Thomason1ff38e02012-02-14 18:18:16 -080016 _CrtMemState startMemState;
Lee Thomason1ff38e02012-02-14 18:18:16 -080017#endif
Lee Thomasone9ecdab2012-02-13 18:11:20 -080018
U-Lama\Leee13c3e62011-12-28 14:36:55 -080019using namespace tinyxml2;
Anton Indrawan8a0006c2014-11-20 18:27:07 +010020using namespace std;
Lee Thomasonec5a7b42012-02-13 18:16:52 -080021int gPass = 0;
22int gFail = 0;
23
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -080024
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070025bool XMLTest (const char* testString, const char* expected, const char* found, bool echo=true, bool extraNL=false )
Lee Thomason1ff38e02012-02-14 18:18:16 -080026{
Sarat Addepalli13b2d732015-05-19 12:44:57 +053027 bool pass;
28 if ( !expected && !found )
29 pass = true;
30 else if ( !expected || !found )
31 pass = false;
Sarat Addepallid608c562015-05-20 10:19:00 +053032 else
33 pass = !strcmp( expected, found );
Lee Thomason1ff38e02012-02-14 18:18:16 -080034 if ( pass )
35 printf ("[pass]");
36 else
37 printf ("[fail]");
38
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070039 if ( !echo ) {
Lee Thomason1ff38e02012-02-14 18:18:16 -080040 printf (" %s\n", testString);
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -070041 }
42 else {
43 if ( extraNL ) {
44 printf( " %s\n", testString );
45 printf( "%s\n", expected );
46 printf( "%s\n", found );
47 }
48 else {
49 printf (" %s [%s][%s]\n", testString, expected, found);
50 }
51 }
Lee Thomason1ff38e02012-02-14 18:18:16 -080052
53 if ( pass )
54 ++gPass;
55 else
56 ++gFail;
57 return pass;
58}
59
kezenator5a700712016-11-26 13:54:42 +100060bool XMLTest(const char* testString, XMLError expected, XMLError found, bool echo = true, bool extraNL = false)
61{
Lee Thomasone90e9012016-12-24 07:34:39 -080062 return XMLTest(testString, XMLDocument::ErrorIDToName(expected), XMLDocument::ErrorIDToName(found), echo, extraNL);
kezenator5a700712016-11-26 13:54:42 +100063}
64
65bool XMLTest(const char* testString, bool expected, bool found, bool echo = true, bool extraNL = false)
66{
67 return XMLTest(testString, expected ? "true" : "false", found ? "true" : "false", echo, extraNL);
68}
Lee Thomason1ff38e02012-02-14 18:18:16 -080069
Lee Thomason21be8822012-07-15 17:27:22 -070070template< class T > bool XMLTest( const char* testString, T expected, T found, bool echo=true )
Lee Thomason1ff38e02012-02-14 18:18:16 -080071{
72 bool pass = ( expected == found );
73 if ( pass )
74 printf ("[pass]");
75 else
76 printf ("[fail]");
77
U-Stream\Lee09a11c52012-02-17 08:31:16 -080078 if ( !echo )
Lee Thomason1ff38e02012-02-14 18:18:16 -080079 printf (" %s\n", testString);
80 else
Lee Thomasonc8312792012-07-16 12:44:41 -070081 printf (" %s [%d][%d]\n", testString, static_cast<int>(expected), static_cast<int>(found) );
Lee Thomason1ff38e02012-02-14 18:18:16 -080082
83 if ( pass )
84 ++gPass;
85 else
86 ++gFail;
87 return pass;
88}
Lee Thomasonec5a7b42012-02-13 18:16:52 -080089
U-Lama\Leee13c3e62011-12-28 14:36:55 -080090
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -080091void NullLineEndings( char* p )
92{
93 while( p && *p ) {
94 if ( *p == '\n' || *p == '\r' ) {
95 *p = 0;
96 return;
97 }
98 ++p;
99 }
100}
101
102
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700103int example_1()
104{
105 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300106 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700107
108 return doc.ErrorID();
109}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200110/** @page Example-1 Load an XML File
111 * @dontinclude ./xmltest.cpp
112 * Basic XML file loading.
113 * The basic syntax to load an XML file from
114 * disk and check for an error. (ErrorID()
115 * will return 0 for no error.)
116 * @skip example_1()
117 * @until }
118 */
119
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700120
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700121int example_2()
122{
123 static const char* xml = "<element/>";
124 XMLDocument doc;
125 doc.Parse( xml );
126
127 return doc.ErrorID();
128}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200129/** @page Example-2 Parse an XML from char buffer
130 * @dontinclude ./xmltest.cpp
131 * Basic XML string parsing.
132 * The basic syntax to parse an XML for
133 * a char* and check for an error. (ErrorID()
134 * will return 0 for no error.)
135 * @skip example_2()
136 * @until }
137 */
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700138
139
140int example_3()
141{
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700142 static const char* xml =
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -0700143 "<?xml version=\"1.0\"?>"
144 "<!DOCTYPE PLAY SYSTEM \"play.dtd\">"
145 "<PLAY>"
146 "<TITLE>A Midsummer Night's Dream</TITLE>"
147 "</PLAY>";
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700148
149 XMLDocument doc;
150 doc.Parse( xml );
151
152 XMLElement* titleElement = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" );
153 const char* title = titleElement->GetText();
154 printf( "Name of play (1): %s\n", title );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700155
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700156 XMLText* textNode = titleElement->FirstChild()->ToText();
157 title = textNode->Value();
158 printf( "Name of play (2): %s\n", title );
159
160 return doc.ErrorID();
161}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200162/** @page Example-3 Get information out of XML
163 @dontinclude ./xmltest.cpp
164 In this example, we navigate a simple XML
165 file, and read some interesting text. Note
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700166 that this example doesn't use error
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200167 checking; working code should check for null
168 pointers when walking an XML tree, or use
169 XMLHandle.
170
171 (The XML is an excerpt from "dream.xml").
172
173 @skip example_3()
174 @until </PLAY>";
175
176 The structure of the XML file is:
177
178 <ul>
179 <li>(declaration)</li>
180 <li>(dtd stuff)</li>
181 <li>Element "PLAY"</li>
182 <ul>
183 <li>Element "TITLE"</li>
184 <ul>
185 <li>Text "A Midsummer Night's Dream"</li>
186 </ul>
187 </ul>
188 </ul>
189
190 For this example, we want to print out the
191 title of the play. The text of the title (what
192 we want) is child of the "TITLE" element which
193 is a child of the "PLAY" element.
194
195 We want to skip the declaration and dtd, so the
196 method FirstChildElement() is a good choice. The
197 FirstChildElement() of the Document is the "PLAY"
198 Element, the FirstChildElement() of the "PLAY" Element
199 is the "TITLE" Element.
200
201 @until ( "TITLE" );
202
203 We can then use the convenience function GetText()
204 to get the title of the play.
205
206 @until title );
207
208 Text is just another Node in the XML DOM. And in
209 fact you should be a little cautious with it, as
210 text nodes can contain elements.
211
212 @verbatim
213 Consider: A Midsummer Night's <b>Dream</b>
214 @endverbatim
215
216 It is more correct to actually query the Text Node
217 if in doubt:
218
219 @until title );
220
221 Noting that here we use FirstChild() since we are
222 looking for XMLText, not an element, and ToText()
223 is a cast from a Node to a XMLText.
224*/
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700225
226
Lee Thomason21be8822012-07-15 17:27:22 -0700227bool example_4()
228{
229 static const char* xml =
230 "<information>"
231 " <attributeApproach v='2' />"
232 " <textApproach>"
233 " <v>2</v>"
234 " </textApproach>"
235 "</information>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700236
Lee Thomason21be8822012-07-15 17:27:22 -0700237 XMLDocument doc;
238 doc.Parse( xml );
239
240 int v0 = 0;
241 int v1 = 0;
242
243 XMLElement* attributeApproachElement = doc.FirstChildElement()->FirstChildElement( "attributeApproach" );
244 attributeApproachElement->QueryIntAttribute( "v", &v0 );
245
246 XMLElement* textApproachElement = doc.FirstChildElement()->FirstChildElement( "textApproach" );
247 textApproachElement->FirstChildElement( "v" )->QueryIntText( &v1 );
248
249 printf( "Both values are the same: %d and %d\n", v0, v1 );
250
251 return !doc.Error() && ( v0 == v1 );
252}
Martinsh Shaitersc9c8b772013-01-16 02:08:19 +0200253/** @page Example-4 Read attributes and text information.
254 @dontinclude ./xmltest.cpp
255
256 There are fundamentally 2 ways of writing a key-value
257 pair into an XML file. (Something that's always annoyed
258 me about XML.) Either by using attributes, or by writing
259 the key name into an element and the value into
260 the text node wrapped by the element. Both approaches
261 are illustrated in this example, which shows two ways
262 to encode the value "2" into the key "v":
263
264 @skip example_4()
265 @until "</information>";
266
267 TinyXML-2 has accessors for both approaches.
268
269 When using an attribute, you navigate to the XMLElement
270 with that attribute and use the QueryIntAttribute()
271 group of methods. (Also QueryFloatAttribute(), etc.)
272
273 @skip XMLElement* attributeApproachElement
274 @until &v0 );
275
276 When using the text approach, you need to navigate
277 down one more step to the XMLElement that contains
278 the text. Note the extra FirstChildElement( "v" )
279 in the code below. The value of the text can then
280 be safely queried with the QueryIntText() group
281 of methods. (Also QueryFloatText(), etc.)
282
283 @skip XMLElement* textApproachElement
284 @until &v1 );
285*/
Lee Thomason21be8822012-07-15 17:27:22 -0700286
287
Lee Thomason178e4cc2013-01-25 16:19:05 -0800288int main( int argc, const char ** argv )
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800289{
Lee Thomason (grinliz)0a4df402012-02-27 20:50:52 -0800290 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason1ff38e02012-02-14 18:18:16 -0800291 _CrtMemCheckpoint( &startMemState );
Dmitry-Me99916592014-10-23 11:37:03 +0400292 // Enable MS Visual C++ debug heap memory leaks dump on exit
293 _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700294 #endif
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800295
Dmitry-Me4bcbf142014-12-25 19:05:18 +0300296 {
297 TIXMLASSERT( true );
298 }
299
Lee Thomason178e4cc2013-01-25 16:19:05 -0800300 if ( argc > 1 ) {
301 XMLDocument* doc = new XMLDocument();
302 clock_t startTime = clock();
303 doc->LoadFile( argv[1] );
Anton Indrawan8a0006c2014-11-20 18:27:07 +0100304 clock_t loadTime = clock();
Lee Thomason178e4cc2013-01-25 16:19:05 -0800305 int errorID = doc->ErrorID();
306 delete doc; doc = 0;
Anton Indrawan8a0006c2014-11-20 18:27:07 +0100307 clock_t deleteTime = clock();
Lee Thomason178e4cc2013-01-25 16:19:05 -0800308
309 printf( "Test file '%s' loaded. ErrorID=%d\n", argv[1], errorID );
310 if ( !errorID ) {
Lee Thomason (grinliz)d6bd7362013-05-11 20:23:13 -0700311 printf( "Load time=%u\n", (unsigned)(loadTime - startTime) );
312 printf( "Delete time=%u\n", (unsigned)(deleteTime - loadTime) );
313 printf( "Total time=%u\n", (unsigned)(deleteTime - startTime) );
Lee Thomason178e4cc2013-01-25 16:19:05 -0800314 }
315 exit(0);
316 }
317
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300318 FILE* fp = fopen( "resources/dream.xml", "r" );
Lee Thomason7f7b1622012-03-24 12:49:03 -0700319 if ( !fp ) {
320 printf( "Error opening test file 'dream.xml'.\n"
321 "Is your working directory the same as where \n"
322 "the xmltest.cpp and dream.xml file are?\n\n"
323 #if defined( _MSC_VER )
324 "In windows Visual Studio you may need to set\n"
325 "Properties->Debugging->Working Directory to '..'\n"
326 #endif
327 );
328 exit( 1 );
329 }
330 fclose( fp );
331
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -0700332 XMLTest( "Example-1", 0, example_1() );
333 XMLTest( "Example-2", 0, example_2() );
334 XMLTest( "Example-3", 0, example_3() );
Lee Thomason21be8822012-07-15 17:27:22 -0700335 XMLTest( "Example-4", true, example_4() );
Lee Thomason87e475a2012-03-20 11:55:29 -0700336
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700337 /* ------ Example 2: Lookup information. ---- */
Lee Thomason87e475a2012-03-20 11:55:29 -0700338
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800339 {
Lee Thomason43f59302012-02-06 18:18:11 -0800340 static const char* test[] = { "<element />",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400341 "<element></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800342 "<element><subelement/></element>",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400343 "<element><subelement></subelement></element>",
344 "<element><subelement><subsub/></subelement></element>",
345 "<!--comment beside elements--><element><subelement></subelement></element>",
346 "<!--comment beside elements, this time with spaces--> \n <element> <subelement> \n </subelement> </element>",
347 "<element attrib1='foo' attrib2=\"bar\" ></element>",
348 "<element attrib1='foo' attrib2=\"bar\" ><subelement attrib3='yeehaa' /></element>",
Lee Thomason43f59302012-02-06 18:18:11 -0800349 "<element>Text inside element.</element>",
350 "<element><b></b></element>",
351 "<element>Text inside and <b>bolded</b> in the element.</element>",
352 "<outer><element>Text inside and <b>bolded</b> in the element.</element></outer>",
Lee Thomason8ee79892012-01-25 17:44:30 -0800353 "<element>This &amp; That.</element>",
Lee Thomason18d68bd2012-01-26 18:17:26 -0800354 "<element attrib='This&lt;That' />",
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800355 0
356 };
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800357 for( int i=0; test[i]; ++i ) {
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800358 XMLDocument doc;
Lee Thomason6ee99fc2012-01-21 18:45:16 -0800359 doc.Parse( test[i] );
Lee Thomason5cae8972012-01-24 18:03:07 -0800360 doc.Print();
Lee Thomasonec975ce2012-01-23 11:42:06 -0800361 printf( "----------------------------------------------\n" );
Lee Thomasondadcdfa2012-01-18 17:55:48 -0800362 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800363 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800364#if 1
Lee Thomasond6277762012-02-22 16:00:12 -0800365 {
366 static const char* test = "<!--hello world\n"
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400367 " line 2\r"
368 " line 3\r\n"
369 " line 4\n\r"
370 " line 5\r-->";
Lee Thomasond6277762012-02-22 16:00:12 -0800371
372 XMLDocument doc;
373 doc.Parse( test );
374 doc.Print();
375 }
376
Lee Thomason2c85a712012-01-31 08:24:24 -0800377 {
378 static const char* test = "<element>Text before.</element>";
379 XMLDocument doc;
380 doc.Parse( test );
381 XMLElement* root = doc.FirstChildElement();
382 XMLElement* newElement = doc.NewElement( "Subelement" );
383 root->InsertEndChild( newElement );
384 doc.Print();
385 }
Lee Thomasond1983222012-02-06 08:41:24 -0800386 {
387 XMLDocument* doc = new XMLDocument();
388 static const char* test = "<element><sub/></element>";
389 doc->Parse( test );
390 delete doc;
391 }
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800392 {
Lee Thomason1ff38e02012-02-14 18:18:16 -0800393 // Test: Programmatic DOM
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800394 // Build:
395 // <element>
396 // <!--comment-->
397 // <sub attrib="1" />
398 // <sub attrib="2" />
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800399 // <sub attrib="3" >& Text!</sub>
Lee Thomasonec5a7b42012-02-13 18:16:52 -0800400 // <element>
401
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800402 XMLDocument* doc = new XMLDocument();
Lee Thomason1ff38e02012-02-14 18:18:16 -0800403 XMLNode* element = doc->InsertEndChild( doc->NewElement( "element" ) );
404
405 XMLElement* sub[3] = { doc->NewElement( "sub" ), doc->NewElement( "sub" ), doc->NewElement( "sub" ) };
406 for( int i=0; i<3; ++i ) {
407 sub[i]->SetAttribute( "attrib", i );
408 }
409 element->InsertEndChild( sub[2] );
410 XMLNode* comment = element->InsertFirstChild( doc->NewComment( "comment" ) );
Lee Thomasonaf9bce12016-07-17 22:35:52 -0700411 comment->SetUserData((void*)2);
Lee Thomason1ff38e02012-02-14 18:18:16 -0800412 element->InsertAfterChild( comment, sub[0] );
413 element->InsertAfterChild( sub[0], sub[1] );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800414 sub[2]->InsertFirstChild( doc->NewText( "& Text!" ));
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800415 doc->Print();
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800416 XMLTest( "Programmatic DOM", "comment", doc->FirstChildElement( "element" )->FirstChild()->Value() );
417 XMLTest( "Programmatic DOM", "0", doc->FirstChildElement( "element" )->FirstChildElement()->Attribute( "attrib" ) );
418 XMLTest( "Programmatic DOM", 2, doc->FirstChildElement()->LastChildElement( "sub" )->IntAttribute( "attrib" ) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700419 XMLTest( "Programmatic DOM", "& Text!",
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800420 doc->FirstChildElement()->LastChildElement( "sub" )->FirstChild()->ToText()->Value() );
Lee Thomasonc9445462016-07-17 22:53:48 -0700421 XMLTest("User data", (void*)2 == comment->GetUserData(), true, false);
U-Stream\Leeae25a442012-02-17 17:48:16 -0800422
423 // And now deletion:
424 element->DeleteChild( sub[2] );
425 doc->DeleteNode( comment );
426
427 element->FirstChildElement()->SetAttribute( "attrib", true );
428 element->LastChildElement()->DeleteAttribute( "attrib" );
429
430 XMLTest( "Programmatic DOM", true, doc->FirstChildElement()->FirstChildElement()->BoolAttribute( "attrib" ) );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700431 int value1 = 10;
432 int value2 = doc->FirstChildElement()->LastChildElement()->IntAttribute( "attrib", 10 );
433 int result = doc->FirstChildElement()->LastChildElement()->QueryIntAttribute( "attrib", &value1 );
Lee Thomason21be8822012-07-15 17:27:22 -0700434 XMLTest( "Programmatic DOM", result, (int)XML_NO_ATTRIBUTE );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700435 XMLTest( "Programmatic DOM", value1, 10 );
436 XMLTest( "Programmatic DOM", value2, 10 );
U-Stream\Leeae25a442012-02-17 17:48:16 -0800437
438 doc->Print();
439
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700440 {
441 XMLPrinter streamer;
442 doc->Print( &streamer );
443 printf( "%s", streamer.CStr() );
444 }
445 {
446 XMLPrinter streamer( 0, true );
447 doc->Print( &streamer );
Doruk Turak1f212f32016-08-28 20:54:17 +0200448 XMLTest( "Compact mode", "<element><sub attrib=\"true\"/><sub/></element>", streamer.CStr(), false );
Lee Thomason7b1b86a2012-06-04 17:01:38 -0700449 }
Lee Thomason (grinliz)6b8b0122012-09-08 21:21:00 -0700450 doc->SaveFile( "./resources/out/pretty.xml" );
451 doc->SaveFile( "./resources/out/compact.xml", true );
Lee Thomasone9ecdab2012-02-13 18:11:20 -0800452 delete doc;
453 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800454 {
455 // Test: Dream
456 // XML1 : 1,187,569 bytes in 31,209 allocations
457 // XML2 : 469,073 bytes in 323 allocations
458 //int newStart = gNew;
459 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300460 doc.LoadFile( "resources/dream.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800461
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400462 doc.SaveFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800463 doc.PrintError();
464
465 XMLTest( "Dream", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400466 doc.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800467 XMLTest( "Dream", true, doc.FirstChild()->NextSibling()->ToUnknown() ? true : false );
468 XMLTest( "Dream", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
469 doc.FirstChild()->NextSibling()->ToUnknown()->Value() );
470 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400471 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800472 XMLTest( "Dream", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400473 doc.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800474
475 XMLDocument doc2;
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400476 doc2.LoadFile( "resources/out/dreamout.xml" );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800477 XMLTest( "Dream-out", "xml version=\"1.0\"",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400478 doc2.FirstChild()->ToDeclaration()->Value() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800479 XMLTest( "Dream-out", true, doc2.FirstChild()->NextSibling()->ToUnknown() ? true : false );
480 XMLTest( "Dream-out", "DOCTYPE PLAY SYSTEM \"play.dtd\"",
481 doc2.FirstChild()->NextSibling()->ToUnknown()->Value() );
482 XMLTest( "Dream-out", "And Robin shall restore amends.",
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400483 doc2.LastChild()->LastChild()->LastChild()->LastChild()->LastChildElement()->GetText() );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800484
485 //gNewTotal = gNew - newStart;
486 }
Lee Thomason6f381b72012-03-02 12:59:39 -0800487
488
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800489 {
490 const char* error = "<?xml version=\"1.0\" standalone=\"no\" ?>\n"
491 "<passages count=\"006\" formatversion=\"20020620\">\n"
492 " <wrong error>\n"
493 "</passages>";
494
495 XMLDocument doc;
496 doc.Parse( error );
Lee Thomason2fa81722012-11-09 12:37:46 -0800497 XMLTest( "Bad XML", doc.ErrorID(), XML_ERROR_PARSING_ATTRIBUTE );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800498 }
499
500 {
501 const char* str = "<doc attr0='1' attr1='2.0' attr2='foo' />";
502
503 XMLDocument doc;
504 doc.Parse( str );
505
506 XMLElement* ele = doc.FirstChildElement();
507
508 int iVal, result;
509 double dVal;
510
511 result = ele->QueryDoubleAttribute( "attr0", &dVal );
Lee Thomason85536252016-06-04 19:10:53 -0700512 XMLTest( "Query attribute: int as double", result, (int)XML_SUCCESS);
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800513 XMLTest( "Query attribute: int as double", (int)dVal, 1 );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700514 XMLTest( "Query attribute: int as double", (int)ele->DoubleAttribute("attr0"), 1);
515
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800516 result = ele->QueryDoubleAttribute( "attr1", &dVal );
Lee Thomason85536252016-06-04 19:10:53 -0700517 XMLTest( "Query attribute: double as double", result, (int)XML_SUCCESS);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700518 XMLTest( "Query attribute: double as double", dVal, 2.0 );
519 XMLTest( "Query attribute: double as double", ele->DoubleAttribute("attr1"), 2.0 );
520
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800521 result = ele->QueryIntAttribute( "attr1", &iVal );
Lee Thomason85536252016-06-04 19:10:53 -0700522 XMLTest( "Query attribute: double as int", result, (int)XML_SUCCESS);
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800523 XMLTest( "Query attribute: double as int", iVal, 2 );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700524
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800525 result = ele->QueryIntAttribute( "attr2", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700526 XMLTest( "Query attribute: not a number", result, (int)XML_WRONG_ATTRIBUTE_TYPE );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700527 XMLTest( "Query attribute: not a number", ele->DoubleAttribute("attr2", 4.0), 4.0 );
528
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800529 result = ele->QueryIntAttribute( "bar", &iVal );
Lee Thomason21be8822012-07-15 17:27:22 -0700530 XMLTest( "Query attribute: does not exist", result, (int)XML_NO_ATTRIBUTE );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700531 XMLTest( "Query attribute: does not exist", ele->BoolAttribute("bar", true), true );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800532 }
533
534 {
535 const char* str = "<doc/>";
536
537 XMLDocument doc;
538 doc.Parse( str );
539
540 XMLElement* ele = doc.FirstChildElement();
541
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800542 int iVal, iVal2;
543 double dVal, dVal2;
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800544
545 ele->SetAttribute( "str", "strValue" );
546 ele->SetAttribute( "int", 1 );
547 ele->SetAttribute( "double", -1.0 );
548
549 const char* cStr = ele->Attribute( "str" );
550 ele->QueryIntAttribute( "int", &iVal );
551 ele->QueryDoubleAttribute( "double", &dVal );
552
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800553 ele->QueryAttribute( "int", &iVal2 );
554 ele->QueryAttribute( "double", &dVal2 );
555
Lee Thomason8ba7f7d2012-03-24 13:04:04 -0700556 XMLTest( "Attribute match test", ele->Attribute( "str", "strValue" ), "strValue" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800557 XMLTest( "Attribute round trip. c-string.", "strValue", cStr );
558 XMLTest( "Attribute round trip. int.", 1, iVal );
559 XMLTest( "Attribute round trip. double.", -1, (int)dVal );
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -0800560 XMLTest( "Alternate query", true, iVal == iVal2 );
561 XMLTest( "Alternate query", true, dVal == dVal2 );
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700562 XMLTest( "Alternate query", true, iVal == ele->IntAttribute("int") );
563 XMLTest( "Alternate query", true, dVal == ele->DoubleAttribute("double") );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800564 }
565
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800566 {
567 XMLDocument doc;
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300568 doc.LoadFile( "resources/utf8test.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800569
570 // Get the attribute "value" from the "Russian" element and check it.
571 XMLElement* element = doc.FirstChildElement( "document" )->FirstChildElement( "Russian" );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700572 const unsigned char correctValue[] = { 0xd1U, 0x86U, 0xd0U, 0xb5U, 0xd0U, 0xbdU, 0xd0U, 0xbdU,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800573 0xd0U, 0xbeU, 0xd1U, 0x81U, 0xd1U, 0x82U, 0xd1U, 0x8cU, 0 };
574
575 XMLTest( "UTF-8: Russian value.", (const char*)correctValue, element->Attribute( "value" ) );
576
577 const unsigned char russianElementName[] = { 0xd0U, 0xa0U, 0xd1U, 0x83U,
578 0xd1U, 0x81U, 0xd1U, 0x81U,
579 0xd0U, 0xbaU, 0xd0U, 0xb8U,
580 0xd0U, 0xb9U, 0 };
581 const char russianText[] = "<\xD0\xB8\xD0\xBC\xD0\xB5\xD0\xB5\xD1\x82>";
582
583 XMLText* text = doc.FirstChildElement( "document" )->FirstChildElement( (const char*) russianElementName )->FirstChild()->ToText();
584 XMLTest( "UTF-8: Browsing russian element name.",
585 russianText,
586 text->Value() );
587
588 // Now try for a round trip.
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400589 doc.SaveFile( "resources/out/utf8testout.xml" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800590
591 // Check the round trip.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800592 int okay = 0;
593
Thomas Roßa6dd8c62012-07-26 20:42:18 +0200594 FILE* saved = fopen( "resources/out/utf8testout.xml", "r" );
Bruno Diasa2d4e6e2012-05-07 04:58:11 -0300595 FILE* verify = fopen( "resources/utf8testverify.xml", "r" );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800596
597 if ( saved && verify )
598 {
599 okay = 1;
PKEuSc28ba3a2012-07-16 03:08:47 -0700600 char verifyBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800601 while ( fgets( verifyBuf, 256, verify ) )
602 {
PKEuSc28ba3a2012-07-16 03:08:47 -0700603 char savedBuf[256];
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800604 fgets( savedBuf, 256, saved );
605 NullLineEndings( verifyBuf );
606 NullLineEndings( savedBuf );
607
608 if ( strcmp( verifyBuf, savedBuf ) )
609 {
610 printf( "verify:%s<\n", verifyBuf );
611 printf( "saved :%s<\n", savedBuf );
612 okay = 0;
613 break;
614 }
615 }
616 }
617 if ( saved )
618 fclose( saved );
619 if ( verify )
620 fclose( verify );
621 XMLTest( "UTF-8: Verified multi-language round trip.", 1, okay );
622 }
623
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800624 // --------GetText()-----------
625 {
626 const char* str = "<foo>This is text</foo>";
627 XMLDocument doc;
628 doc.Parse( str );
629 const XMLElement* element = doc.RootElement();
630
631 XMLTest( "GetText() normal use.", "This is text", element->GetText() );
632
633 str = "<foo><b>This is text</b></foo>";
634 doc.Parse( str );
635 element = doc.RootElement();
636
637 XMLTest( "GetText() contained element.", element->GetText() == 0, true );
638 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800639
Lee Thomasond6277762012-02-22 16:00:12 -0800640
Uli Kusterer321072e2014-01-21 01:57:38 +0100641 // --------SetText()-----------
642 {
643 const char* str = "<foo></foo>";
644 XMLDocument doc;
645 doc.Parse( str );
646 XMLElement* element = doc.RootElement();
647
Lee Thomason9c0678a2014-01-24 10:18:27 -0800648 element->SetText("darkness.");
649 XMLTest( "SetText() normal use (open/close).", "darkness.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100650
Lee Thomason9c0678a2014-01-24 10:18:27 -0800651 element->SetText("blue flame.");
652 XMLTest( "SetText() replace.", "blue flame.", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100653
654 str = "<foo/>";
655 doc.Parse( str );
656 element = doc.RootElement();
657
Lee Thomason9c0678a2014-01-24 10:18:27 -0800658 element->SetText("The driver");
659 XMLTest( "SetText() normal use. (self-closing)", "The driver", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100660
Lee Thomason9c0678a2014-01-24 10:18:27 -0800661 element->SetText("<b>horses</b>");
662 XMLTest( "SetText() replace with tag-like text.", "<b>horses</b>", element->GetText() );
663 //doc.Print();
Uli Kusterer321072e2014-01-21 01:57:38 +0100664
665 str = "<foo><bar>Text in nested element</bar></foo>";
666 doc.Parse( str );
667 element = doc.RootElement();
668
Lee Thomason9c0678a2014-01-24 10:18:27 -0800669 element->SetText("wolves");
670 XMLTest( "SetText() prefix to nested non-text children.", "wolves", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800671
672 str = "<foo/>";
673 doc.Parse( str );
674 element = doc.RootElement();
675
676 element->SetText( "str" );
677 XMLTest( "SetText types", "str", element->GetText() );
678
679 element->SetText( 1 );
680 XMLTest( "SetText types", "1", element->GetText() );
681
682 element->SetText( 1U );
683 XMLTest( "SetText types", "1", element->GetText() );
684
685 element->SetText( true );
Doruk Turak1f212f32016-08-28 20:54:17 +0200686 XMLTest( "SetText types", "true", element->GetText() );
Lee Thomason5bb2d802014-01-24 10:42:57 -0800687
688 element->SetText( 1.5f );
689 XMLTest( "SetText types", "1.5", element->GetText() );
690
691 element->SetText( 1.5 );
692 XMLTest( "SetText types", "1.5", element->GetText() );
Uli Kusterer321072e2014-01-21 01:57:38 +0100693 }
694
Lee Thomason51c12712016-06-04 20:18:49 -0700695 // ---------- Attributes ---------
696 {
697 static const int64_t BIG = -123456789012345678;
698 XMLDocument doc;
699 XMLElement* element = doc.NewElement("element");
700 doc.InsertFirstChild(element);
701
702 {
703 element->SetAttribute("attrib", int(-100));
704 int v = 0;
705 element->QueryIntAttribute("attrib", &v);
706 XMLTest("Attribute: int", -100, v, true);
707 element->QueryAttribute("attrib", &v);
708 XMLTest("Attribute: int", -100, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700709 XMLTest("Attribute: int", -100, element->IntAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700710 }
711 {
712 element->SetAttribute("attrib", unsigned(100));
713 unsigned v = 0;
714 element->QueryUnsignedAttribute("attrib", &v);
715 XMLTest("Attribute: unsigned", unsigned(100), v, true);
716 element->QueryAttribute("attrib", &v);
717 XMLTest("Attribute: unsigned", unsigned(100), v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700718 XMLTest("Attribute: unsigned", unsigned(100), element->UnsignedAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700719 }
720 {
721 element->SetAttribute("attrib", BIG);
722 int64_t v = 0;
723 element->QueryInt64Attribute("attrib", &v);
724 XMLTest("Attribute: int64_t", BIG, v, true);
725 element->QueryAttribute("attrib", &v);
726 XMLTest("Attribute: int64_t", BIG, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700727 XMLTest("Attribute: int64_t", BIG, element->Int64Attribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700728 }
729 {
730 element->SetAttribute("attrib", true);
731 bool v = false;
732 element->QueryBoolAttribute("attrib", &v);
733 XMLTest("Attribute: bool", true, v, true);
734 element->QueryAttribute("attrib", &v);
735 XMLTest("Attribute: bool", true, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700736 XMLTest("Attribute: bool", true, element->BoolAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700737 }
738 {
Lee Thomasonce667c92016-12-26 16:45:30 -0800739 element->SetAttribute("attrib", true);
740 const char* result = element->Attribute("attrib");
741 XMLTest("Bool true is 'true'", "true", result);
742
Lee Thomasonc5c99c22016-12-29 11:19:17 -0800743 XMLUtil::SetBoolSerialization("1", "0");
Lee Thomasonce667c92016-12-26 16:45:30 -0800744 element->SetAttribute("attrib", true);
745 result = element->Attribute("attrib");
746 XMLTest("Bool true is '1'", "1", result);
747
Lee Thomasonc5c99c22016-12-29 11:19:17 -0800748 XMLUtil::SetBoolSerialization(0, 0);
Lee Thomasonce667c92016-12-26 16:45:30 -0800749 }
750 {
Lee Thomason51c12712016-06-04 20:18:49 -0700751 element->SetAttribute("attrib", 100.0);
752 double v = 0;
753 element->QueryDoubleAttribute("attrib", &v);
754 XMLTest("Attribute: double", 100.0, v, true);
755 element->QueryAttribute("attrib", &v);
756 XMLTest("Attribute: double", 100.0, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700757 XMLTest("Attribute: double", 100.0, element->DoubleAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700758 }
759 {
760 element->SetAttribute("attrib", 100.0f);
761 float v = 0;
762 element->QueryFloatAttribute("attrib", &v);
763 XMLTest("Attribute: float", 100.0f, v, true);
764 element->QueryAttribute("attrib", &v);
765 XMLTest("Attribute: float", 100.0f, v, true);
Lee Thomason13cbc9a2016-10-27 14:55:07 -0700766 XMLTest("Attribute: float", 100.0f, element->FloatAttribute("attrib"), true);
Lee Thomason51c12712016-06-04 20:18:49 -0700767 }
768 {
769 element->SetText(BIG);
770 int64_t v = 0;
771 element->QueryInt64Text(&v);
772 XMLTest("Element: int64_t", BIG, v, true);
773 }
774 }
775
776 // ---------- XMLPrinter stream mode ------
777 {
778 {
779 FILE* printerfp = fopen("resources/printer.xml", "w");
780 XMLPrinter printer(printerfp);
781 printer.OpenElement("foo");
782 printer.PushAttribute("attrib-text", "text");
783 printer.PushAttribute("attrib-int", int(1));
784 printer.PushAttribute("attrib-unsigned", unsigned(2));
785 printer.PushAttribute("attrib-int64", int64_t(3));
786 printer.PushAttribute("attrib-bool", true);
787 printer.PushAttribute("attrib-double", 4.0);
788 printer.CloseElement();
789 fclose(printerfp);
790 }
791 {
792 XMLDocument doc;
793 doc.LoadFile("resources/printer.xml");
794 XMLTest("XMLPrinter Stream mode: load", doc.ErrorID(), XML_SUCCESS, true);
795
796 const XMLDocument& cdoc = doc;
797
798 const XMLAttribute* attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-text");
799 XMLTest("attrib-text", "text", attrib->Value(), true);
800 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int");
801 XMLTest("attrib-int", int(1), attrib->IntValue(), true);
802 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-unsigned");
803 XMLTest("attrib-unsigned", unsigned(2), attrib->UnsignedValue(), true);
804 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-int64");
805 XMLTest("attrib-int64", int64_t(3), attrib->Int64Value(), true);
806 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-bool");
807 XMLTest("attrib-bool", true, attrib->BoolValue(), true);
808 attrib = cdoc.FirstChildElement("foo")->FindAttribute("attrib-double");
809 XMLTest("attrib-double", 4.0, attrib->DoubleValue(), true);
810 }
811
812 }
813
Uli Kusterer321072e2014-01-21 01:57:38 +0100814
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800815 // ---------- CDATA ---------------
816 {
817 const char* str = "<xmlElement>"
818 "<![CDATA["
819 "I am > the rules!\n"
820 "...since I make symbolic puns"
821 "]]>"
822 "</xmlElement>";
823 XMLDocument doc;
824 doc.Parse( str );
825 doc.Print();
Lee Thomasond6277762012-02-22 16:00:12 -0800826
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700827 XMLTest( "CDATA parse.", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800828 "I am > the rules!\n...since I make symbolic puns",
Lee Thomasond6277762012-02-22 16:00:12 -0800829 false );
830 }
831
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800832 // ----------- CDATA -------------
833 {
834 const char* str = "<xmlElement>"
835 "<![CDATA["
836 "<b>I am > the rules!</b>\n"
837 "...since I make symbolic puns"
838 "]]>"
839 "</xmlElement>";
840 XMLDocument doc;
841 doc.Parse( str );
842 doc.Print();
843
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700844 XMLTest( "CDATA parse. [ tixml1:1480107 ]", doc.FirstChildElement()->FirstChild()->Value(),
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800845 "<b>I am > the rules!</b>\n...since I make symbolic puns",
846 false );
847 }
848
849 // InsertAfterChild causes crash.
850 {
851 // InsertBeforeChild and InsertAfterChild causes crash.
852 XMLDocument doc;
853 XMLElement* parent = doc.NewElement( "Parent" );
854 doc.InsertFirstChild( parent );
855
856 XMLElement* childText0 = doc.NewElement( "childText0" );
857 XMLElement* childText1 = doc.NewElement( "childText1" );
858
859 XMLNode* childNode0 = parent->InsertEndChild( childText0 );
860 XMLNode* childNode1 = parent->InsertAfterChild( childNode0, childText1 );
861
862 XMLTest( "Test InsertAfterChild on empty node. ", ( childNode1 == parent->LastChild() ), true );
863 }
Lee Thomasond6277762012-02-22 16:00:12 -0800864
865 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800866 // Entities not being written correctly.
867 // From Lynn Allen
Lee Thomasond6277762012-02-22 16:00:12 -0800868
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800869 const char* passages =
870 "<?xml version=\"1.0\" standalone=\"no\" ?>"
871 "<passages count=\"006\" formatversion=\"20020620\">"
872 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
873 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright &#xA9;.\"> </psg>"
874 "</passages>";
Lee Thomasond6277762012-02-22 16:00:12 -0800875
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800876 XMLDocument doc;
877 doc.Parse( passages );
878 XMLElement* psg = doc.RootElement()->FirstChildElement();
879 const char* context = psg->Attribute( "context" );
880 const char* expected = "Line 5 has \"quotation marks\" and 'apostrophe marks'. It also has <, >, and &, as well as a fake copyright \xC2\xA9.";
Lee Thomasond6277762012-02-22 16:00:12 -0800881
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800882 XMLTest( "Entity transformation: read. ", expected, context, true );
Lee Thomasond6277762012-02-22 16:00:12 -0800883
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400884 FILE* textfile = fopen( "resources/out/textfile.txt", "w" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800885 if ( textfile )
886 {
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800887 XMLPrinter streamer( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800888 psg->Accept( &streamer );
889 fclose( textfile );
890 }
Thomas Roß0922b732012-09-23 16:31:22 +0200891
892 textfile = fopen( "resources/out/textfile.txt", "r" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800893 TIXMLASSERT( textfile );
894 if ( textfile )
895 {
896 char buf[ 1024 ];
897 fgets( buf, 1024, textfile );
898 XMLTest( "Entity transformation: write. ",
899 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;."
900 " It also has &lt;, &gt;, and &amp;, as well as a fake copyright \xC2\xA9.\"/>\n",
901 buf, false );
PKEuSc28ba3a2012-07-16 03:08:47 -0700902 fclose( textfile );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800903 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800904 }
905
906 {
Lee Thomason6f381b72012-03-02 12:59:39 -0800907 // Suppress entities.
908 const char* passages =
909 "<?xml version=\"1.0\" standalone=\"no\" ?>"
910 "<passages count=\"006\" formatversion=\"20020620\">"
911 "<psg context=\"Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;.\">Crazy &ttk;</psg>"
912 "</passages>";
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700913
Lee Thomason6f381b72012-03-02 12:59:39 -0800914 XMLDocument doc( false );
915 doc.Parse( passages );
916
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700917 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->Attribute( "context" ),
Lee Thomason6f381b72012-03-02 12:59:39 -0800918 "Line 5 has &quot;quotation marks&quot; and &apos;apostrophe marks&apos;." );
919 XMLTest( "No entity parsing.", doc.FirstChildElement()->FirstChildElement()->FirstChild()->Value(),
920 "Crazy &ttk;" );
921 doc.Print();
922 }
923
924 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400925 const char* test = "<?xml version='1.0'?><a.elem xmi.version='2.0'/>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800926
927 XMLDocument doc;
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400928 doc.Parse( test );
929 XMLTest( "dot in names", doc.Error(), false );
930 XMLTest( "dot in names", doc.FirstChildElement()->Name(), "a.elem" );
931 XMLTest( "dot in names", doc.FirstChildElement()->Attribute( "xmi.version" ), "2.0" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800932 }
933
934 {
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400935 const char* test = "<element><Name>1.1 Start easy ignore fin thickness&#xA;</Name></element>";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800936
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400937 XMLDocument doc;
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800938 doc.Parse( test );
939
940 XMLText* text = doc.FirstChildElement()->FirstChildElement()->FirstChild()->ToText();
941 XMLTest( "Entity with one digit.",
942 text->Value(), "1.1 Start easy ignore fin thickness\n",
943 false );
Arkadiy Shapkinef1c69c2012-07-25 22:10:39 +0400944 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800945
946 {
947 // DOCTYPE not preserved (950171)
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700948 //
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800949 const char* doctype =
950 "<?xml version=\"1.0\" ?>"
951 "<!DOCTYPE PLAY SYSTEM 'play.dtd'>"
952 "<!ELEMENT title (#PCDATA)>"
953 "<!ELEMENT books (title,authors)>"
954 "<element />";
955
956 XMLDocument doc;
957 doc.Parse( doctype );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400958 doc.SaveFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800959 doc.DeleteChild( doc.RootElement() );
Arkadiy Shapkinff72d1f2012-07-24 00:24:07 +0400960 doc.LoadFile( "resources/out/test7.xml" );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800961 doc.Print();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700962
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800963 const XMLUnknown* decl = doc.FirstChild()->NextSibling()->ToUnknown();
964 XMLTest( "Correct value of unknown.", "DOCTYPE PLAY SYSTEM 'play.dtd'", decl->Value() );
965
966 }
967
968 {
969 // Comments do not stream out correctly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700970 const char* doctype =
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800971 "<!-- Somewhat<evil> -->";
972 XMLDocument doc;
973 doc.Parse( doctype );
974
975 XMLComment* comment = doc.FirstChild()->ToComment();
976
977 XMLTest( "Comment formatting.", " Somewhat<evil> ", comment->Value() );
978 }
979 {
980 // Double attributes
981 const char* doctype = "<element attr='red' attr='blue' />";
982
983 XMLDocument doc;
984 doc.Parse( doctype );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700985
Lee Thomason2fa81722012-11-09 12:37:46 -0800986 XMLTest( "Parsing repeated attributes.", XML_ERROR_PARSING_ATTRIBUTE, doc.ErrorID() ); // is an error to tinyxml (didn't use to be, but caused issues)
Lee Thomason (grinliz)0a4df402012-02-27 20:50:52 -0800987 doc.PrintError();
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800988 }
989
990 {
991 // Embedded null in stream.
992 const char* doctype = "<element att\0r='red' attr='blue' />";
993
994 XMLDocument doc;
995 doc.Parse( doctype );
996 XMLTest( "Embedded null throws error.", true, doc.Error() );
997 }
998
999 {
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -07001000 // Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
Dmitry-Me588bb8d2014-12-25 18:59:18 +03001001 const char* str = "";
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001002 XMLDocument doc;
1003 doc.Parse( str );
Lee Thomason2fa81722012-11-09 12:37:46 -08001004 XMLTest( "Empty document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001005 }
1006
1007 {
Dmitry-Me588bb8d2014-12-25 18:59:18 +03001008 // Documents with all whitespaces should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
1009 const char* str = " ";
1010 XMLDocument doc;
1011 doc.Parse( str );
1012 XMLTest( "All whitespaces document error", XML_ERROR_EMPTY_DOCUMENT, doc.ErrorID() );
1013 }
1014
1015 {
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001016 // Low entities
1017 XMLDocument doc;
1018 doc.Parse( "<test>&#x0e;</test>" );
1019 const char result[] = { 0x0e, 0 };
1020 XMLTest( "Low entities.", doc.FirstChildElement()->GetText(), result );
1021 doc.Print();
1022 }
1023
1024 {
1025 // Attribute values with trailing quotes not handled correctly
1026 XMLDocument doc;
1027 doc.Parse( "<foo attribute=bar\" />" );
1028 XMLTest( "Throw error with bad end quotes.", doc.Error(), true );
1029 }
1030
1031 {
1032 // [ 1663758 ] Failure to report error on bad XML
1033 XMLDocument xml;
1034 xml.Parse("<x>");
1035 XMLTest("Missing end tag at end of input", xml.Error(), true);
1036 xml.Parse("<x> ");
1037 XMLTest("Missing end tag with trailing whitespace", xml.Error(), true);
1038 xml.Parse("<x></y>");
Lee Thomason2fa81722012-11-09 12:37:46 -08001039 XMLTest("Mismatched tags", xml.ErrorID(), XML_ERROR_MISMATCHED_ELEMENT);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001040 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001041
1042
1043 {
1044 // [ 1475201 ] TinyXML parses entities in comments
1045 XMLDocument xml;
1046 xml.Parse("<!-- declarations for <head> & <body> -->"
1047 "<!-- far &amp; away -->" );
1048
1049 XMLNode* e0 = xml.FirstChild();
1050 XMLNode* e1 = e0->NextSibling();
1051 XMLComment* c0 = e0->ToComment();
1052 XMLComment* c1 = e1->ToComment();
1053
1054 XMLTest( "Comments ignore entities.", " declarations for <head> & <body> ", c0->Value(), true );
1055 XMLTest( "Comments ignore entities.", " far &amp; away ", c1->Value(), true );
1056 }
1057
1058 {
1059 XMLDocument xml;
1060 xml.Parse( "<Parent>"
1061 "<child1 att=''/>"
1062 "<!-- With this comment, child2 will not be parsed! -->"
1063 "<child2 att=''/>"
1064 "</Parent>" );
1065 xml.Print();
1066
1067 int count = 0;
1068
1069 for( XMLNode* ele = xml.FirstChildElement( "Parent" )->FirstChild();
1070 ele;
1071 ele = ele->NextSibling() )
1072 {
1073 ++count;
1074 }
1075
1076 XMLTest( "Comments iterate correctly.", 3, count );
1077 }
1078
1079 {
1080 // trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
1081 unsigned char buf[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?><feed><![CDATA[Test XMLblablablalblbl";
1082 buf[60] = 239;
1083 buf[61] = 0;
1084
1085 XMLDocument doc;
1086 doc.Parse( (const char*)buf);
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001087 }
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001088
1089
1090 {
1091 // bug 1827248 Error while parsing a little bit malformed file
1092 // Actually not malformed - should work.
1093 XMLDocument xml;
1094 xml.Parse( "<attributelist> </attributelist >" );
1095 XMLTest( "Handle end tag whitespace", false, xml.Error() );
1096 }
1097
1098 {
1099 // This one must not result in an infinite loop
1100 XMLDocument xml;
1101 xml.Parse( "<infinite>loop" );
1102 XMLTest( "Infinite loop test.", true, true );
1103 }
1104#endif
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001105 {
1106 const char* pub = "<?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE>";
1107 XMLDocument doc;
1108 doc.Parse( pub );
1109
1110 XMLDocument clone;
1111 for( const XMLNode* node=doc.FirstChild(); node; node=node->NextSibling() ) {
1112 XMLNode* copy = node->ShallowClone( &clone );
1113 clone.InsertEndChild( copy );
1114 }
1115
1116 clone.Print();
1117
1118 int count=0;
1119 const XMLNode* a=clone.FirstChild();
1120 const XMLNode* b=doc.FirstChild();
1121 for( ; a && b; a=a->NextSibling(), b=b->NextSibling() ) {
1122 ++count;
1123 XMLTest( "Clone and Equal", true, a->ShallowEqual( b ));
1124 }
1125 XMLTest( "Clone and Equal", 4, count );
1126 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001127
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001128 {
1129 // This shouldn't crash.
1130 XMLDocument doc;
Lee Thomason85536252016-06-04 19:10:53 -07001131 if(XML_SUCCESS != doc.LoadFile( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ))
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001132 {
1133 doc.PrintError();
1134 }
1135 XMLTest( "Error in snprinf handling.", true, doc.Error() );
1136 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001137
Lee Thomason5e3803c2012-04-16 08:57:05 -07001138 {
1139 // Attribute ordering.
1140 static const char* xml = "<element attrib1=\"1\" attrib2=\"2\" attrib3=\"3\" />";
1141 XMLDocument doc;
1142 doc.Parse( xml );
1143 XMLElement* ele = doc.FirstChildElement();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001144
Lee Thomason5e3803c2012-04-16 08:57:05 -07001145 const XMLAttribute* a = ele->FirstAttribute();
1146 XMLTest( "Attribute order", "1", a->Value() );
1147 a = a->Next();
1148 XMLTest( "Attribute order", "2", a->Value() );
1149 a = a->Next();
1150 XMLTest( "Attribute order", "3", a->Value() );
1151 XMLTest( "Attribute order", "attrib3", a->Name() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001152
Lee Thomason5e3803c2012-04-16 08:57:05 -07001153 ele->DeleteAttribute( "attrib2" );
1154 a = ele->FirstAttribute();
1155 XMLTest( "Attribute order", "1", a->Value() );
1156 a = a->Next();
1157 XMLTest( "Attribute order", "3", a->Value() );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001158
Lee Thomason5e3803c2012-04-16 08:57:05 -07001159 ele->DeleteAttribute( "attrib1" );
1160 ele->DeleteAttribute( "attrib3" );
1161 XMLTest( "Attribute order (empty)", false, ele->FirstAttribute() ? true : false );
1162 }
Lee Thomason (grinliz)a4a36ba2012-04-06 21:24:29 -07001163
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001164 {
1165 // Make sure an attribute with a space in it succeeds.
Lee Thomason78a773d2012-07-02 10:10:19 -07001166 static const char* xml0 = "<element attribute1= \"Test Attribute\"/>";
1167 static const char* xml1 = "<element attribute1 =\"Test Attribute\"/>";
1168 static const char* xml2 = "<element attribute1 = \"Test Attribute\"/>";
1169 XMLDocument doc0;
1170 doc0.Parse( xml0 );
1171 XMLDocument doc1;
1172 doc1.Parse( xml1 );
1173 XMLDocument doc2;
1174 doc2.Parse( xml2 );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001175
Lee Thomason78a773d2012-07-02 10:10:19 -07001176 XMLElement* ele = 0;
1177 ele = doc0.FirstChildElement();
1178 XMLTest( "Attribute with space #1", "Test Attribute", ele->Attribute( "attribute1" ) );
1179 ele = doc1.FirstChildElement();
1180 XMLTest( "Attribute with space #2", "Test Attribute", ele->Attribute( "attribute1" ) );
1181 ele = doc2.FirstChildElement();
1182 XMLTest( "Attribute with space #3", "Test Attribute", ele->Attribute( "attribute1" ) );
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -07001183 }
1184
1185 {
1186 // Make sure we don't go into an infinite loop.
1187 static const char* xml = "<doc><element attribute='attribute'/><element attribute='attribute'/></doc>";
1188 XMLDocument doc;
1189 doc.Parse( xml );
1190 XMLElement* ele0 = doc.FirstChildElement()->FirstChildElement();
1191 XMLElement* ele1 = ele0->NextSiblingElement();
1192 bool equal = ele0->ShallowEqual( ele1 );
1193
1194 XMLTest( "Infinite loop in shallow equal.", true, equal );
1195 }
1196
Lee Thomason5708f812012-03-28 17:46:41 -07001197 // -------- Handles ------------
1198 {
1199 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1200 XMLDocument doc;
1201 doc.Parse( xml );
Lee Thomason5708f812012-03-28 17:46:41 -07001202
1203 XMLElement* ele = XMLHandle( doc ).FirstChildElement( "element" ).FirstChild().ToElement();
1204 XMLTest( "Handle, success, mutable", ele->Value(), "sub" );
1205
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001206 XMLHandle docH( doc );
1207 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001208 XMLTest( "Handle, dne, mutable", false, ele != 0 );
Lee Thomason5708f812012-03-28 17:46:41 -07001209 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001210
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001211 {
1212 static const char* xml = "<element attrib='bar'><sub>Text</sub></element>";
1213 XMLDocument doc;
1214 doc.Parse( xml );
1215 XMLConstHandle docH( doc );
1216
1217 const XMLElement* ele = docH.FirstChildElement( "element" ).FirstChild().ToElement();
1218 XMLTest( "Handle, success, const", ele->Value(), "sub" );
1219
1220 ele = docH.FirstChildElement( "none" ).FirstChildElement( "element" ).ToElement();
Lee Thomasond0b19df2012-04-12 08:41:37 -07001221 XMLTest( "Handle, dne, const", false, ele != 0 );
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001222 }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001223 {
1224 // Default Declaration & BOM
1225 XMLDocument doc;
1226 doc.InsertEndChild( doc.NewDeclaration() );
1227 doc.SetBOM( true );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001228
Lee Thomasonf68c4382012-04-28 14:37:11 -07001229 XMLPrinter printer;
1230 doc.Print( &printer );
1231
1232 static const char* result = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
1233 XMLTest( "BOM and default declaration", printer.CStr(), result, false );
Lee Thomason (grinliz)48ea0bc2012-05-26 14:41:14 -07001234 XMLTest( "CStrSize", printer.CStrSize(), 42, false );
Lee Thomasonf68c4382012-04-28 14:37:11 -07001235 }
Lee Thomason21be8822012-07-15 17:27:22 -07001236 {
1237 const char* xml = "<ipxml ws='1'><info bla=' /></ipxml>";
1238 XMLDocument doc;
1239 doc.Parse( xml );
1240 XMLTest( "Ill formed XML", true, doc.Error() );
1241 }
1242
1243 // QueryXYZText
1244 {
1245 const char* xml = "<point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point>";
1246 XMLDocument doc;
1247 doc.Parse( xml );
1248
1249 const XMLElement* pointElement = doc.RootElement();
1250
1251 int intValue = 0;
1252 unsigned unsignedValue = 0;
1253 float floatValue = 0;
1254 double doubleValue = 0;
1255 bool boolValue = false;
1256
1257 pointElement->FirstChildElement( "y" )->QueryIntText( &intValue );
1258 pointElement->FirstChildElement( "y" )->QueryUnsignedText( &unsignedValue );
1259 pointElement->FirstChildElement( "x" )->QueryFloatText( &floatValue );
1260 pointElement->FirstChildElement( "x" )->QueryDoubleText( &doubleValue );
1261 pointElement->FirstChildElement( "valid" )->QueryBoolText( &boolValue );
1262
1263
1264 XMLTest( "QueryIntText", intValue, 1, false );
1265 XMLTest( "QueryUnsignedText", unsignedValue, (unsigned)1, false );
1266 XMLTest( "QueryFloatText", floatValue, 1.2f, false );
1267 XMLTest( "QueryDoubleText", doubleValue, 1.2, false );
1268 XMLTest( "QueryBoolText", boolValue, true, false );
1269 }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001270
Lee Thomason (grinliz)5fbacbe2012-09-08 21:40:53 -07001271 {
1272 const char* xml = "<element><_sub/><:sub/><sub:sub/><sub-sub/></element>";
1273 XMLDocument doc;
1274 doc.Parse( xml );
1275 XMLTest( "Non-alpha element lead letter parses.", doc.Error(), false );
1276 }
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001277
1278 {
1279 const char* xml = "<element _attr1=\"foo\" :attr2=\"bar\"></element>";
1280 XMLDocument doc;
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001281 doc.Parse( xml );
Martinsh Shaiters23e7ae62013-01-26 20:15:44 +02001282 XMLTest("Non-alpha attribute lead character parses.", doc.Error(), false);
1283 }
Martinsh Shaiters95b3e652013-01-26 23:08:10 +02001284
1285 {
1286 const char* xml = "<3lement></3lement>";
1287 XMLDocument doc;
1288 doc.Parse( xml );
1289 XMLTest("Element names with lead digit fail to parse.", doc.Error(), true);
1290 }
Lee Thomason (grinliz)62d1c5a2012-09-08 21:44:12 -07001291
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001292 {
1293 const char* xml = "<element/>WOA THIS ISN'T GOING TO PARSE";
1294 XMLDocument doc;
1295 doc.Parse( xml, 10 );
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001296 XMLTest( "Set length of incoming data", doc.Error(), false );
1297 }
1298
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001299 {
1300 XMLDocument doc;
Dmitry-Me48b5df02015-04-06 18:20:25 +03001301 XMLTest( "Document is initially empty", doc.NoChildren(), true );
1302 doc.Clear();
1303 XMLTest( "Empty is empty after Clear()", doc.NoChildren(), true );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001304 doc.LoadFile( "resources/dream.xml" );
Dmitry-Meaaa4cea2015-02-06 16:00:46 +03001305 XMLTest( "Document has something to Clear()", doc.NoChildren(), false );
Martinsh Shaiters53ab79a2013-01-30 11:21:36 +02001306 doc.Clear();
1307 XMLTest( "Document Clear()'s", doc.NoChildren(), true );
1308 }
1309
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001310 // ----------- Whitespace ------------
1311 {
1312 const char* xml = "<element>"
1313 "<a> This \nis &apos; text &apos; </a>"
1314 "<b> This is &apos; text &apos; \n</b>"
1315 "<c>This is &apos; \n\n text &apos;</c>"
1316 "</element>";
1317 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1318 doc.Parse( xml );
1319
1320 const XMLElement* element = doc.FirstChildElement();
1321 for( const XMLElement* parent = element->FirstChildElement();
1322 parent;
1323 parent = parent->NextSiblingElement() )
1324 {
1325 XMLTest( "Whitespace collapse", "This is ' text '", parent->GetText() );
1326 }
1327 }
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001328
Lee Thomasonae9ab072012-10-24 10:17:53 -07001329#if 0
1330 {
1331 // Passes if assert doesn't fire.
1332 XMLDocument xmlDoc;
1333
1334 xmlDoc.NewDeclaration();
1335 xmlDoc.NewComment("Configuration file");
1336
1337 XMLElement *root = xmlDoc.NewElement("settings");
1338 root->SetAttribute("version", 2);
1339 }
1340#endif
1341
Lee Thomason (grinliz)0fa82992012-09-08 21:53:47 -07001342 {
1343 const char* xml = "<element> </element>";
1344 XMLDocument doc( true, COLLAPSE_WHITESPACE );
1345 doc.Parse( xml );
1346 XMLTest( "Whitespace all space", true, 0 == doc.FirstChildElement()->FirstChild() );
1347 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001348
Lee Thomason5b0a6772012-11-19 13:54:42 -08001349 {
1350 // An assert should not fire.
1351 const char* xml = "<element/>";
1352 XMLDocument doc;
1353 doc.Parse( xml );
1354 XMLElement* ele = doc.NewElement( "unused" ); // This will get cleaned up with the 'doc' going out of scope.
1355 XMLTest( "Tracking unused elements", true, ele != 0, false );
1356 }
1357
Lee Thomasona6412ac2012-12-13 15:39:11 -08001358
1359 {
1360 const char* xml = "<parent><child>abc</child></parent>";
1361 XMLDocument doc;
1362 doc.Parse( xml );
1363 XMLElement* ele = doc.FirstChildElement( "parent")->FirstChildElement( "child");
1364
1365 XMLPrinter printer;
1366 ele->Accept( &printer );
1367 XMLTest( "Printing of sub-element", "<child>abc</child>\n", printer.CStr(), false );
1368 }
1369
1370
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001371 {
1372 XMLDocument doc;
1373 XMLError error = doc.LoadFile( "resources/empty.xml" );
1374 XMLTest( "Loading an empty file", XML_ERROR_EMPTY_DOCUMENT, error );
Lee Thomason331596e2014-09-11 14:56:43 -07001375 XMLTest( "Loading an empty file and ErrorName as string", "XML_ERROR_EMPTY_DOCUMENT", doc.ErrorName() );
Lee Thomasonc7556672014-09-14 12:39:42 -07001376 doc.PrintError();
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001377 }
1378
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001379 {
1380 // BOM preservation
1381 static const char* xml_bom_preservation = "\xef\xbb\xbf<element/>\n";
1382 {
1383 XMLDocument doc;
Lee Thomason85536252016-06-04 19:10:53 -07001384 XMLTest( "BOM preservation (parse)", XML_SUCCESS, doc.Parse( xml_bom_preservation ), false );
Lee Thomason (grinliz)d0a38c32013-04-29 09:15:37 -07001385 XMLPrinter printer;
1386 doc.Print( &printer );
1387
1388 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1389 doc.SaveFile( "resources/bomtest.xml" );
1390 }
1391 {
1392 XMLDocument doc;
1393 doc.LoadFile( "resources/bomtest.xml" );
1394 XMLTest( "BOM preservation (load)", true, doc.HasBOM(), false );
1395
1396 XMLPrinter printer;
1397 doc.Print( &printer );
1398 XMLTest( "BOM preservation (compare)", xml_bom_preservation, printer.CStr(), false, true );
1399 }
1400 }
Vasily Biryukov1cfafd02013-04-20 14:12:33 +06001401
Michael Daumlinged523282013-10-23 07:47:29 +02001402 {
1403 // Insertion with Removal
1404 const char* xml = "<?xml version=\"1.0\" ?>"
1405 "<root>"
1406 "<one>"
1407 "<subtree>"
1408 "<elem>element 1</elem>text<!-- comment -->"
1409 "</subtree>"
1410 "</one>"
1411 "<two/>"
1412 "</root>";
1413 const char* xmlInsideTwo = "<?xml version=\"1.0\" ?>"
1414 "<root>"
1415 "<one/>"
1416 "<two>"
1417 "<subtree>"
1418 "<elem>element 1</elem>text<!-- comment -->"
1419 "</subtree>"
1420 "</two>"
1421 "</root>";
1422 const char* xmlAfterOne = "<?xml version=\"1.0\" ?>"
1423 "<root>"
1424 "<one/>"
1425 "<subtree>"
1426 "<elem>element 1</elem>text<!-- comment -->"
1427 "</subtree>"
1428 "<two/>"
1429 "</root>";
1430 const char* xmlAfterTwo = "<?xml version=\"1.0\" ?>"
1431 "<root>"
1432 "<one/>"
1433 "<two/>"
1434 "<subtree>"
1435 "<elem>element 1</elem>text<!-- comment -->"
1436 "</subtree>"
1437 "</root>";
1438
1439 XMLDocument doc;
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001440 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001441 XMLElement* subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1442 XMLElement* two = doc.RootElement()->FirstChildElement("two");
1443 two->InsertFirstChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001444 XMLPrinter printer1(0, true);
1445 doc.Accept(&printer1);
1446 XMLTest("Move node from within <one> to <two>", xmlInsideTwo, printer1.CStr());
Michael Daumlinged523282013-10-23 07:47:29 +02001447
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001448 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001449 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1450 two = doc.RootElement()->FirstChildElement("two");
1451 doc.RootElement()->InsertAfterChild(two, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001452 XMLPrinter printer2(0, true);
1453 doc.Accept(&printer2);
1454 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer2.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001455
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001456 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001457 XMLNode* one = doc.RootElement()->FirstChildElement("one");
1458 subtree = one->FirstChildElement("subtree");
1459 doc.RootElement()->InsertAfterChild(one, subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001460 XMLPrinter printer3(0, true);
1461 doc.Accept(&printer3);
1462 XMLTest("Move node from within <one> after <one>", xmlAfterOne, printer3.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001463
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001464 doc.Parse(xml);
Michael Daumlinged523282013-10-23 07:47:29 +02001465 subtree = doc.RootElement()->FirstChildElement("one")->FirstChildElement("subtree");
1466 two = doc.RootElement()->FirstChildElement("two");
1467 doc.RootElement()->InsertEndChild(subtree);
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001468 XMLPrinter printer4(0, true);
1469 doc.Accept(&printer4);
1470 XMLTest("Move node from within <one> after <two>", xmlAfterTwo, printer4.CStr(), false);
Michael Daumlinged523282013-10-23 07:47:29 +02001471 }
1472
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001473 {
1474 const char* xml = "<svg width = \"128\" height = \"128\">"
1475 " <text> </text>"
1476 "</svg>";
1477 XMLDocument doc;
1478 doc.Parse(xml);
1479 doc.Print();
1480 }
1481
Lee Thomason92e521b2014-11-15 17:45:51 -08001482 {
1483 // Test that it doesn't crash.
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001484 const char* xml = "<?xml version=\"1.0\"?><root><sample><field0><1</field0><field1>2</field1></sample></root>";
1485 XMLDocument doc;
1486 doc.Parse(xml);
1487 doc.PrintError();
Lee Thomason92e521b2014-11-15 17:45:51 -08001488 }
1489
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001490#if 1
1491 // the question being explored is what kind of print to use:
1492 // https://github.com/leethomason/tinyxml2/issues/63
1493 {
1494 //const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
1495 const char* xml = "<element/>";
1496 XMLDocument doc;
1497 doc.Parse( xml );
1498 doc.FirstChildElement()->SetAttribute( "attrA-f64", 123456789.123456789 );
1499 doc.FirstChildElement()->SetAttribute( "attrB-f64", 1.001e9 );
1500 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e9 );
1501 doc.FirstChildElement()->SetAttribute( "attrC-f64", 1.0e20 );
1502 doc.FirstChildElement()->SetAttribute( "attrD-f64", 1.0e-10 );
1503 doc.FirstChildElement()->SetAttribute( "attrD-f64", 0.123456789 );
1504
1505 doc.FirstChildElement()->SetAttribute( "attrA-f32", 123456789.123456789f );
1506 doc.FirstChildElement()->SetAttribute( "attrB-f32", 1.001e9f );
1507 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e9f );
1508 doc.FirstChildElement()->SetAttribute( "attrC-f32", 1.0e20f );
1509 doc.FirstChildElement()->SetAttribute( "attrD-f32", 1.0e-10f );
1510 doc.FirstChildElement()->SetAttribute( "attrD-f32", 0.123456789f );
1511
1512 doc.Print();
1513
1514 /* The result of this test is platform, compiler, and library version dependent. :("
1515 XMLPrinter printer;
1516 doc.Print( &printer );
1517 XMLTest( "Float and double formatting.",
1518 "<element attrA-f64=\"123456789.12345679\" attrB-f64=\"1001000000\" attrC-f64=\"1e+20\" attrD-f64=\"0.123456789\" attrA-f32=\"1.2345679e+08\" attrB-f32=\"1.001e+09\" attrC-f32=\"1e+20\" attrD-f32=\"0.12345679\"/>\n",
1519 printer.CStr(),
1520 true );
1521 */
1522 }
1523#endif
Lee Thomasonf07b9522014-10-30 13:25:12 -07001524
1525 {
1526 // Issue #184
1527 // If it doesn't assert, it passes. Caused by objects
1528 // getting created during parsing which are then
1529 // inaccessible in the memory pools.
1530 {
1531 XMLDocument doc;
1532 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1533 }
1534 {
1535 XMLDocument doc;
1536 doc.Parse("<?xml version=\"1.0\" encoding=\"UTF-8\"?><test>");
1537 doc.Clear();
1538 }
1539 }
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001540
1541 {
1542 // If this doesn't assert in DEBUG, all is well.
1543 tinyxml2::XMLDocument doc;
1544 tinyxml2::XMLElement *pRoot = doc.NewElement("Root");
1545 doc.DeleteNode(pRoot);
1546 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001547
Dmitry-Me8b67d742014-12-22 11:35:12 +03001548 {
1549 // Should not assert in DEBUG
1550 XMLPrinter printer;
1551 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001552
Dmitry-Me6f51c802015-03-14 13:25:03 +03001553 {
1554 // Issue 291. Should not crash
1555 const char* xml = "&#0</a>";
1556 XMLDocument doc;
1557 doc.Parse( xml );
1558
1559 XMLPrinter printer;
1560 doc.Print( &printer );
1561 }
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001562 {
1563 // Issue 299. Can print elements that are not linked in.
1564 // Will crash if issue not fixed.
1565 XMLDocument doc;
1566 XMLElement* newElement = doc.NewElement( "printme" );
1567 XMLPrinter printer;
1568 newElement->Accept( &printer );
Dmitry-Me5daa54c2015-04-08 17:45:07 +03001569 // Delete the node to avoid possible memory leak report in debug output
1570 doc.DeleteNode( newElement );
Ant Mitchell148cc1a2015-03-24 15:12:35 +00001571 }
Lee Thomasonf6577832015-03-26 11:18:21 -07001572 {
Ant Mitchell189198f2015-03-24 16:20:36 +00001573 // Issue 302. Clear errors from LoadFile/SaveFile
1574 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001575 XMLTest( "Issue 302. Should be no error initially", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001576 doc.SaveFile( "./no/such/path/pretty.xml" );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001577 XMLTest( "Issue 302. Fail to save", "XML_ERROR_FILE_COULD_NOT_BE_OPENED", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001578 doc.SaveFile( "./resources/out/compact.xml", true );
Dmitry-Me32533ca2015-04-07 10:37:39 +03001579 XMLTest( "Issue 302. Subsequent success in saving", "XML_SUCCESS", doc.ErrorName() );
Ant Mitchell189198f2015-03-24 16:20:36 +00001580 }
Dmitry-Me6f51c802015-03-14 13:25:03 +03001581
Dmitry-Med9852a52015-03-25 10:17:49 +03001582 {
1583 // If a document fails to load then subsequent
1584 // successful loads should clear the error
1585 XMLDocument doc;
Dmitry-Me32533ca2015-04-07 10:37:39 +03001586 XMLTest( "Should be no error initially", false, doc.Error() );
Dmitry-Med9852a52015-03-25 10:17:49 +03001587 doc.LoadFile( "resources/no-such-file.xml" );
1588 XMLTest( "No such file - should fail", true, doc.Error() );
1589
1590 doc.LoadFile( "resources/dream.xml" );
1591 XMLTest( "Error should be cleared", false, doc.Error() );
1592 }
Sarat Addepalli8e85afa2015-05-19 09:07:03 +05301593
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301594 {
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001595 // Check that declarations are allowed only at beginning of document
Lee Thomason85492022015-05-22 11:07:45 -07001596 const char* xml0 = "<?xml version=\"1.0\" ?>"
1597 " <!-- xml version=\"1.1\" -->"
1598 "<first />";
1599 const char* xml1 = "<?xml version=\"1.0\" ?>"
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001600 "<?xml-stylesheet type=\"text/xsl\" href=\"Anything.xsl\"?>"
Lee Thomason85492022015-05-22 11:07:45 -07001601 "<first />";
1602 const char* xml2 = "<first />"
1603 "<?xml version=\"1.0\" ?>";
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001604 const char* xml3 = "<first></first>"
1605 "<?xml version=\"1.0\" ?>";
1606
1607 const char* xml4 = "<first><?xml version=\"1.0\" ?></first>";
1608
Lee Thomason85492022015-05-22 11:07:45 -07001609 XMLDocument doc;
1610 doc.Parse(xml0);
1611 XMLTest("Test that the code changes do not affect normal parsing", doc.Error(), false);
1612 doc.Parse(xml1);
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001613 XMLTest("Test that the second declaration is allowed", doc.Error(), false);
Lee Thomason85492022015-05-22 11:07:45 -07001614 doc.Parse(xml2);
Dmitry-Me446c3bc2016-11-11 10:34:56 +03001615 XMLTest("Test that declaration after a child is not allowed", doc.ErrorID(), XML_ERROR_PARSING_DECLARATION);
1616 doc.Parse(xml3);
1617 XMLTest("Test that declaration after a child is not allowed", doc.ErrorID(), XML_ERROR_PARSING_DECLARATION);
1618 doc.Parse(xml4);
1619 XMLTest("Test that declaration inside a child is not allowed", doc.ErrorID(), XML_ERROR_PARSING_DECLARATION);
Sarat Addepalli2bb6bb52015-05-18 09:16:34 +05301620 }
Dmitry-Med9852a52015-03-25 10:17:49 +03001621
Lee Thomason85492022015-05-22 11:07:45 -07001622 {
1623 // No matter - before or after successfully parsing a text -
1624 // calling XMLDocument::Value() causes an assert in debug.
1625 const char* validXml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
1626 "<first />"
1627 "<second />";
1628 XMLDocument* doc = new XMLDocument();
1629 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1630 doc->Parse( validXml );
1631 XMLTest( "XMLDocument::Value() returns null?", NULL, doc->Value() );
1632 delete doc;
1633 }
1634
Dmitry-Mea1beddf2015-05-26 16:19:21 +03001635 {
1636 XMLDocument doc;
1637 for( int i = 0; i < XML_ERROR_COUNT; i++ ) {
kezenatorec694152016-11-26 17:21:43 +10001638 doc.SetError( (XMLError)i, 0, 0, 0 );
Dmitry-Mea1beddf2015-05-26 16:19:21 +03001639 doc.ErrorName();
1640 }
1641 }
1642
kezenatorec694152016-11-26 17:21:43 +10001643 // ----------- Line Number Tracking --------------
1644 {
Lee Thomasone90e9012016-12-24 07:34:39 -08001645 struct TestUtil: XMLVisitor
kezenatorec694152016-11-26 17:21:43 +10001646 {
1647 void TestParseError(const char *testString, const char *docStr, XMLError expected_error, int expectedLine)
1648 {
1649 XMLDocument doc;
1650 XMLError err = doc.Parse(docStr);
1651
1652 XMLTest(testString, true, doc.Error());
1653 XMLTest(testString, expected_error, err);
1654 XMLTest(testString, expectedLine, doc.GetErrorLineNum());
1655 };
1656
1657 void TestStringLines(const char *testString, const char *docStr, const char *expectedLines)
1658 {
1659 XMLDocument doc;
1660 doc.Parse(docStr);
1661 XMLTest(testString, false, doc.Error());
1662 TestDocLines(testString, doc, expectedLines);
1663 }
1664
1665 void TestFileLines(const char *testString, const char *file_name, const char *expectedLines)
1666 {
1667 XMLDocument doc;
1668 doc.LoadFile(file_name);
1669 XMLTest(testString, false, doc.Error());
1670 TestDocLines(testString, doc, expectedLines);
1671 }
1672
1673 private:
1674 DynArray<char, 10> str;
1675
1676 void Push(char type, int lineNum)
1677 {
1678 str.Push(type);
1679 str.Push(char('0' + (lineNum / 10)));
1680 str.Push(char('0' + (lineNum % 10)));
1681 }
1682
1683 bool VisitEnter(const XMLDocument& doc)
1684 {
kezenator19d8ea82016-11-29 19:50:27 +10001685 Push('D', doc.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001686 return true;
1687 }
1688 bool VisitEnter(const XMLElement& element, const XMLAttribute* firstAttribute)
1689 {
kezenator19d8ea82016-11-29 19:50:27 +10001690 Push('E', element.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001691 for (const XMLAttribute *attr = firstAttribute; attr != 0; attr = attr->Next())
kezenator19d8ea82016-11-29 19:50:27 +10001692 Push('A', attr->GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001693 return true;
1694 }
1695 bool Visit(const XMLDeclaration& declaration)
1696 {
kezenator19d8ea82016-11-29 19:50:27 +10001697 Push('L', declaration.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001698 return true;
1699 }
1700 bool Visit(const XMLText& text)
1701 {
kezenator19d8ea82016-11-29 19:50:27 +10001702 Push('T', text.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001703 return true;
1704 }
1705 bool Visit(const XMLComment& comment)
1706 {
kezenator19d8ea82016-11-29 19:50:27 +10001707 Push('C', comment.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001708 return true;
1709 }
1710 bool Visit(const XMLUnknown& unknown)
1711 {
kezenator19d8ea82016-11-29 19:50:27 +10001712 Push('U', unknown.GetLineNum());
kezenatorec694152016-11-26 17:21:43 +10001713 return true;
1714 }
1715
1716 void TestDocLines(const char *testString, XMLDocument &doc, const char *expectedLines)
1717 {
1718 str.Clear();
1719 doc.Accept(this);
1720 str.Push(0);
1721 XMLTest(testString, expectedLines, str.Mem());
1722 }
Lee Thomasone90e9012016-12-24 07:34:39 -08001723 } tester;
kezenatorec694152016-11-26 17:21:43 +10001724
Lee Thomasone90e9012016-12-24 07:34:39 -08001725 tester.TestParseError("ErrorLine-Parsing", "\n<root>\n foo \n<unclosed/>", XML_ERROR_PARSING, 2);
1726 tester.TestParseError("ErrorLine-Declaration", "<root>\n<?xml version=\"1.0\"?>", XML_ERROR_PARSING_DECLARATION, 2);
1727 tester.TestParseError("ErrorLine-Mismatch", "\n<root>\n</mismatch>", XML_ERROR_MISMATCHED_ELEMENT, 2);
1728 tester.TestParseError("ErrorLine-CData", "\n<root><![CDATA[ \n foo bar \n", XML_ERROR_PARSING_CDATA, 2);
1729 tester.TestParseError("ErrorLine-Text", "\n<root>\n foo bar \n", XML_ERROR_PARSING_TEXT, 3);
1730 tester.TestParseError("ErrorLine-Comment", "\n<root>\n<!-- >\n", XML_ERROR_PARSING_COMMENT, 3);
1731 tester.TestParseError("ErrorLine-Declaration", "\n<root>\n<? >\n", XML_ERROR_PARSING_DECLARATION, 3);
1732 tester.TestParseError("ErrorLine-Unknown", "\n<root>\n<! \n", XML_ERROR_PARSING_UNKNOWN, 3);
1733 tester.TestParseError("ErrorLine-Element", "\n<root>\n<unclosed \n", XML_ERROR_PARSING_ELEMENT, 3);
1734 tester.TestParseError("ErrorLine-Attribute", "\n<root>\n<unclosed \n att\n", XML_ERROR_PARSING_ATTRIBUTE, 4);
1735 tester.TestParseError("ErrorLine-ElementClose", "\n<root>\n<unclosed \n/unexpected", XML_ERROR_PARSING_ELEMENT, 3);
kezenatorec694152016-11-26 17:21:43 +10001736
Lee Thomasone90e9012016-12-24 07:34:39 -08001737 tester.TestStringLines(
kezenatorec694152016-11-26 17:21:43 +10001738 "LineNumbers-String",
Lee Thomasone90e9012016-12-24 07:34:39 -08001739
1740 "<?xml version=\"1.0\"?>\n" // 1 Doc, DecL
1741 "<root a='b' \n" // 2 Element Attribute
1742 "c='d'> d <blah/> \n" // 3 Attribute Text Element
1743 "newline in text \n" // 4 Text
1744 "and second <zxcv/><![CDATA[\n" // 5 Element Text
1745 " cdata test ]]><!-- comment -->\n" // 6 Comment
1746 "<! unknown></root>", // 7 Unknown
1747
kezenatorec694152016-11-26 17:21:43 +10001748 "D01L01E02A02A03T03E03T04E05T05C06U07");
1749
Lee Thomasone90e9012016-12-24 07:34:39 -08001750 tester.TestStringLines(
kezenatorec694152016-11-26 17:21:43 +10001751 "LineNumbers-CRLF",
Lee Thomasone90e9012016-12-24 07:34:39 -08001752
1753 "\r\n" // 1 Doc (arguably should be line 2)
1754 "<?xml version=\"1.0\"?>\n" // 2 DecL
1755 "<root>\r\n" // 3 Element
1756 "\n" // 4
1757 "text contining new line \n" // 5 Text
1758 " and also containing crlf \r\n" // 6
1759 "<sub><![CDATA[\n" // 7 Element Text
1760 "cdata containing new line \n" // 8
1761 " and also containing cflr\r\n" // 9
1762 "]]></sub><sub2/></root>", // 10 Element
1763
kezenatorec694152016-11-26 17:21:43 +10001764 "D01L02E03T05E07T07E10");
1765
Lee Thomasone90e9012016-12-24 07:34:39 -08001766 tester.TestFileLines(
kezenatorec694152016-11-26 17:21:43 +10001767 "LineNumbers-File",
1768 "resources/utf8test.xml",
1769 "D01L01E02E03A03A03T03E04A04A04T04E05A05A05T05E06A06A06T06E07A07A07T07E08A08A08T08E09T09E10T10");
1770 }
1771
Lee Thomason85492022015-05-22 11:07:45 -07001772 // ----------- Performance tracking --------------
Lee Thomason6f381b72012-03-02 12:59:39 -08001773 {
1774#if defined( _MSC_VER )
1775 __int64 start, end, freq;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001776 QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
Lee Thomason6f381b72012-03-02 12:59:39 -08001777#endif
1778
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001779 FILE* perfFP = fopen("resources/dream.xml", "r");
1780 fseek(perfFP, 0, SEEK_END);
Armagetron3c21d6f2016-10-13 13:31:23 +02001781 long size = ftell(perfFP);
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001782 fseek(perfFP, 0, SEEK_SET);
Lee Thomason6f381b72012-03-02 12:59:39 -08001783
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001784 char* mem = new char[size + 1];
1785 fread(mem, size, 1, perfFP);
1786 fclose(perfFP);
Lee Thomason6f381b72012-03-02 12:59:39 -08001787 mem[size] = 0;
1788
1789#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001790 QueryPerformanceCounter((LARGE_INTEGER*)&start);
Lee Thomason6f381b72012-03-02 12:59:39 -08001791#else
1792 clock_t cstart = clock();
1793#endif
1794 static const int COUNT = 10;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001795 for (int i = 0; i < COUNT; ++i) {
Lee Thomason6f381b72012-03-02 12:59:39 -08001796 XMLDocument doc;
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001797 doc.Parse(mem);
Lee Thomason6f381b72012-03-02 12:59:39 -08001798 }
1799#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001800 QueryPerformanceCounter((LARGE_INTEGER*)&end);
Lee Thomason6f381b72012-03-02 12:59:39 -08001801#else
1802 clock_t cend = clock();
1803#endif
1804
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001805 delete[] mem;
Lee Thomason6f381b72012-03-02 12:59:39 -08001806
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001807 static const char* note =
Lee Thomason6f381b72012-03-02 12:59:39 -08001808#ifdef DEBUG
1809 "DEBUG";
1810#else
1811 "Release";
1812#endif
1813
1814#if defined( _MSC_VER )
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001815 printf("\nParsing %s of dream.xml: %.3f milli-seconds\n", note, 1000.0 * (double)(end - start) / ((double)freq * (double)COUNT));
Lee Thomason6f381b72012-03-02 12:59:39 -08001816#else
Lee Thomasondf4ffc02016-06-04 11:32:46 -07001817 printf("\nParsing %s of dream.xml: %.3f milli-seconds\n", note, (double)(cend - cstart) / (double)COUNT);
Lee Thomason6f381b72012-03-02 12:59:39 -08001818#endif
1819 }
1820
Lee Thomason (grinliz)7ca55582012-03-07 21:54:57 -08001821 #if defined( _MSC_VER ) && defined( DEBUG )
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001822 _CrtMemCheckpoint( &endMemState );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001823
1824 _CrtMemState diffMemState;
1825 _CrtMemDifference( &diffMemState, &startMemState, &endMemState );
1826 _CrtMemDumpStatistics( &diffMemState );
1827 #endif
1828
1829 printf ("\nPass %d, Fail %d\n", gPass, gFail);
Lee Thomason (grinliz)db304252013-07-31 12:24:52 -07001830
1831 return gFail;
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -08001832}