2012-11-19 21:54:42 +00:00
# if defined( _MSC_VER )
# define _CRT_SECURE_NO_WARNINGS // This test file is not intended to be secure.
# endif
2011-12-28 22:36:55 +00:00
2012-11-19 21:54:42 +00:00
# include "tinyxml2.h"
2012-03-20 18:26:57 +00:00
# include <cstdlib>
# include <cstring>
# include <ctime>
2011-12-28 22:36:55 +00:00
2012-02-25 01:37:53 +00:00
# if defined( _MSC_VER )
2012-07-25 19:24:23 +00:00
# include <direct.h> // _mkdir
2012-02-15 02:18:16 +00:00
# include <crtdbg.h>
2012-03-02 20:59:39 +00:00
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
2012-02-15 02:18:16 +00:00
_CrtMemState startMemState ;
_CrtMemState endMemState ;
2013-01-15 19:53:08 +00:00
# elif defined(MINGW32) || defined(__MINGW32__)
# include <io.h> // mkdir
2012-07-25 19:24:23 +00:00
# else
# include <sys/stat.h> // mkdir
2012-02-15 02:18:16 +00:00
# endif
2012-02-14 02:11:20 +00:00
2011-12-28 22:36:55 +00:00
using namespace tinyxml2 ;
2012-02-14 02:16:52 +00:00
int gPass = 0 ;
int gFail = 0 ;
2012-02-21 04:14:33 +00:00
2013-04-29 16:15:37 +00:00
bool XMLTest ( const char * testString , const char * expected , const char * found , bool echo = true , bool extraNL = false )
2012-02-15 02:18:16 +00:00
{
bool pass = ! strcmp ( expected , found ) ;
if ( pass )
printf ( " [pass] " ) ;
else
printf ( " [fail] " ) ;
2013-04-29 16:15:37 +00:00
if ( ! echo ) {
2012-02-15 02:18:16 +00:00
printf ( " %s \n " , testString ) ;
2013-04-29 16:15:37 +00:00
}
else {
if ( extraNL ) {
printf ( " %s \n " , testString ) ;
printf ( " %s \n " , expected ) ;
printf ( " %s \n " , found ) ;
}
else {
printf ( " %s [%s][%s] \n " , testString , expected , found ) ;
}
}
2012-02-15 02:18:16 +00:00
if ( pass )
+ + gPass ;
else
+ + gFail ;
return pass ;
}
2012-07-16 00:27:22 +00:00
template < class T > bool XMLTest ( const char * testString , T expected , T found , bool echo = true )
2012-02-15 02:18:16 +00:00
{
bool pass = ( expected = = found ) ;
if ( pass )
printf ( " [pass] " ) ;
else
printf ( " [fail] " ) ;
2012-02-17 16:31:16 +00:00
if ( ! echo )
2012-02-15 02:18:16 +00:00
printf ( " %s \n " , testString ) ;
else
2012-07-16 19:44:41 +00:00
printf ( " %s [%d][%d] \n " , testString , static_cast < int > ( expected ) , static_cast < int > ( found ) ) ;
2012-02-15 02:18:16 +00:00
if ( pass )
+ + gPass ;
else
+ + gFail ;
return pass ;
}
2012-02-14 02:16:52 +00:00
2011-12-28 22:36:55 +00:00
2012-02-21 17:08:12 +00:00
void NullLineEndings ( char * p )
{
while ( p & & * p ) {
if ( * p = = ' \n ' | | * p = = ' \r ' ) {
* p = 0 ;
return ;
}
+ + p ;
}
}
2012-04-04 19:39:05 +00:00
int example_1 ( )
{
XMLDocument doc ;
2012-05-07 07:58:11 +00:00
doc . LoadFile ( " resources/dream.xml " ) ;
2012-04-04 19:39:05 +00:00
return doc . ErrorID ( ) ;
}
2013-01-16 00:08:19 +00:00
/** @page Example-1 Load an XML File
* @ dontinclude . / xmltest . cpp
* Basic XML file loading .
* The basic syntax to load an XML file from
* disk and check for an error . ( ErrorID ( )
* will return 0 for no error . )
* @ skip example_1 ( )
* @ until }
*/
2012-04-04 19:39:05 +00:00
int example_2 ( )
{
static const char * xml = " <element/> " ;
XMLDocument doc ;
doc . Parse ( xml ) ;
return doc . ErrorID ( ) ;
}
2013-01-16 00:08:19 +00:00
/** @page Example-2 Parse an XML from char buffer
* @ dontinclude . / xmltest . cpp
* Basic XML string parsing .
* The basic syntax to parse an XML for
* a char * and check for an error . ( ErrorID ( )
* will return 0 for no error . )
* @ skip example_2 ( )
* @ until }
*/
2012-04-04 19:39:05 +00:00
int example_3 ( )
{
2012-09-16 18:32:34 +00:00
static const char * xml =
2012-04-07 04:24:29 +00:00
" <?xml version= \" 1.0 \" ?> "
" <!DOCTYPE PLAY SYSTEM \" play.dtd \" > "
" <PLAY> "
" <TITLE>A Midsummer Night's Dream</TITLE> "
" </PLAY> " ;
2012-04-04 19:39:05 +00:00
XMLDocument doc ;
doc . Parse ( xml ) ;
XMLElement * titleElement = doc . FirstChildElement ( " PLAY " ) - > FirstChildElement ( " TITLE " ) ;
const char * title = titleElement - > GetText ( ) ;
printf ( " Name of play (1): %s \n " , title ) ;
2012-09-16 18:32:34 +00:00
2012-04-04 19:39:05 +00:00
XMLText * textNode = titleElement - > FirstChild ( ) - > ToText ( ) ;
title = textNode - > Value ( ) ;
printf ( " Name of play (2): %s \n " , title ) ;
return doc . ErrorID ( ) ;
}
2013-01-16 00:08:19 +00:00
/** @page Example-3 Get information out of XML
@ dontinclude . / xmltest . cpp
In this example , we navigate a simple XML
file , and read some interesting text . Note
2013-03-10 03:09:45 +00:00
that this example doesn ' t use error
2013-01-16 00:08:19 +00:00
checking ; working code should check for null
pointers when walking an XML tree , or use
XMLHandle .
( The XML is an excerpt from " dream.xml " ) .
@ skip example_3 ( )
@ until < / PLAY > " ;
The structure of the XML file is :
< ul >
< li > ( declaration ) < / li >
< li > ( dtd stuff ) < / li >
< li > Element " PLAY " < / li >
< ul >
< li > Element " TITLE " < / li >
< ul >
< li > Text " A Midsummer Night's Dream " < / li >
< / ul >
< / ul >
< / ul >
For this example , we want to print out the
title of the play . The text of the title ( what
we want ) is child of the " TITLE " element which
is a child of the " PLAY " element .
We want to skip the declaration and dtd , so the
method FirstChildElement ( ) is a good choice . The
FirstChildElement ( ) of the Document is the " PLAY "
Element , the FirstChildElement ( ) of the " PLAY " Element
is the " TITLE " Element .
@ until ( " TITLE " ) ;
We can then use the convenience function GetText ( )
to get the title of the play .
@ until title ) ;
Text is just another Node in the XML DOM . And in
fact you should be a little cautious with it , as
text nodes can contain elements .
@ verbatim
Consider : A Midsummer Night ' s < b > Dream < / b >
@ endverbatim
It is more correct to actually query the Text Node
if in doubt :
@ until title ) ;
Noting that here we use FirstChild ( ) since we are
looking for XMLText , not an element , and ToText ( )
is a cast from a Node to a XMLText .
*/
2012-04-04 19:39:05 +00:00
2012-07-16 00:27:22 +00:00
bool example_4 ( )
{
static const char * xml =
" <information> "
" <attributeApproach v='2' /> "
" <textApproach> "
" <v>2</v> "
" </textApproach> "
" </information> " ;
2012-09-16 18:32:34 +00:00
2012-07-16 00:27:22 +00:00
XMLDocument doc ;
doc . Parse ( xml ) ;
int v0 = 0 ;
int v1 = 0 ;
XMLElement * attributeApproachElement = doc . FirstChildElement ( ) - > FirstChildElement ( " attributeApproach " ) ;
attributeApproachElement - > QueryIntAttribute ( " v " , & v0 ) ;
XMLElement * textApproachElement = doc . FirstChildElement ( ) - > FirstChildElement ( " textApproach " ) ;
textApproachElement - > FirstChildElement ( " v " ) - > QueryIntText ( & v1 ) ;
printf ( " Both values are the same: %d and %d \n " , v0 , v1 ) ;
return ! doc . Error ( ) & & ( v0 = = v1 ) ;
}
2013-01-16 00:08:19 +00:00
/** @page Example-4 Read attributes and text information.
@ dontinclude . / xmltest . cpp
There are fundamentally 2 ways of writing a key - value
pair into an XML file . ( Something that ' s always annoyed
me about XML . ) Either by using attributes , or by writing
the key name into an element and the value into
the text node wrapped by the element . Both approaches
are illustrated in this example , which shows two ways
to encode the value " 2 " into the key " v " :
@ skip example_4 ( )
@ until " </information> " ;
TinyXML - 2 has accessors for both approaches .
When using an attribute , you navigate to the XMLElement
with that attribute and use the QueryIntAttribute ( )
group of methods . ( Also QueryFloatAttribute ( ) , etc . )
@ skip XMLElement * attributeApproachElement
@ until & v0 ) ;
When using the text approach , you need to navigate
down one more step to the XMLElement that contains
the text . Note the extra FirstChildElement ( " v " )
in the code below . The value of the text can then
be safely queried with the QueryIntText ( ) group
of methods . ( Also QueryFloatText ( ) , etc . )
@ skip XMLElement * textApproachElement
@ until & v1 ) ;
*/
2012-07-16 00:27:22 +00:00
2013-01-26 00:19:05 +00:00
int main ( int argc , const char * * argv )
2011-12-28 22:36:55 +00:00
{
2012-02-28 04:50:52 +00:00
# if defined( _MSC_VER ) && defined( DEBUG )
2012-02-15 02:18:16 +00:00
_CrtMemCheckpoint ( & startMemState ) ;
2012-09-16 18:32:34 +00:00
# endif
2012-01-19 01:43:40 +00:00
2013-01-15 19:53:08 +00:00
# if defined(_MSC_VER) || defined(MINGW32) || defined(__MINGW32__)
2013-05-05 15:42:52 +00:00
# if defined __MINGW64_VERSION_MAJOR && defined __MINGW64_VERSION_MINOR
//MINGW64: both 32 and 64-bit
mkdir ( " resources/out/ " ) ;
# else
_mkdir ( " resources/out/ " ) ;
# endif
2012-07-25 19:24:23 +00:00
# else
mkdir ( " resources/out/ " , S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH ) ;
# endif
2012-07-23 20:24:07 +00:00
2013-01-26 00:19:05 +00:00
if ( argc > 1 ) {
XMLDocument * doc = new XMLDocument ( ) ;
clock_t startTime = clock ( ) ;
doc - > LoadFile ( argv [ 1 ] ) ;
clock_t loadTime = clock ( ) ;
int errorID = doc - > ErrorID ( ) ;
delete doc ; doc = 0 ;
clock_t deleteTime = clock ( ) ;
printf ( " Test file '%s' loaded. ErrorID=%d \n " , argv [ 1 ] , errorID ) ;
if ( ! errorID ) {
2013-05-12 03:23:13 +00:00
printf ( " Load time=%u \n " , ( unsigned ) ( loadTime - startTime ) ) ;
printf ( " Delete time=%u \n " , ( unsigned ) ( deleteTime - loadTime ) ) ;
printf ( " Total time=%u \n " , ( unsigned ) ( deleteTime - startTime ) ) ;
2013-01-26 00:19:05 +00:00
}
exit ( 0 ) ;
}
2012-05-07 07:58:11 +00:00
FILE * fp = fopen ( " resources/dream.xml " , " r " ) ;
2012-03-24 19:49:03 +00:00
if ( ! fp ) {
printf ( " Error opening test file 'dream.xml'. \n "
" Is your working directory the same as where \n "
" the xmltest.cpp and dream.xml file are? \n \n "
# if defined( _MSC_VER )
" In windows Visual Studio you may need to set \n "
" Properties->Debugging->Working Directory to '..' \n "
# endif
) ;
exit ( 1 ) ;
}
fclose ( fp ) ;
2012-04-04 19:39:05 +00:00
XMLTest ( " Example-1 " , 0 , example_1 ( ) ) ;
XMLTest ( " Example-2 " , 0 , example_2 ( ) ) ;
XMLTest ( " Example-3 " , 0 , example_3 ( ) ) ;
2012-07-16 00:27:22 +00:00
XMLTest ( " Example-4 " , true , example_4 ( ) ) ;
2012-03-20 18:55:29 +00:00
2012-09-16 18:32:34 +00:00
/* ------ Example 2: Lookup information. ---- */
2012-03-20 18:55:29 +00:00
2012-01-19 01:43:40 +00:00
{
2012-02-07 02:18:11 +00:00
static const char * test [ ] = { " <element /> " ,
2012-07-25 18:10:39 +00:00
" <element></element> " ,
2012-02-07 02:18:11 +00:00
" <element><subelement/></element> " ,
2012-07-25 18:10:39 +00:00
" <element><subelement></subelement></element> " ,
" <element><subelement><subsub/></subelement></element> " ,
" <!--comment beside elements--><element><subelement></subelement></element> " ,
" <!--comment beside elements, this time with spaces--> \n <element> <subelement> \n </subelement> </element> " ,
" <element attrib1='foo' attrib2= \" bar \" ></element> " ,
" <element attrib1='foo' attrib2= \" bar \" ><subelement attrib3='yeehaa' /></element> " ,
2012-02-07 02:18:11 +00:00
" <element>Text inside element.</element> " ,
" <element><b></b></element> " ,
" <element>Text inside and <b>bolded</b> in the element.</element> " ,
" <outer><element>Text inside and <b>bolded</b> in the element.</element></outer> " ,
2012-01-26 01:44:30 +00:00
" <element>This & That.</element> " ,
2012-01-27 02:17:26 +00:00
" <element attrib='This<That' /> " ,
2012-01-19 01:55:48 +00:00
0
} ;
2012-01-22 02:45:16 +00:00
for ( int i = 0 ; test [ i ] ; + + i ) {
2012-01-19 01:55:48 +00:00
XMLDocument doc ;
2012-01-22 02:45:16 +00:00
doc . Parse ( test [ i ] ) ;
2012-01-25 02:03:07 +00:00
doc . Print ( ) ;
2012-01-23 19:42:06 +00:00
printf ( " ---------------------------------------------- \n " ) ;
2012-01-19 01:55:48 +00:00
}
2011-12-31 22:58:18 +00:00
}
2012-02-24 06:27:28 +00:00
# if 1
2012-02-23 00:00:12 +00:00
{
static const char * test = " <!--hello world \n "
2012-07-25 18:10:39 +00:00
" line 2 \r "
" line 3 \r \n "
" line 4 \n \r "
" line 5 \r --> " ;
2012-02-23 00:00:12 +00:00
XMLDocument doc ;
doc . Parse ( test ) ;
doc . Print ( ) ;
}
2012-01-31 16:24:24 +00:00
{
static const char * test = " <element>Text before.</element> " ;
XMLDocument doc ;
doc . Parse ( test ) ;
XMLElement * root = doc . FirstChildElement ( ) ;
XMLElement * newElement = doc . NewElement ( " Subelement " ) ;
root - > InsertEndChild ( newElement ) ;
doc . Print ( ) ;
}
2012-02-06 16:41:24 +00:00
{
XMLDocument * doc = new XMLDocument ( ) ;
static const char * test = " <element><sub/></element> " ;
doc - > Parse ( test ) ;
delete doc ;
}
2012-02-14 02:11:20 +00:00
{
2012-02-15 02:18:16 +00:00
// Test: Programmatic DOM
2012-02-14 02:16:52 +00:00
// Build:
// <element>
// <!--comment-->
// <sub attrib="1" />
// <sub attrib="2" />
2012-02-17 16:31:16 +00:00
// <sub attrib="3" >& Text!</sub>
2012-02-14 02:16:52 +00:00
// <element>
2012-02-14 02:11:20 +00:00
XMLDocument * doc = new XMLDocument ( ) ;
2012-02-15 02:18:16 +00:00
XMLNode * element = doc - > InsertEndChild ( doc - > NewElement ( " element " ) ) ;
XMLElement * sub [ 3 ] = { doc - > NewElement ( " sub " ) , doc - > NewElement ( " sub " ) , doc - > NewElement ( " sub " ) } ;
for ( int i = 0 ; i < 3 ; + + i ) {
sub [ i ] - > SetAttribute ( " attrib " , i ) ;
}
element - > InsertEndChild ( sub [ 2 ] ) ;
XMLNode * comment = element - > InsertFirstChild ( doc - > NewComment ( " comment " ) ) ;
element - > InsertAfterChild ( comment , sub [ 0 ] ) ;
element - > InsertAfterChild ( sub [ 0 ] , sub [ 1 ] ) ;
2012-02-17 16:31:16 +00:00
sub [ 2 ] - > InsertFirstChild ( doc - > NewText ( " & Text! " ) ) ;
2012-02-14 02:11:20 +00:00
doc - > Print ( ) ;
2012-02-17 16:31:16 +00:00
XMLTest ( " Programmatic DOM " , " comment " , doc - > FirstChildElement ( " element " ) - > FirstChild ( ) - > Value ( ) ) ;
XMLTest ( " Programmatic DOM " , " 0 " , doc - > FirstChildElement ( " element " ) - > FirstChildElement ( ) - > Attribute ( " attrib " ) ) ;
XMLTest ( " Programmatic DOM " , 2 , doc - > FirstChildElement ( ) - > LastChildElement ( " sub " ) - > IntAttribute ( " attrib " ) ) ;
2012-09-16 18:32:34 +00:00
XMLTest ( " Programmatic DOM " , " & Text! " ,
2012-02-17 16:31:16 +00:00
doc - > FirstChildElement ( ) - > LastChildElement ( " sub " ) - > FirstChild ( ) - > ToText ( ) - > Value ( ) ) ;
2012-02-18 01:48:16 +00:00
// And now deletion:
element - > DeleteChild ( sub [ 2 ] ) ;
doc - > DeleteNode ( comment ) ;
element - > FirstChildElement ( ) - > SetAttribute ( " attrib " , true ) ;
element - > LastChildElement ( ) - > DeleteAttribute ( " attrib " ) ;
XMLTest ( " Programmatic DOM " , true , doc - > FirstChildElement ( ) - > FirstChildElement ( ) - > BoolAttribute ( " attrib " ) ) ;
int value = 10 ;
int result = doc - > FirstChildElement ( ) - > LastChildElement ( ) - > QueryIntAttribute ( " attrib " , & value ) ;
2012-07-16 00:27:22 +00:00
XMLTest ( " Programmatic DOM " , result , ( int ) XML_NO_ATTRIBUTE ) ;
2012-02-18 01:48:16 +00:00
XMLTest ( " Programmatic DOM " , value , 10 ) ;
doc - > Print ( ) ;
2012-06-05 00:01:38 +00:00
{
XMLPrinter streamer ;
doc - > Print ( & streamer ) ;
printf ( " %s " , streamer . CStr ( ) ) ;
}
{
XMLPrinter streamer ( 0 , true ) ;
doc - > Print ( & streamer ) ;
XMLTest ( " Compact mode " , " <element><sub attrib= \" 1 \" /><sub/></element> " , streamer . CStr ( ) , false ) ;
}
2012-09-09 04:21:00 +00:00
doc - > SaveFile ( " ./resources/out/pretty.xml " ) ;
doc - > SaveFile ( " ./resources/out/compact.xml " , true ) ;
2012-02-14 02:11:20 +00:00
delete doc ;
}
2012-02-21 04:14:33 +00:00
{
// Test: Dream
// XML1 : 1,187,569 bytes in 31,209 allocations
// XML2 : 469,073 bytes in 323 allocations
//int newStart = gNew;
XMLDocument doc ;
2012-05-07 07:58:11 +00:00
doc . LoadFile ( " resources/dream.xml " ) ;
2012-02-21 04:14:33 +00:00
2012-07-23 20:24:07 +00:00
doc . SaveFile ( " resources/out/dreamout.xml " ) ;
2012-02-21 04:14:33 +00:00
doc . PrintError ( ) ;
XMLTest ( " Dream " , " xml version= \" 1.0 \" " ,
2012-07-25 18:10:39 +00:00
doc . FirstChild ( ) - > ToDeclaration ( ) - > Value ( ) ) ;
2012-02-21 04:14:33 +00:00
XMLTest ( " Dream " , true , doc . FirstChild ( ) - > NextSibling ( ) - > ToUnknown ( ) ? true : false ) ;
XMLTest ( " Dream " , " DOCTYPE PLAY SYSTEM \" play.dtd \" " ,
doc . FirstChild ( ) - > NextSibling ( ) - > ToUnknown ( ) - > Value ( ) ) ;
XMLTest ( " Dream " , " And Robin shall restore amends. " ,
2012-07-25 18:10:39 +00:00
doc . LastChild ( ) - > LastChild ( ) - > LastChild ( ) - > LastChild ( ) - > LastChildElement ( ) - > GetText ( ) ) ;
2012-02-21 04:14:33 +00:00
XMLTest ( " Dream " , " And Robin shall restore amends. " ,
2012-07-25 18:10:39 +00:00
doc . LastChild ( ) - > LastChild ( ) - > LastChild ( ) - > LastChild ( ) - > LastChildElement ( ) - > GetText ( ) ) ;
2012-02-21 04:14:33 +00:00
XMLDocument doc2 ;
2012-07-23 20:24:07 +00:00
doc2 . LoadFile ( " resources/out/dreamout.xml " ) ;
2012-02-21 04:14:33 +00:00
XMLTest ( " Dream-out " , " xml version= \" 1.0 \" " ,
2012-07-25 18:10:39 +00:00
doc2 . FirstChild ( ) - > ToDeclaration ( ) - > Value ( ) ) ;
2012-02-21 04:14:33 +00:00
XMLTest ( " Dream-out " , true , doc2 . FirstChild ( ) - > NextSibling ( ) - > ToUnknown ( ) ? true : false ) ;
XMLTest ( " Dream-out " , " DOCTYPE PLAY SYSTEM \" play.dtd \" " ,
doc2 . FirstChild ( ) - > NextSibling ( ) - > ToUnknown ( ) - > Value ( ) ) ;
XMLTest ( " Dream-out " , " And Robin shall restore amends. " ,
2012-07-25 18:10:39 +00:00
doc2 . LastChild ( ) - > LastChild ( ) - > LastChild ( ) - > LastChild ( ) - > LastChildElement ( ) - > GetText ( ) ) ;
2012-02-21 04:14:33 +00:00
//gNewTotal = gNew - newStart;
}
2012-03-02 20:59:39 +00:00
2012-02-21 17:08:12 +00:00
{
const char * error = " <?xml version= \" 1.0 \" standalone= \" no \" ?> \n "
" <passages count= \" 006 \" formatversion= \" 20020620 \" > \n "
" <wrong error> \n "
" </passages> " ;
XMLDocument doc ;
doc . Parse ( error ) ;
2012-11-09 20:37:46 +00:00
XMLTest ( " Bad XML " , doc . ErrorID ( ) , XML_ERROR_PARSING_ATTRIBUTE ) ;
2012-02-21 17:08:12 +00:00
}
{
const char * str = " <doc attr0='1' attr1='2.0' attr2='foo' /> " ;
XMLDocument doc ;
doc . Parse ( str ) ;
XMLElement * ele = doc . FirstChildElement ( ) ;
int iVal , result ;
double dVal ;
result = ele - > QueryDoubleAttribute ( " attr0 " , & dVal ) ;
2012-07-16 00:27:22 +00:00
XMLTest ( " Query attribute: int as double " , result , ( int ) XML_NO_ERROR ) ;
2012-02-21 17:08:12 +00:00
XMLTest ( " Query attribute: int as double " , ( int ) dVal , 1 ) ;
result = ele - > QueryDoubleAttribute ( " attr1 " , & dVal ) ;
2013-05-11 08:22:12 +00:00
XMLTest ( " Query attribute: double as double " , result , ( int ) XML_NO_ERROR ) ;
2012-02-21 17:08:12 +00:00
XMLTest ( " Query attribute: double as double " , ( int ) dVal , 2 ) ;
result = ele - > QueryIntAttribute ( " attr1 " , & iVal ) ;
2012-07-16 00:27:22 +00:00
XMLTest ( " Query attribute: double as int " , result , ( int ) XML_NO_ERROR ) ;
2012-02-21 17:08:12 +00:00
XMLTest ( " Query attribute: double as int " , iVal , 2 ) ;
result = ele - > QueryIntAttribute ( " attr2 " , & iVal ) ;
2012-07-16 00:27:22 +00:00
XMLTest ( " Query attribute: not a number " , result , ( int ) XML_WRONG_ATTRIBUTE_TYPE ) ;
2012-02-21 17:08:12 +00:00
result = ele - > QueryIntAttribute ( " bar " , & iVal ) ;
2012-07-16 00:27:22 +00:00
XMLTest ( " Query attribute: does not exist " , result , ( int ) XML_NO_ATTRIBUTE ) ;
2012-02-21 17:08:12 +00:00
}
{
const char * str = " <doc/> " ;
XMLDocument doc ;
doc . Parse ( str ) ;
XMLElement * ele = doc . FirstChildElement ( ) ;
2013-02-02 03:26:30 +00:00
int iVal , iVal2 ;
double dVal , dVal2 ;
2012-02-21 17:08:12 +00:00
ele - > SetAttribute ( " str " , " strValue " ) ;
ele - > SetAttribute ( " int " , 1 ) ;
ele - > SetAttribute ( " double " , - 1.0 ) ;
const char * cStr = ele - > Attribute ( " str " ) ;
ele - > QueryIntAttribute ( " int " , & iVal ) ;
ele - > QueryDoubleAttribute ( " double " , & dVal ) ;
2013-02-02 03:26:30 +00:00
ele - > QueryAttribute ( " int " , & iVal2 ) ;
ele - > QueryAttribute ( " double " , & dVal2 ) ;
2012-03-24 20:04:04 +00:00
XMLTest ( " Attribute match test " , ele - > Attribute ( " str " , " strValue " ) , " strValue " ) ;
2012-02-21 17:08:12 +00:00
XMLTest ( " Attribute round trip. c-string. " , " strValue " , cStr ) ;
XMLTest ( " Attribute round trip. int. " , 1 , iVal ) ;
XMLTest ( " Attribute round trip. double. " , - 1 , ( int ) dVal ) ;
2013-02-02 03:26:30 +00:00
XMLTest ( " Alternate query " , true , iVal = = iVal2 ) ;
XMLTest ( " Alternate query " , true , dVal = = dVal2 ) ;
2012-02-21 17:08:12 +00:00
}
{
XMLDocument doc ;
2012-05-07 07:58:11 +00:00
doc . LoadFile ( " resources/utf8test.xml " ) ;
2012-02-21 17:08:12 +00:00
// Get the attribute "value" from the "Russian" element and check it.
XMLElement * element = doc . FirstChildElement ( " document " ) - > FirstChildElement ( " Russian " ) ;
2012-09-16 18:32:34 +00:00
const unsigned char correctValue [ ] = { 0xd1U , 0x86U , 0xd0U , 0xb5U , 0xd0U , 0xbdU , 0xd0U , 0xbdU ,
2012-02-21 17:08:12 +00:00
0xd0U , 0xbeU , 0xd1U , 0x81U , 0xd1U , 0x82U , 0xd1U , 0x8cU , 0 } ;
XMLTest ( " UTF-8: Russian value. " , ( const char * ) correctValue , element - > Attribute ( " value " ) ) ;
const unsigned char russianElementName [ ] = { 0xd0U , 0xa0U , 0xd1U , 0x83U ,
0xd1U , 0x81U , 0xd1U , 0x81U ,
0xd0U , 0xbaU , 0xd0U , 0xb8U ,
0xd0U , 0xb9U , 0 } ;
const char russianText [ ] = " < \xD0 \xB8 \xD0 \xBC \xD0 \xB5 \xD0 \xB5 \xD1 \x82 > " ;
XMLText * text = doc . FirstChildElement ( " document " ) - > FirstChildElement ( ( const char * ) russianElementName ) - > FirstChild ( ) - > ToText ( ) ;
XMLTest ( " UTF-8: Browsing russian element name. " ,
russianText ,
text - > Value ( ) ) ;
// Now try for a round trip.
2012-07-23 20:24:07 +00:00
doc . SaveFile ( " resources/out/utf8testout.xml " ) ;
2012-02-21 17:08:12 +00:00
// Check the round trip.
int okay = 0 ;
2012-07-26 18:42:18 +00:00
FILE * saved = fopen ( " resources/out/utf8testout.xml " , " r " ) ;
2012-05-07 07:58:11 +00:00
FILE * verify = fopen ( " resources/utf8testverify.xml " , " r " ) ;
2012-02-21 17:08:12 +00:00
if ( saved & & verify )
{
okay = 1 ;
2012-07-16 10:08:47 +00:00
char verifyBuf [ 256 ] ;
2012-02-21 17:08:12 +00:00
while ( fgets ( verifyBuf , 256 , verify ) )
{
2012-07-16 10:08:47 +00:00
char savedBuf [ 256 ] ;
2012-02-21 17:08:12 +00:00
fgets ( savedBuf , 256 , saved ) ;
NullLineEndings ( verifyBuf ) ;
NullLineEndings ( savedBuf ) ;
if ( strcmp ( verifyBuf , savedBuf ) )
{
printf ( " verify:%s< \n " , verifyBuf ) ;
printf ( " saved :%s< \n " , savedBuf ) ;
okay = 0 ;
break ;
}
}
}
if ( saved )
fclose ( saved ) ;
if ( verify )
fclose ( verify ) ;
XMLTest ( " UTF-8: Verified multi-language round trip. " , 1 , okay ) ;
}
2012-02-24 06:27:28 +00:00
// --------GetText()-----------
{
const char * str = " <foo>This is text</foo> " ;
XMLDocument doc ;
doc . Parse ( str ) ;
const XMLElement * element = doc . RootElement ( ) ;
XMLTest ( " GetText() normal use. " , " This is text " , element - > GetText ( ) ) ;
str = " <foo><b>This is text</b></foo> " ;
doc . Parse ( str ) ;
element = doc . RootElement ( ) ;
XMLTest ( " GetText() contained element. " , element - > GetText ( ) = = 0 , true ) ;
}
2014-01-21 00:57:38 +00:00
// --------SetText()-----------
{
const char * str = " <foo></foo> " ;
XMLDocument doc ;
doc . Parse ( str ) ;
XMLElement * element = doc . RootElement ( ) ;
element - > SetText ( " He kept turning his head to left and right, but I could not see anything through the darkness. " ) ;
XMLTest ( " SetText() normal use (open/close). " , " He kept turning his head to left and right, but I could not see anything through the darkness. " , element - > GetText ( ) ) ;
element - > SetText ( " Suddenly, away on our left I saw a faint flickering blue flame. " ) ;
XMLTest ( " SetText() replace. " , " Suddenly, away on our left I saw a faint flickering blue flame. " , element - > GetText ( ) ) ;
str = " <foo/> " ;
doc . Parse ( str ) ;
element = doc . RootElement ( ) ;
element - > SetText ( " The driver saw it at the same moment. " ) ;
XMLTest ( " SetText() normal use. (self-closing) " , " The driver saw it at the same moment. " , element - > GetText ( ) ) ;
element - > SetText ( " <b>He at once checked the horses, and, jumping to the ground, disappeared into the darkness.</b> " ) ;
XMLTest ( " SetText() replace with tag-like text. " , " <b>He at once checked the horses, and, jumping to the ground, disappeared into the darkness.</b> " , element - > GetText ( ) ) ;
str = " <foo><bar>Text in nested element</bar></foo> " ;
doc . Parse ( str ) ;
element = doc . RootElement ( ) ;
element - > SetText ( " I did not know what to do, the less as the howling of the wolves grew closer. " ) ;
XMLTest ( " SetText() prefix to nested non-text children. " , " I did not know what to do, the less as the howling of the wolves grew closer. " , element - > GetText ( ) ) ;
}
2014-01-21 01:36:47 +00:00
// --------SetBoolFirstChild()-----------
{
const char * str = " <foo></foo> " ;
XMLDocument doc ;
doc . Parse ( str ) ;
XMLElement * element = doc . RootElement ( ) ;
element - > SetBoolFirstChild ( true ) ;
XMLTest ( " SetBoolFirstChild() normal use (open/close). " , " true " , element - > FirstChild ( ) - > ToElement ( ) - > Value ( ) ) ;
element - > SetBoolFirstChild ( false ) ;
XMLTest ( " SetBoolFirstChild() replace. " , " false " , element - > FirstChild ( ) - > ToElement ( ) - > Value ( ) ) ;
str = " <foo/> " ;
doc . Parse ( str ) ;
element = doc . RootElement ( ) ;
element - > SetBoolFirstChild ( false ) ;
XMLTest ( " SetBoolFirstChild() normal use (self-closing). " , " false " , element - > FirstChild ( ) - > ToElement ( ) - > Value ( ) ) ;
}
// --------BoolFirstChild()-----------
{
const char * str = " <foo><false /></foo> " ;
XMLDocument doc ;
doc . Parse ( str ) ;
XMLElement * element = doc . RootElement ( ) ;
XMLTest ( " BoolFirstChild() normal use (open/close). " , false , element - > BoolFirstChild ( ) ) ;
str = " <foo><true /></foo> " ;
doc . Parse ( str ) ;
element = doc . RootElement ( ) ;
XMLTest ( " BoolFirstChild() normal use (open/close). " , true , element - > BoolFirstChild ( ) ) ;
str = " <foo></foo> " ;
doc . Parse ( str ) ;
element = doc . RootElement ( ) ;
element - > SetBoolFirstChild ( true ) ;
XMLTest ( " BoolFirstChild() after SetBoolFirstChild(). " , true , element - > BoolFirstChild ( ) ) ;
element - > SetBoolFirstChild ( false ) ;
XMLTest ( " BoolFirstChild() after SetBoolFirstChild() replace. " , false , element - > BoolFirstChild ( ) ) ;
str = " <foo/> " ;
doc . Parse ( str ) ;
element = doc . RootElement ( ) ;
element - > SetBoolFirstChild ( false ) ;
XMLTest ( " BoolFirstChild() (self-closing) after SetBoolFirstChild() replace. " , false , element - > BoolFirstChild ( ) ) ;
}
2012-02-24 06:27:28 +00:00
// ---------- CDATA ---------------
{
const char * str = " <xmlElement> "
" <![CDATA[ "
" I am > the rules! \n "
" ...since I make symbolic puns "
" ]]> "
" </xmlElement> " ;
XMLDocument doc ;
doc . Parse ( str ) ;
doc . Print ( ) ;
2012-09-16 18:32:34 +00:00
XMLTest ( " CDATA parse. " , doc . FirstChildElement ( ) - > FirstChild ( ) - > Value ( ) ,
2012-02-24 06:27:28 +00:00
" I am > the rules! \n ...since I make symbolic puns " ,
2012-02-23 00:00:12 +00:00
false ) ;
}
2012-02-21 17:08:12 +00:00
2012-02-24 06:27:28 +00:00
// ----------- CDATA -------------
{
const char * str = " <xmlElement> "
" <![CDATA[ "
" <b>I am > the rules!</b> \n "
" ...since I make symbolic puns "
" ]]> "
" </xmlElement> " ;
XMLDocument doc ;
doc . Parse ( str ) ;
doc . Print ( ) ;
2012-09-16 18:32:34 +00:00
XMLTest ( " CDATA parse. [ tixml1:1480107 ] " , doc . FirstChildElement ( ) - > FirstChild ( ) - > Value ( ) ,
2012-02-24 06:27:28 +00:00
" <b>I am > the rules!</b> \n ...since I make symbolic puns " ,
false ) ;
}
2012-02-23 00:00:12 +00:00
2012-02-24 06:27:28 +00:00
// InsertAfterChild causes crash.
2012-02-23 00:00:12 +00:00
{
2012-02-24 06:27:28 +00:00
// InsertBeforeChild and InsertAfterChild causes crash.
XMLDocument doc ;
XMLElement * parent = doc . NewElement ( " Parent " ) ;
doc . InsertFirstChild ( parent ) ;
XMLElement * childText0 = doc . NewElement ( " childText0 " ) ;
XMLElement * childText1 = doc . NewElement ( " childText1 " ) ;
XMLNode * childNode0 = parent - > InsertEndChild ( childText0 ) ;
XMLNode * childNode1 = parent - > InsertAfterChild ( childNode0 , childText1 ) ;
XMLTest ( " Test InsertAfterChild on empty node. " , ( childNode1 = = parent - > LastChild ( ) ) , true ) ;
}
{
// Entities not being written correctly.
// From Lynn Allen
const char * passages =
" <?xml version= \" 1.0 \" standalone= \" no \" ?> "
" <passages count= \" 006 \" formatversion= \" 20020620 \" > "
" <psg context= \" Line 5 has "quotation marks" and 'apostrophe marks'. "
" It also has <, >, and &, as well as a fake copyright ©. \" > </psg> "
" </passages> " ;
XMLDocument doc ;
doc . Parse ( passages ) ;
XMLElement * psg = doc . RootElement ( ) - > FirstChildElement ( ) ;
const char * context = psg - > Attribute ( " context " ) ;
const char * expected = " Line 5 has \" quotation marks \" and 'apostrophe marks'. It also has <, >, and &, as well as a fake copyright \xC2 \xA9 . " ;
XMLTest ( " Entity transformation: read. " , expected , context , true ) ;
2012-07-23 20:24:07 +00:00
FILE * textfile = fopen ( " resources/out/textfile.txt " , " w " ) ;
2012-02-24 06:27:28 +00:00
if ( textfile )
{
2012-02-25 01:37:53 +00:00
XMLPrinter streamer ( textfile ) ;
2012-02-24 06:27:28 +00:00
psg - > Accept ( & streamer ) ;
fclose ( textfile ) ;
}
2012-09-23 14:31:22 +00:00
textfile = fopen ( " resources/out/textfile.txt " , " r " ) ;
2012-02-24 06:27:28 +00:00
TIXMLASSERT ( textfile ) ;
if ( textfile )
{
char buf [ 1024 ] ;
fgets ( buf , 1024 , textfile ) ;
XMLTest ( " Entity transformation: write. " ,
" <psg context= \" Line 5 has "quotation marks" and 'apostrophe marks'. "
" It also has <, >, and &, as well as a fake copyright \xC2 \xA9 . \" /> \n " ,
buf , false ) ;
2012-07-16 10:08:47 +00:00
fclose ( textfile ) ;
2012-02-24 06:27:28 +00:00
}
}
2012-03-02 20:59:39 +00:00
{
// Suppress entities.
const char * passages =
" <?xml version= \" 1.0 \" standalone= \" no \" ?> "
" <passages count= \" 006 \" formatversion= \" 20020620 \" > "
" <psg context= \" Line 5 has "quotation marks" and 'apostrophe marks'. \" >Crazy &ttk;</psg> "
" </passages> " ;
2012-09-16 18:32:34 +00:00
2012-03-02 20:59:39 +00:00
XMLDocument doc ( false ) ;
doc . Parse ( passages ) ;
2012-09-16 18:32:34 +00:00
XMLTest ( " No entity parsing. " , doc . FirstChildElement ( ) - > FirstChildElement ( ) - > Attribute ( " context " ) ,
2012-03-02 20:59:39 +00:00
" Line 5 has "quotation marks" and 'apostrophe marks'. " ) ;
XMLTest ( " No entity parsing. " , doc . FirstChildElement ( ) - > FirstChildElement ( ) - > FirstChild ( ) - > Value ( ) ,
" Crazy &ttk; " ) ;
doc . Print ( ) ;
}
2012-02-24 06:27:28 +00:00
{
2012-07-25 18:10:39 +00:00
const char * test = " <?xml version='1.0'?><a.elem xmi.version='2.0'/> " ;
2012-02-24 06:27:28 +00:00
XMLDocument doc ;
2012-07-25 18:10:39 +00:00
doc . Parse ( test ) ;
XMLTest ( " dot in names " , doc . Error ( ) , false ) ;
XMLTest ( " dot in names " , doc . FirstChildElement ( ) - > Name ( ) , " a.elem " ) ;
XMLTest ( " dot in names " , doc . FirstChildElement ( ) - > Attribute ( " xmi.version " ) , " 2.0 " ) ;
2012-02-24 06:27:28 +00:00
}
{
2012-07-25 18:10:39 +00:00
const char * test = " <element><Name>1.1 Start easy ignore fin thickness
</Name></element> " ;
2012-02-24 06:27:28 +00:00
2012-07-25 18:10:39 +00:00
XMLDocument doc ;
2012-02-24 06:27:28 +00:00
doc . Parse ( test ) ;
XMLText * text = doc . FirstChildElement ( ) - > FirstChildElement ( ) - > FirstChild ( ) - > ToText ( ) ;
XMLTest ( " Entity with one digit. " ,
text - > Value ( ) , " 1.1 Start easy ignore fin thickness \n " ,
false ) ;
2012-07-25 18:10:39 +00:00
}
2012-02-24 06:27:28 +00:00
{
// DOCTYPE not preserved (950171)
2012-09-16 18:32:34 +00:00
//
2012-02-24 06:27:28 +00:00
const char * doctype =
" <?xml version= \" 1.0 \" ?> "
" <!DOCTYPE PLAY SYSTEM 'play.dtd'> "
" <!ELEMENT title (#PCDATA)> "
" <!ELEMENT books (title,authors)> "
" <element /> " ;
XMLDocument doc ;
doc . Parse ( doctype ) ;
2012-07-23 20:24:07 +00:00
doc . SaveFile ( " resources/out/test7.xml " ) ;
2012-02-24 06:27:28 +00:00
doc . DeleteChild ( doc . RootElement ( ) ) ;
2012-07-23 20:24:07 +00:00
doc . LoadFile ( " resources/out/test7.xml " ) ;
2012-02-24 06:27:28 +00:00
doc . Print ( ) ;
2012-09-16 18:32:34 +00:00
2012-02-24 06:27:28 +00:00
const XMLUnknown * decl = doc . FirstChild ( ) - > NextSibling ( ) - > ToUnknown ( ) ;
XMLTest ( " Correct value of unknown. " , " DOCTYPE PLAY SYSTEM 'play.dtd' " , decl - > Value ( ) ) ;
2012-02-23 00:00:12 +00:00
2012-02-24 06:27:28 +00:00
}
{
// Comments do not stream out correctly.
2012-09-16 18:32:34 +00:00
const char * doctype =
2012-02-24 06:27:28 +00:00
" <!-- Somewhat<evil> --> " ;
XMLDocument doc ;
doc . Parse ( doctype ) ;
XMLComment * comment = doc . FirstChild ( ) - > ToComment ( ) ;
XMLTest ( " Comment formatting. " , " Somewhat<evil> " , comment - > Value ( ) ) ;
}
{
// Double attributes
const char * doctype = " <element attr='red' attr='blue' /> " ;
XMLDocument doc ;
doc . Parse ( doctype ) ;
2012-09-16 18:32:34 +00:00
2012-11-09 20:37:46 +00:00
XMLTest ( " Parsing repeated attributes. " , XML_ERROR_PARSING_ATTRIBUTE , doc . ErrorID ( ) ) ; // is an error to tinyxml (didn't use to be, but caused issues)
2012-02-28 04:50:52 +00:00
doc . PrintError ( ) ;
2012-02-24 06:27:28 +00:00
}
{
// Embedded null in stream.
const char * doctype = " <element att \0 r='red' attr='blue' /> " ;
XMLDocument doc ;
doc . Parse ( doctype ) ;
XMLTest ( " Embedded null throws error. " , true , doc . Error ( ) ) ;
}
{
2012-03-20 18:26:57 +00:00
// Empty documents should return TIXML_XML_ERROR_PARSING_EMPTY, bug 1070717
2012-02-24 06:27:28 +00:00
const char * str = " " ;
XMLDocument doc ;
doc . Parse ( str ) ;
2012-11-09 20:37:46 +00:00
XMLTest ( " Empty document error " , XML_ERROR_EMPTY_DOCUMENT , doc . ErrorID ( ) ) ;
2012-02-24 06:27:28 +00:00
}
{
// Low entities
XMLDocument doc ;
doc . Parse ( " <test></test> " ) ;
const char result [ ] = { 0x0e , 0 } ;
XMLTest ( " Low entities. " , doc . FirstChildElement ( ) - > GetText ( ) , result ) ;
doc . Print ( ) ;
}
{
// Attribute values with trailing quotes not handled correctly
XMLDocument doc ;
doc . Parse ( " <foo attribute=bar \" /> " ) ;
XMLTest ( " Throw error with bad end quotes. " , doc . Error ( ) , true ) ;
}
{
// [ 1663758 ] Failure to report error on bad XML
XMLDocument xml ;
xml . Parse ( " <x> " ) ;
XMLTest ( " Missing end tag at end of input " , xml . Error ( ) , true ) ;
xml . Parse ( " <x> " ) ;
XMLTest ( " Missing end tag with trailing whitespace " , xml . Error ( ) , true ) ;
xml . Parse ( " <x></y> " ) ;
2012-11-09 20:37:46 +00:00
XMLTest ( " Mismatched tags " , xml . ErrorID ( ) , XML_ERROR_MISMATCHED_ELEMENT ) ;
2012-09-16 18:32:34 +00:00
}
2012-02-24 06:27:28 +00:00
{
// [ 1475201 ] TinyXML parses entities in comments
XMLDocument xml ;
xml . Parse ( " <!-- declarations for <head> & <body> --> "
" <!-- far & away --> " ) ;
XMLNode * e0 = xml . FirstChild ( ) ;
XMLNode * e1 = e0 - > NextSibling ( ) ;
XMLComment * c0 = e0 - > ToComment ( ) ;
XMLComment * c1 = e1 - > ToComment ( ) ;
XMLTest ( " Comments ignore entities. " , " declarations for <head> & <body> " , c0 - > Value ( ) , true ) ;
XMLTest ( " Comments ignore entities. " , " far & away " , c1 - > Value ( ) , true ) ;
}
{
XMLDocument xml ;
xml . Parse ( " <Parent> "
" <child1 att=''/> "
" <!-- With this comment, child2 will not be parsed! --> "
" <child2 att=''/> "
" </Parent> " ) ;
xml . Print ( ) ;
int count = 0 ;
for ( XMLNode * ele = xml . FirstChildElement ( " Parent " ) - > FirstChild ( ) ;
ele ;
ele = ele - > NextSibling ( ) )
{
+ + count ;
}
XMLTest ( " Comments iterate correctly. " , 3 , count ) ;
}
{
// trying to repro ]1874301]. If it doesn't go into an infinite loop, all is well.
unsigned char buf [ ] = " <?xml version= \" 1.0 \" encoding= \" utf-8 \" ?><feed><![CDATA[Test XMLblablablalblbl " ;
buf [ 60 ] = 239 ;
buf [ 61 ] = 0 ;
XMLDocument doc ;
doc . Parse ( ( const char * ) buf ) ;
2012-09-16 18:32:34 +00:00
}
2012-02-24 06:27:28 +00:00
{
// bug 1827248 Error while parsing a little bit malformed file
// Actually not malformed - should work.
XMLDocument xml ;
xml . Parse ( " <attributelist> </attributelist > " ) ;
XMLTest ( " Handle end tag whitespace " , false , xml . Error ( ) ) ;
}
{
// This one must not result in an infinite loop
XMLDocument xml ;
xml . Parse ( " <infinite>loop " ) ;
XMLTest ( " Infinite loop test. " , true , true ) ;
}
# endif
2012-02-28 01:54:22 +00:00
{
const char * pub = " <?xml version='1.0'?> <element><sub/></element> <!--comment--> <!DOCTYPE> " ;
XMLDocument doc ;
doc . Parse ( pub ) ;
XMLDocument clone ;
for ( const XMLNode * node = doc . FirstChild ( ) ; node ; node = node - > NextSibling ( ) ) {
XMLNode * copy = node - > ShallowClone ( & clone ) ;
clone . InsertEndChild ( copy ) ;
}
clone . Print ( ) ;
int count = 0 ;
const XMLNode * a = clone . FirstChild ( ) ;
const XMLNode * b = doc . FirstChild ( ) ;
for ( ; a & & b ; a = a - > NextSibling ( ) , b = b - > NextSibling ( ) ) {
+ + count ;
XMLTest ( " Clone and Equal " , true , a - > ShallowEqual ( b ) ) ;
}
XMLTest ( " Clone and Equal " , 4 , count ) ;
}
2012-02-25 01:37:53 +00:00
2012-04-07 04:24:29 +00:00
{
// This shouldn't crash.
XMLDocument doc ;
if ( XML_NO_ERROR ! = doc . LoadFile ( " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa " ) )
{
doc . PrintError ( ) ;
}
XMLTest ( " Error in snprinf handling. " , true , doc . Error ( ) ) ;
}
2012-09-16 18:32:34 +00:00
2012-04-16 15:57:05 +00:00
{
// Attribute ordering.
static const char * xml = " <element attrib1= \" 1 \" attrib2= \" 2 \" attrib3= \" 3 \" /> " ;
XMLDocument doc ;
doc . Parse ( xml ) ;
XMLElement * ele = doc . FirstChildElement ( ) ;
2012-09-16 18:32:34 +00:00
2012-04-16 15:57:05 +00:00
const XMLAttribute * a = ele - > FirstAttribute ( ) ;
XMLTest ( " Attribute order " , " 1 " , a - > Value ( ) ) ;
a = a - > Next ( ) ;
XMLTest ( " Attribute order " , " 2 " , a - > Value ( ) ) ;
a = a - > Next ( ) ;
XMLTest ( " Attribute order " , " 3 " , a - > Value ( ) ) ;
XMLTest ( " Attribute order " , " attrib3 " , a - > Name ( ) ) ;
2012-09-16 18:32:34 +00:00
2012-04-16 15:57:05 +00:00
ele - > DeleteAttribute ( " attrib2 " ) ;
a = ele - > FirstAttribute ( ) ;
XMLTest ( " Attribute order " , " 1 " , a - > Value ( ) ) ;
a = a - > Next ( ) ;
XMLTest ( " Attribute order " , " 3 " , a - > Value ( ) ) ;
2012-09-16 18:32:34 +00:00
2012-04-16 15:57:05 +00:00
ele - > DeleteAttribute ( " attrib1 " ) ;
ele - > DeleteAttribute ( " attrib3 " ) ;
XMLTest ( " Attribute order (empty) " , false , ele - > FirstAttribute ( ) ? true : false ) ;
}
2012-04-07 04:24:29 +00:00
2012-07-02 04:22:53 +00:00
{
// Make sure an attribute with a space in it succeeds.
2012-07-02 17:10:19 +00:00
static const char * xml0 = " <element attribute1= \" Test Attribute \" /> " ;
static const char * xml1 = " <element attribute1 = \" Test Attribute \" /> " ;
static const char * xml2 = " <element attribute1 = \" Test Attribute \" /> " ;
XMLDocument doc0 ;
doc0 . Parse ( xml0 ) ;
XMLDocument doc1 ;
doc1 . Parse ( xml1 ) ;
XMLDocument doc2 ;
doc2 . Parse ( xml2 ) ;
XMLElement * ele = 0 ;
ele = doc0 . FirstChildElement ( ) ;
XMLTest ( " Attribute with space #1 " , " Test Attribute " , ele - > Attribute ( " attribute1 " ) ) ;
ele = doc1 . FirstChildElement ( ) ;
XMLTest ( " Attribute with space #2 " , " Test Attribute " , ele - > Attribute ( " attribute1 " ) ) ;
ele = doc2 . FirstChildElement ( ) ;
XMLTest ( " Attribute with space #3 " , " Test Attribute " , ele - > Attribute ( " attribute1 " ) ) ;
2012-07-02 04:22:53 +00:00
}
{
// Make sure we don't go into an infinite loop.
static const char * xml = " <doc><element attribute='attribute'/><element attribute='attribute'/></doc> " ;
XMLDocument doc ;
doc . Parse ( xml ) ;
XMLElement * ele0 = doc . FirstChildElement ( ) - > FirstChildElement ( ) ;
XMLElement * ele1 = ele0 - > NextSiblingElement ( ) ;
bool equal = ele0 - > ShallowEqual ( ele1 ) ;
XMLTest ( " Infinite loop in shallow equal. " , true , equal ) ;
}
2012-03-29 00:46:41 +00:00
// -------- Handles ------------
{
static const char * xml = " <element attrib='bar'><sub>Text</sub></element> " ;
XMLDocument doc ;
doc . Parse ( xml ) ;
XMLElement * ele = XMLHandle ( doc ) . FirstChildElement ( " element " ) . FirstChild ( ) . ToElement ( ) ;
XMLTest ( " Handle, success, mutable " , ele - > Value ( ) , " sub " ) ;
2012-04-05 05:00:07 +00:00
XMLHandle docH ( doc ) ;
ele = docH . FirstChildElement ( " none " ) . FirstChildElement ( " element " ) . ToElement ( ) ;
2012-04-12 15:41:37 +00:00
XMLTest ( " Handle, dne, mutable " , false , ele ! = 0 ) ;
2012-04-05 05:00:07 +00:00
}
2012-09-16 18:32:34 +00:00
2012-04-05 05:00:07 +00:00
{
static const char * xml = " <element attrib='bar'><sub>Text</sub></element> " ;
XMLDocument doc ;
doc . Parse ( xml ) ;
XMLConstHandle docH ( doc ) ;
2012-03-29 00:46:41 +00:00
2012-04-05 05:00:07 +00:00
const XMLElement * ele = docH . FirstChildElement ( " element " ) . FirstChild ( ) . ToElement ( ) ;
XMLTest ( " Handle, success, const " , ele - > Value ( ) , " sub " ) ;
ele = docH . FirstChildElement ( " none " ) . FirstChildElement ( " element " ) . ToElement ( ) ;
2012-04-12 15:41:37 +00:00
XMLTest ( " Handle, dne, const " , false , ele ! = 0 ) ;
2012-03-29 00:46:41 +00:00
}
2012-04-28 21:37:11 +00:00
{
// Default Declaration & BOM
XMLDocument doc ;
doc . InsertEndChild ( doc . NewDeclaration ( ) ) ;
doc . SetBOM ( true ) ;
2012-09-16 18:32:34 +00:00
2012-04-28 21:37:11 +00:00
XMLPrinter printer ;
doc . Print ( & printer ) ;
static const char * result = " \xef \xbb \xbf <?xml version= \" 1.0 \" encoding= \" UTF-8 \" ?> " ;
XMLTest ( " BOM and default declaration " , printer . CStr ( ) , result , false ) ;
2012-05-26 21:41:14 +00:00
XMLTest ( " CStrSize " , printer . CStrSize ( ) , 42 , false ) ;
2012-04-28 21:37:11 +00:00
}
2012-07-16 00:27:22 +00:00
{
const char * xml = " <ipxml ws='1'><info bla=' /></ipxml> " ;
XMLDocument doc ;
doc . Parse ( xml ) ;
XMLTest ( " Ill formed XML " , true , doc . Error ( ) ) ;
}
// QueryXYZText
{
const char * xml = " <point> <x>1.2</x> <y>1</y> <z>38</z> <valid>true</valid> </point> " ;
XMLDocument doc ;
doc . Parse ( xml ) ;
const XMLElement * pointElement = doc . RootElement ( ) ;
int intValue = 0 ;
unsigned unsignedValue = 0 ;
float floatValue = 0 ;
double doubleValue = 0 ;
bool boolValue = false ;
pointElement - > FirstChildElement ( " y " ) - > QueryIntText ( & intValue ) ;
pointElement - > FirstChildElement ( " y " ) - > QueryUnsignedText ( & unsignedValue ) ;
pointElement - > FirstChildElement ( " x " ) - > QueryFloatText ( & floatValue ) ;
pointElement - > FirstChildElement ( " x " ) - > QueryDoubleText ( & doubleValue ) ;
pointElement - > FirstChildElement ( " valid " ) - > QueryBoolText ( & boolValue ) ;
XMLTest ( " QueryIntText " , intValue , 1 , false ) ;
XMLTest ( " QueryUnsignedText " , unsignedValue , ( unsigned ) 1 , false ) ;
XMLTest ( " QueryFloatText " , floatValue , 1.2f , false ) ;
XMLTest ( " QueryDoubleText " , doubleValue , 1.2 , false ) ;
XMLTest ( " QueryBoolText " , boolValue , true , false ) ;
}
2012-04-05 05:00:07 +00:00
2012-09-09 04:40:53 +00:00
{
const char * xml = " <element><_sub/><:sub/><sub:sub/><sub-sub/></element> " ;
XMLDocument doc ;
doc . Parse ( xml ) ;
XMLTest ( " Non-alpha element lead letter parses. " , doc . Error ( ) , false ) ;
}
2013-01-26 18:15:44 +00:00
{
const char * xml = " <element _attr1= \" foo \" :attr2= \" bar \" ></element> " ;
XMLDocument doc ;
2013-01-26 21:08:10 +00:00
doc . Parse ( xml ) ;
2013-01-26 18:15:44 +00:00
XMLTest ( " Non-alpha attribute lead character parses. " , doc . Error ( ) , false ) ;
}
2013-01-26 21:08:10 +00:00
{
const char * xml = " <3lement></3lement> " ;
XMLDocument doc ;
doc . Parse ( xml ) ;
XMLTest ( " Element names with lead digit fail to parse. " , doc . Error ( ) , true ) ;
}
2012-09-09 04:44:12 +00:00
2012-09-18 00:58:25 +00:00
{
const char * xml = " <element/>WOA THIS ISN'T GOING TO PARSE " ;
XMLDocument doc ;
doc . Parse ( xml , 10 ) ;
XMLTest ( " Set length of incoming data " , doc . Error ( ) , false ) ;
}
2013-01-30 09:21:36 +00:00
{
XMLDocument doc ;
doc . LoadFile ( " resources/dream.xml " ) ;
doc . Clear ( ) ;
XMLTest ( " Document Clear()'s " , doc . NoChildren ( ) , true ) ;
}
2012-08-21 05:00:38 +00:00
// ----------- Whitespace ------------
{
const char * xml = " <element> "
" <a> This \n is ' text ' </a> "
" <b> This is ' text ' \n </b> "
" <c>This is ' \n \n text '</c> "
" </element> " ;
XMLDocument doc ( true , COLLAPSE_WHITESPACE ) ;
doc . Parse ( xml ) ;
const XMLElement * element = doc . FirstChildElement ( ) ;
for ( const XMLElement * parent = element - > FirstChildElement ( ) ;
parent ;
parent = parent - > NextSiblingElement ( ) )
{
XMLTest ( " Whitespace collapse " , " This is ' text ' " , parent - > GetText ( ) ) ;
}
}
2012-09-09 04:53:47 +00:00
2012-10-24 17:17:53 +00:00
#if 0
{
// Passes if assert doesn't fire.
XMLDocument xmlDoc ;
xmlDoc . NewDeclaration ( ) ;
xmlDoc . NewComment ( " Configuration file " ) ;
XMLElement * root = xmlDoc . NewElement ( " settings " ) ;
root - > SetAttribute ( " version " , 2 ) ;
}
# endif
2012-09-09 04:53:47 +00:00
{
const char * xml = " <element> </element> " ;
XMLDocument doc ( true , COLLAPSE_WHITESPACE ) ;
doc . Parse ( xml ) ;
XMLTest ( " Whitespace all space " , true , 0 = = doc . FirstChildElement ( ) - > FirstChild ( ) ) ;
}
2012-09-16 18:32:34 +00:00
2012-11-19 21:54:42 +00:00
{
// An assert should not fire.
const char * xml = " <element/> " ;
XMLDocument doc ;
doc . Parse ( xml ) ;
XMLElement * ele = doc . NewElement ( " unused " ) ; // This will get cleaned up with the 'doc' going out of scope.
XMLTest ( " Tracking unused elements " , true , ele ! = 0 , false ) ;
}
2012-12-13 23:39:11 +00:00
{
const char * xml = " <parent><child>abc</child></parent> " ;
XMLDocument doc ;
doc . Parse ( xml ) ;
XMLElement * ele = doc . FirstChildElement ( " parent " ) - > FirstChildElement ( " child " ) ;
XMLPrinter printer ;
ele - > Accept ( & printer ) ;
XMLTest ( " Printing of sub-element " , " <child>abc</child> \n " , printer . CStr ( ) , false ) ;
}
2013-04-20 08:12:33 +00:00
{
XMLDocument doc ;
XMLError error = doc . LoadFile ( " resources/empty.xml " ) ;
XMLTest ( " Loading an empty file " , XML_ERROR_EMPTY_DOCUMENT , error ) ;
}
2013-04-29 16:15:37 +00:00
{
// BOM preservation
static const char * xml_bom_preservation = " \xef \xbb \xbf <element/> \n " ;
{
XMLDocument doc ;
XMLTest ( " BOM preservation (parse) " , XML_NO_ERROR , doc . Parse ( xml_bom_preservation ) , false ) ;
XMLPrinter printer ;
doc . Print ( & printer ) ;
XMLTest ( " BOM preservation (compare) " , xml_bom_preservation , printer . CStr ( ) , false , true ) ;
doc . SaveFile ( " resources/bomtest.xml " ) ;
}
{
XMLDocument doc ;
doc . LoadFile ( " resources/bomtest.xml " ) ;
XMLTest ( " BOM preservation (load) " , true , doc . HasBOM ( ) , false ) ;
XMLPrinter printer ;
doc . Print ( & printer ) ;
XMLTest ( " BOM preservation (compare) " , xml_bom_preservation , printer . CStr ( ) , false , true ) ;
}
}
2013-04-20 08:12:33 +00:00
2013-10-23 05:47:29 +00:00
{
// Insertion with Removal
const char * xml = " <?xml version= \" 1.0 \" ?> "
" <root> "
" <one> "
" <subtree> "
" <elem>element 1</elem>text<!-- comment --> "
" </subtree> "
" </one> "
" <two/> "
" </root> " ;
const char * xmlInsideTwo = " <?xml version= \" 1.0 \" ?> "
" <root> "
" <one/> "
" <two> "
" <subtree> "
" <elem>element 1</elem>text<!-- comment --> "
" </subtree> "
" </two> "
" </root> " ;
const char * xmlAfterOne = " <?xml version= \" 1.0 \" ?> "
" <root> "
" <one/> "
" <subtree> "
" <elem>element 1</elem>text<!-- comment --> "
" </subtree> "
" <two/> "
" </root> " ;
const char * xmlAfterTwo = " <?xml version= \" 1.0 \" ?> "
" <root> "
" <one/> "
" <two/> "
" <subtree> "
" <elem>element 1</elem>text<!-- comment --> "
" </subtree> "
" </root> " ;
XMLDocument doc ;
2014-01-14 20:30:03 +00:00
doc . Parse ( xml ) ;
2013-10-23 05:47:29 +00:00
XMLElement * subtree = doc . RootElement ( ) - > FirstChildElement ( " one " ) - > FirstChildElement ( " subtree " ) ;
XMLElement * two = doc . RootElement ( ) - > FirstChildElement ( " two " ) ;
two - > InsertFirstChild ( subtree ) ;
2014-01-14 20:30:03 +00:00
XMLPrinter printer1 ( 0 , true ) ;
doc . Accept ( & printer1 ) ;
XMLTest ( " Move node from within <one> to <two> " , xmlInsideTwo , printer1 . CStr ( ) ) ;
2013-10-23 05:47:29 +00:00
2014-01-14 20:30:03 +00:00
doc . Parse ( xml ) ;
2013-10-23 05:47:29 +00:00
subtree = doc . RootElement ( ) - > FirstChildElement ( " one " ) - > FirstChildElement ( " subtree " ) ;
two = doc . RootElement ( ) - > FirstChildElement ( " two " ) ;
doc . RootElement ( ) - > InsertAfterChild ( two , subtree ) ;
2014-01-14 20:30:03 +00:00
XMLPrinter printer2 ( 0 , true ) ;
doc . Accept ( & printer2 ) ;
XMLTest ( " Move node from within <one> after <two> " , xmlAfterTwo , printer2 . CStr ( ) , false ) ;
2013-10-23 05:47:29 +00:00
2014-01-14 20:30:03 +00:00
doc . Parse ( xml ) ;
2013-10-23 05:47:29 +00:00
XMLNode * one = doc . RootElement ( ) - > FirstChildElement ( " one " ) ;
subtree = one - > FirstChildElement ( " subtree " ) ;
doc . RootElement ( ) - > InsertAfterChild ( one , subtree ) ;
2014-01-14 20:30:03 +00:00
XMLPrinter printer3 ( 0 , true ) ;
doc . Accept ( & printer3 ) ;
XMLTest ( " Move node from within <one> after <one> " , xmlAfterOne , printer3 . CStr ( ) , false ) ;
2013-10-23 05:47:29 +00:00
2014-01-14 20:30:03 +00:00
doc . Parse ( xml ) ;
2013-10-23 05:47:29 +00:00
subtree = doc . RootElement ( ) - > FirstChildElement ( " one " ) - > FirstChildElement ( " subtree " ) ;
two = doc . RootElement ( ) - > FirstChildElement ( " two " ) ;
doc . RootElement ( ) - > InsertEndChild ( subtree ) ;
2014-01-14 20:30:03 +00:00
XMLPrinter printer4 ( 0 , true ) ;
doc . Accept ( & printer4 ) ;
XMLTest ( " Move node from within <one> after <two> " , xmlAfterTwo , printer4 . CStr ( ) , false ) ;
}
{
const char * xml = " <svg width = \" 128 \" height = \" 128 \" > "
" <text> </text> "
" </svg> " ;
XMLDocument doc ;
doc . Parse ( xml ) ;
doc . Print ( ) ;
2013-10-23 05:47:29 +00:00
}
2014-01-14 20:30:03 +00:00
# if 1
// the question being explored is what kind of print to use:
// https://github.com/leethomason/tinyxml2/issues/63
{
//const char* xml = "<element attrA='123456789.123456789' attrB='1.001e9' attrC='1.0e-10' attrD='1001000000.000000' attrE='0.1234567890123456789'/>";
const char * xml = " <element/> " ;
XMLDocument doc ;
doc . Parse ( xml ) ;
doc . FirstChildElement ( ) - > SetAttribute ( " attrA-f64 " , 123456789.123456789 ) ;
doc . FirstChildElement ( ) - > SetAttribute ( " attrB-f64 " , 1.001e9 ) ;
doc . FirstChildElement ( ) - > SetAttribute ( " attrC-f64 " , 1.0e9 ) ;
doc . FirstChildElement ( ) - > SetAttribute ( " attrC-f64 " , 1.0e20 ) ;
doc . FirstChildElement ( ) - > SetAttribute ( " attrD-f64 " , 1.0e-10 ) ;
doc . FirstChildElement ( ) - > SetAttribute ( " attrD-f64 " , 0.123456789 ) ;
doc . FirstChildElement ( ) - > SetAttribute ( " attrA-f32 " , 123456789.123456789f ) ;
doc . FirstChildElement ( ) - > SetAttribute ( " attrB-f32 " , 1.001e9 f ) ;
doc . FirstChildElement ( ) - > SetAttribute ( " attrC-f32 " , 1.0e9 f ) ;
doc . FirstChildElement ( ) - > SetAttribute ( " attrC-f32 " , 1.0e20 f ) ;
doc . FirstChildElement ( ) - > SetAttribute ( " attrD-f32 " , 1.0e-10 f ) ;
doc . FirstChildElement ( ) - > SetAttribute ( " attrD-f32 " , 0.123456789f ) ;
doc . Print ( ) ;
/* The result of this test is platform, compiler, and library version dependent. :("
XMLPrinter printer ;
doc . Print ( & printer ) ;
XMLTest ( " Float and double formatting. " ,
" <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 " ,
printer . CStr ( ) ,
true ) ;
*/
}
# endif
2012-03-02 20:59:39 +00:00
// ----------- Performance tracking --------------
{
# if defined( _MSC_VER )
__int64 start , end , freq ;
QueryPerformanceFrequency ( ( LARGE_INTEGER * ) & freq ) ;
# endif
2012-05-07 07:58:11 +00:00
FILE * fp = fopen ( " resources/dream.xml " , " r " ) ;
2012-03-02 20:59:39 +00:00
fseek ( fp , 0 , SEEK_END ) ;
long size = ftell ( fp ) ;
fseek ( fp , 0 , SEEK_SET ) ;
char * mem = new char [ size + 1 ] ;
fread ( mem , size , 1 , fp ) ;
fclose ( fp ) ;
mem [ size ] = 0 ;
# if defined( _MSC_VER )
QueryPerformanceCounter ( ( LARGE_INTEGER * ) & start ) ;
# else
clock_t cstart = clock ( ) ;
# endif
static const int COUNT = 10 ;
for ( int i = 0 ; i < COUNT ; + + i ) {
XMLDocument doc ;
doc . Parse ( mem ) ;
}
# if defined( _MSC_VER )
QueryPerformanceCounter ( ( LARGE_INTEGER * ) & end ) ;
# else
clock_t cend = clock ( ) ;
# endif
delete [ ] mem ;
2012-09-16 18:32:34 +00:00
static const char * note =
2012-03-02 20:59:39 +00:00
# ifdef DEBUG
" DEBUG " ;
# else
" Release " ;
# endif
# if defined( _MSC_VER )
printf ( " \n Parsing %s of dream.xml: %.3f milli-seconds \n " , note , 1000.0 * ( double ) ( end - start ) / ( ( double ) freq * ( double ) COUNT ) ) ;
# else
printf ( " \n Parsing %s of dream.xml: %.3f milli-seconds \n " , note , ( double ) ( cend - cstart ) / ( double ) COUNT ) ;
# endif
}
2012-03-08 05:54:57 +00:00
# if defined( _MSC_VER ) && defined( DEBUG )
2012-09-16 18:32:34 +00:00
_CrtMemCheckpoint ( & endMemState ) ;
2012-02-15 02:18:16 +00:00
//_CrtMemDumpStatistics( &endMemState );
_CrtMemState diffMemState ;
_CrtMemDifference ( & diffMemState , & startMemState , & endMemState ) ;
_CrtMemDumpStatistics ( & diffMemState ) ;
2012-02-21 04:14:33 +00:00
//printf( "new total=%d\n", gNewTotal );
2012-02-15 02:18:16 +00:00
# endif
printf ( " \n Pass %d, Fail %d \n " , gPass , gFail ) ;
2013-07-31 19:24:52 +00:00
return gFail ;
2012-02-26 05:30:18 +00:00
}