24
www.sourceforge.net/projects/tinyxml
25
Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
27
This software is provided 'as-is', without any express or implied
28
warranty. In no event will the authors be held liable for any
29
damages arising from the use of this software.
31
Permission is granted to anyone to use this software for any
32
purpose, including commercial applications, and to alter it and
33
redistribute it freely, subject to the following restrictions:
35
1. The origin of this software must not be misrepresented; you must
36
not claim that you wrote the original software. If you use this
37
software in a product, an acknowledgment in the product documentation
38
would be appreciated but is not required.
40
2. Altered source versions must be plainly marked as such, and
41
must not be misrepresented as being the original software.
43
3. This notice may not be removed or altered from any source
57
bool TiXmlBase::condenseWhiteSpace = true;
59
// Microsoft compiler security
60
FILE* TiXmlFOpen( const char* filename, const char* mode )
62
#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
64
errno_t err = fopen_s( &fp, filename, mode );
69
return fopen( filename, mode );
73
void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString )
77
while( i<(int)str.length() )
79
unsigned char c = (unsigned char) str[i];
82
&& i < ( (int)str.length() - 2 )
86
// Hexadecimal character reference.
87
// Pass through unchanged.
88
// © -- copyright symbol, for example.
90
// The -1 is a bug fix from Rob Laveaux. It keeps
91
// an overflow from happening if there is no ';'.
92
// There are actually 2 ways to exit this loop -
93
// while fails (error case) and break (semicolon found).
94
// However, there is no mechanism (currently) for
95
// this function to return an error.
96
while ( i<(int)str.length()-1 )
98
outString->append( str.c_str() + i, 1 );
106
outString->append( entity[0].str, entity[0].strLength );
111
outString->append( entity[1].str, entity[1].strLength );
116
outString->append( entity[2].str, entity[2].strLength );
119
else if ( c == '\"' )
121
outString->append( entity[3].str, entity[3].strLength );
124
else if ( c == '\'' )
126
outString->append( entity[4].str, entity[4].strLength );
131
// Easy pass at non-alpha/numeric/symbol
132
// Below 32 is symbolic.
135
#if defined(TIXML_SNPRINTF)
136
TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) );
138
sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
141
//*ME: warning C4267: convert 'size_t' to 'int'
142
//*ME: Int-Cast to make compiler happy ...
143
outString->append( buf, (int)strlen( buf ) );
148
//char realc = (char) c;
149
//outString->append( &realc, 1 );
150
*outString += (char) c; // somewhat more efficient function call.
157
TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
168
TiXmlNode::~TiXmlNode()
170
TiXmlNode* node = firstChild;
182
void TiXmlNode::CopyTo( TiXmlNode* target ) const
184
target->SetValue (value.c_str() );
185
target->userData = userData;
189
void TiXmlNode::Clear()
191
TiXmlNode* node = firstChild;
206
TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
208
assert( node->parent == 0 || node->parent == this );
209
assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
211
if ( node->Type() == TiXmlNode::DOCUMENT )
214
if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
220
node->prev = lastChild;
224
lastChild->next = node;
226
firstChild = node; // it was an empty list.
233
TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
235
if ( addThis.Type() == TiXmlNode::DOCUMENT )
237
if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
240
TiXmlNode* node = addThis.Clone();
244
return LinkEndChild( node );
248
TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
250
if ( !beforeThis || beforeThis->parent != this ) {
253
if ( addThis.Type() == TiXmlNode::DOCUMENT )
255
if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
259
TiXmlNode* node = addThis.Clone();
264
node->next = beforeThis;
265
node->prev = beforeThis->prev;
266
if ( beforeThis->prev )
268
beforeThis->prev->next = node;
272
assert( firstChild == beforeThis );
275
beforeThis->prev = node;
280
TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
282
if ( !afterThis || afterThis->parent != this ) {
285
if ( addThis.Type() == TiXmlNode::DOCUMENT )
287
if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
291
TiXmlNode* node = addThis.Clone();
296
node->prev = afterThis;
297
node->next = afterThis->next;
298
if ( afterThis->next )
300
afterThis->next->prev = node;
304
assert( lastChild == afterThis );
307
afterThis->next = node;
312
TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
314
if ( replaceThis->parent != this )
317
TiXmlNode* node = withThis.Clone();
321
node->next = replaceThis->next;
322
node->prev = replaceThis->prev;
324
if ( replaceThis->next )
325
replaceThis->next->prev = node;
329
if ( replaceThis->prev )
330
replaceThis->prev->next = node;
340
bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
342
if ( removeThis->parent != this )
348
if ( removeThis->next )
349
removeThis->next->prev = removeThis->prev;
351
lastChild = removeThis->prev;
353
if ( removeThis->prev )
354
removeThis->prev->next = removeThis->next;
356
firstChild = removeThis->next;
362
const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const
364
const TiXmlNode* node;
365
for ( node = firstChild; node; node = node->next )
367
if ( strcmp( node->Value(), _value ) == 0 )
374
const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
376
const TiXmlNode* node;
377
for ( node = lastChild; node; node = node->prev )
379
if ( strcmp( node->Value(), _value ) == 0 )
386
const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const
394
assert( previous->parent == this );
395
return previous->NextSibling();
400
const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const
404
return FirstChild( val );
408
assert( previous->parent == this );
409
return previous->NextSibling( val );
414
const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const
416
const TiXmlNode* node;
417
for ( node = next; node; node = node->next )
419
if ( strcmp( node->Value(), _value ) == 0 )
426
const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
428
const TiXmlNode* node;
429
for ( node = prev; node; node = node->prev )
431
if ( strcmp( node->Value(), _value ) == 0 )
438
void TiXmlElement::RemoveAttribute( const char * name )
441
TIXML_STRING str( name );
442
TiXmlAttribute* node = attributeSet.Find( str );
444
TiXmlAttribute* node = attributeSet.Find( name );
448
attributeSet.Remove( node );
453
const TiXmlElement* TiXmlNode::FirstChildElement() const
455
const TiXmlNode* node;
457
for ( node = FirstChild();
459
node = node->NextSibling() )
461
if ( node->ToElement() )
462
return node->ToElement();
468
const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
470
const TiXmlNode* node;
472
for ( node = FirstChild( _value );
474
node = node->NextSibling( _value ) )
476
if ( node->ToElement() )
477
return node->ToElement();
483
const TiXmlElement* TiXmlNode::NextSiblingElement() const
485
const TiXmlNode* node;
487
for ( node = NextSibling();
489
node = node->NextSibling() )
491
if ( node->ToElement() )
492
return node->ToElement();
498
const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
500
const TiXmlNode* node;
502
for ( node = NextSibling( _value );
504
node = node->NextSibling( _value ) )
506
if ( node->ToElement() )
507
return node->ToElement();
513
const TiXmlDocument* TiXmlNode::GetDocument() const
515
const TiXmlNode* node;
517
for( node = this; node; node = node->parent )
519
if ( node->ToDocument() )
520
return node->ToDocument();
526
TiXmlElement::TiXmlElement (const char * _value)
527
: TiXmlNode( TiXmlNode::ELEMENT )
529
firstChild = lastChild = 0;
535
TiXmlElement::TiXmlElement( const std::string& _value )
536
: TiXmlNode( TiXmlNode::ELEMENT )
538
firstChild = lastChild = 0;
544
TiXmlElement::TiXmlElement( const TiXmlElement& copy)
545
: TiXmlNode( TiXmlNode::ELEMENT )
547
firstChild = lastChild = 0;
552
void TiXmlElement::operator=( const TiXmlElement& base )
559
TiXmlElement::~TiXmlElement()
565
void TiXmlElement::ClearThis()
568
while( attributeSet.First() )
570
TiXmlAttribute* node = attributeSet.First();
571
attributeSet.Remove( node );
577
const char* TiXmlElement::Attribute( const char* name ) const
579
const TiXmlAttribute* node = attributeSet.Find( name );
581
return node->Value();
587
const std::string* TiXmlElement::Attribute( const std::string& name ) const
589
const TiXmlAttribute* node = attributeSet.Find( name );
591
return &node->ValueStr();
597
const char* TiXmlElement::Attribute( const char* name, int* i ) const
599
const char* s = Attribute( name );
614
const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const
616
const std::string* s = Attribute( name );
620
*i = atoi( s->c_str() );
631
const char* TiXmlElement::Attribute( const char* name, double* d ) const
633
const char* s = Attribute( name );
648
const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const
650
const std::string* s = Attribute( name );
654
*d = atof( s->c_str() );
665
int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
667
const TiXmlAttribute* node = attributeSet.Find( name );
669
return TIXML_NO_ATTRIBUTE;
670
return node->QueryIntValue( ival );
675
int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const
677
const TiXmlAttribute* node = attributeSet.Find( name );
679
return TIXML_NO_ATTRIBUTE;
680
return node->QueryIntValue( ival );
685
int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
687
const TiXmlAttribute* node = attributeSet.Find( name );
689
return TIXML_NO_ATTRIBUTE;
690
return node->QueryDoubleValue( dval );
695
int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const
697
const TiXmlAttribute* node = attributeSet.Find( name );
699
return TIXML_NO_ATTRIBUTE;
700
return node->QueryDoubleValue( dval );
705
void TiXmlElement::SetAttribute( const char * name, int val )
708
#if defined(TIXML_SNPRINTF)
709
TIXML_SNPRINTF( buf, sizeof(buf), "%d", val );
711
sprintf( buf, "%d", val );
713
SetAttribute( name, buf );
718
void TiXmlElement::SetAttribute( const std::string& name, int val )
720
std::ostringstream oss;
722
SetAttribute( name, oss.str() );
727
void TiXmlElement::SetDoubleAttribute( const char * name, double val )
730
#if defined(TIXML_SNPRINTF)
731
TIXML_SNPRINTF( buf, sizeof(buf), "%f", val );
733
sprintf( buf, "%f", val );
735
SetAttribute( name, buf );
739
void TiXmlElement::SetAttribute( const char * cname, const char * cvalue )
742
TIXML_STRING _name( cname );
743
TIXML_STRING _value( cvalue );
745
const char* _name = cname;
746
const char* _value = cvalue;
749
TiXmlAttribute* node = attributeSet.Find( _name );
752
node->SetValue( _value );
756
TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue );
759
attributeSet.Add( attrib );
763
TiXmlDocument* document = GetDocument();
764
if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
770
void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value )
772
TiXmlAttribute* node = attributeSet.Find( name );
775
node->SetValue( _value );
779
TiXmlAttribute* attrib = new TiXmlAttribute( name, _value );
782
attributeSet.Add( attrib );
786
TiXmlDocument* document = GetDocument();
787
if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
793
void TiXmlElement::Print( FILE* cfile, int depth ) const
797
for ( i=0; i<depth; i++ ) {
798
fprintf( cfile, " " );
801
fprintf( cfile, "<%s", value.c_str() );
803
const TiXmlAttribute* attrib;
804
for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
806
fprintf( cfile, " " );
807
attrib->Print( cfile, depth );
810
// There are 3 different formatting approaches:
811
// 1) An element without children is printed as a <foo /> node
812
// 2) An element with only a text child is printed as <foo> text </foo>
813
// 3) An element with children is printed on multiple lines.
817
fprintf( cfile, " />" );
819
else if ( firstChild == lastChild && firstChild->ToText() )
821
fprintf( cfile, ">" );
822
firstChild->Print( cfile, depth + 1 );
823
fprintf( cfile, "</%s>", value.c_str() );
827
fprintf( cfile, ">" );
829
for ( node = firstChild; node; node=node->NextSibling() )
831
if ( !node->ToText() )
833
fprintf( cfile, "\n" );
835
node->Print( cfile, depth+1 );
837
fprintf( cfile, "\n" );
838
for( i=0; i<depth; ++i ) {
839
fprintf( cfile, " " );
841
fprintf( cfile, "</%s>", value.c_str() );
846
void TiXmlElement::CopyTo( TiXmlElement* target ) const
849
TiXmlNode::CopyTo( target );
852
// Clone the attributes, then clone the children.
853
const TiXmlAttribute* attribute = 0;
854
for( attribute = attributeSet.First();
856
attribute = attribute->Next() )
858
target->SetAttribute( attribute->Name(), attribute->Value() );
862
for ( node = firstChild; node; node = node->NextSibling() )
864
target->LinkEndChild( node->Clone() );
868
bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const
870
if ( visitor->VisitEnter( *this, attributeSet.First() ) )
872
for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
874
if ( !node->Accept( visitor ) )
878
return visitor->VisitExit( *this );
882
TiXmlNode* TiXmlElement::Clone() const
884
TiXmlElement* clone = new TiXmlElement( Value() );
893
const char* TiXmlElement::GetText() const
895
const TiXmlNode* child = this->FirstChild();
897
const TiXmlText* childText = child->ToText();
899
return childText->Value();
906
TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
909
useMicrosoftBOM = false;
913
TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
916
useMicrosoftBOM = false;
917
value = documentName;
923
TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
926
useMicrosoftBOM = false;
927
value = documentName;
933
TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT )
939
void TiXmlDocument::operator=( const TiXmlDocument& copy )
946
bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
948
// See STL_STRING_BUG below.
949
//StringToBuffer buf( value );
951
return LoadFile( Value(), encoding );
955
bool TiXmlDocument::SaveFile() const
957
// See STL_STRING_BUG below.
958
// StringToBuffer buf( value );
960
// if ( buf.buffer && SaveFile( buf.buffer ) )
964
return SaveFile( Value() );
967
bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
969
// There was a really terrifying little bug here. The code:
971
// in the STL case, cause the assignment method of the std::string to
972
// be called. What is strange, is that the std::string had the same
973
// address as it's c_str() method, and so bad things happen. Looks
974
// like a bug in the Microsoft STL implementation.
975
// Add an extra string to avoid the crash.
976
TIXML_STRING filename( _filename );
979
// reading in binary mode so that tinyxml can normalize the EOL
980
FILE* file = TiXmlFOpen( value.c_str (), "rb" );
984
bool result = LoadFile( file, encoding );
990
SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
995
bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
999
SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
1003
// Delete the existing data:
1007
// Get the file size, so we can pre-allocate the string. HUGE speed impact.
1009
fseek( file, 0, SEEK_END );
1010
length = ftell( file );
1011
fseek( file, 0, SEEK_SET );
1013
// Strange case, but good to handle up front.
1016
SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
1020
// If we have a file, assume it is all one big XML file, and read it in.
1021
// The document parser may decide the document ends sooner than the entire file, however.
1023
data.reserve( length );
1025
// Subtle bug here. TinyXml did use fgets. But from the XML spec:
1026
// 2.11 End-of-Line Handling
1029
// ...the XML processor MUST behave as if it normalized all line breaks in external
1030
// parsed entities (including the document entity) on input, before parsing, by translating
1031
// both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
1032
// a single #xA character.
1035
// It is not clear fgets does that, and certainly isn't clear it works cross platform.
1036
// Generally, you expect fgets to translate from the convention of the OS to the c/unix
1037
// convention, and not work generally.
1040
while( fgets( buf, sizeof(buf), file ) )
1046
char* buf = new char[ length+1 ];
1049
if ( fread( buf, length, 1, file ) != 1 ) {
1051
SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
1055
const char* lastPos = buf;
1056
const char* p = buf;
1060
assert( p < (buf+length) );
1062
// Newline character. No special rules for this. Append all the characters
1063
// since the last string, and include the newline.
1064
data.append( lastPos, (p-lastPos+1) ); // append, include the newline
1065
++p; // move past the newline
1066
lastPos = p; // and point to the new buffer (may be 0)
1067
assert( p <= (buf+length) );
1069
else if ( *p == 0xd ) {
1070
// Carriage return. Append what we have so far, then
1071
// handle moving forward in the buffer.
1072
if ( (p-lastPos) > 0 ) {
1073
data.append( lastPos, p-lastPos ); // do not add the CR
1075
data += (char)0xa; // a proper newline
1077
if ( *(p+1) == 0xa ) {
1078
// Carriage return - new line sequence
1081
assert( p <= (buf+length) );
1084
// it was followed by something else...that is presumably characters again.
1087
assert( p <= (buf+length) );
1094
// Handle any left over characters.
1096
data.append( lastPos, p-lastPos );
1101
Parse( data.c_str(), 0, encoding );
1110
bool TiXmlDocument::SaveFile( const char * filename ) const
1112
// The old c stuff lives on...
1113
FILE* fp = TiXmlFOpen( filename, "w" );
1116
bool result = SaveFile( fp );
1124
bool TiXmlDocument::SaveFile( FILE* fp ) const
1126
if ( useMicrosoftBOM )
1128
const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
1129
const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
1130
const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
1132
fputc( TIXML_UTF_LEAD_0, fp );
1133
fputc( TIXML_UTF_LEAD_1, fp );
1134
fputc( TIXML_UTF_LEAD_2, fp );
1137
return (ferror(fp) == 0);
1141
void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
1143
TiXmlNode::CopyTo( target );
1145
target->error = error;
1146
target->errorId = errorId;
1147
target->errorDesc = errorDesc;
1148
target->tabsize = tabsize;
1149
target->errorLocation = errorLocation;
1150
target->useMicrosoftBOM = useMicrosoftBOM;
1152
TiXmlNode* node = 0;
1153
for ( node = firstChild; node; node = node->NextSibling() )
1155
target->LinkEndChild( node->Clone() );
1160
TiXmlNode* TiXmlDocument::Clone() const
1162
TiXmlDocument* clone = new TiXmlDocument();
1171
void TiXmlDocument::Print( FILE* cfile, int depth ) const
1174
for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
1176
node->Print( cfile, depth );
1177
fprintf( cfile, "\n" );
1182
bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const
1184
if ( visitor->VisitEnter( *this ) )
1186
for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
1188
if ( !node->Accept( visitor ) )
1192
return visitor->VisitExit( *this );
1196
const TiXmlAttribute* TiXmlAttribute::Next() const
1198
// We are using knowledge of the sentinel. The sentinel
1199
// have a value or name.
1200
if ( next->value.empty() && next->name.empty() )
1206
TiXmlAttribute* TiXmlAttribute::Next()
1208
// We are using knowledge of the sentinel. The sentinel
1209
// have a value or name.
1210
if ( next->value.empty() && next->name.empty() )
1216
const TiXmlAttribute* TiXmlAttribute::Previous() const
1218
// We are using knowledge of the sentinel. The sentinel
1219
// have a value or name.
1220
if ( prev->value.empty() && prev->name.empty() )
1226
TiXmlAttribute* TiXmlAttribute::Previous()
1228
// We are using knowledge of the sentinel. The sentinel
1229
// have a value or name.
1230
if ( prev->value.empty() && prev->name.empty() )
1236
void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
1240
EncodeString( name, &n );
1241
EncodeString( value, &v );
1243
if (value.find ('\"') == TIXML_STRING::npos) {
1245
fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
1248
(*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\"";
1253
fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
1256
(*str) += n; (*str) += "='"; (*str) += v; (*str) += "'";
1262
int TiXmlAttribute::QueryIntValue( int* ival ) const
1264
if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 )
1265
return TIXML_SUCCESS;
1266
return TIXML_WRONG_TYPE;
1269
int TiXmlAttribute::QueryDoubleValue( double* dval ) const
1271
if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 )
1272
return TIXML_SUCCESS;
1273
return TIXML_WRONG_TYPE;
1276
void TiXmlAttribute::SetIntValue( int _value )
1279
#if defined(TIXML_SNPRINTF)
1280
TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
1282
sprintf (buf, "%d", _value);
1287
void TiXmlAttribute::SetDoubleValue( double _value )
1290
#if defined(TIXML_SNPRINTF)
1291
TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value);
1293
sprintf (buf, "%lf", _value);
1298
int TiXmlAttribute::IntValue() const
1300
return atoi (value.c_str ());
1303
double TiXmlAttribute::DoubleValue() const
1305
return atof (value.c_str ());
1309
TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT )
1311
copy.CopyTo( this );
1315
void TiXmlComment::operator=( const TiXmlComment& base )
1318
base.CopyTo( this );
1322
void TiXmlComment::Print( FILE* cfile, int depth ) const
1325
for ( int i=0; i<depth; i++ )
1327
fprintf( cfile, " " );
1329
fprintf( cfile, "<!--%s-->", value.c_str() );
1333
void TiXmlComment::CopyTo( TiXmlComment* target ) const
1335
TiXmlNode::CopyTo( target );
1339
bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const
1341
return visitor->Visit( *this );
1345
TiXmlNode* TiXmlComment::Clone() const
1347
TiXmlComment* clone = new TiXmlComment();
1357
void TiXmlText::Print( FILE* cfile, int depth ) const
1363
fprintf( cfile, "\n" );
1364
for ( i=0; i<depth; i++ ) {
1365
fprintf( cfile, " " );
1367
fprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() ); // unformatted output
1371
TIXML_STRING buffer;
1372
EncodeString( value, &buffer );
1373
fprintf( cfile, "%s", buffer.c_str() );
1378
void TiXmlText::CopyTo( TiXmlText* target ) const
1380
TiXmlNode::CopyTo( target );
1381
target->cdata = cdata;
1385
bool TiXmlText::Accept( TiXmlVisitor* visitor ) const
1387
return visitor->Visit( *this );
1391
TiXmlNode* TiXmlText::Clone() const
1393
TiXmlText* clone = 0;
1394
clone = new TiXmlText( "" );
1404
TiXmlDeclaration::TiXmlDeclaration( const char * _version,
1405
const char * _encoding,
1406
const char * _standalone )
1407
: TiXmlNode( TiXmlNode::DECLARATION )
1410
encoding = _encoding;
1411
standalone = _standalone;
1415
#ifdef TIXML_USE_STL
1416
TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
1417
const std::string& _encoding,
1418
const std::string& _standalone )
1419
: TiXmlNode( TiXmlNode::DECLARATION )
1422
encoding = _encoding;
1423
standalone = _standalone;
1428
TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
1429
: TiXmlNode( TiXmlNode::DECLARATION )
1431
copy.CopyTo( this );
1435
void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
1438
copy.CopyTo( this );
1442
void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
1444
if ( cfile ) fprintf( cfile, "<?xml " );
1445
if ( str ) (*str) += "<?xml ";
1447
if ( !version.empty() ) {
1448
if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ());
1449
if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; }
1451
if ( !encoding.empty() ) {
1452
if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
1453
if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; }
1455
if ( !standalone.empty() ) {
1456
if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
1457
if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; }
1459
if ( cfile ) fprintf( cfile, "?>" );
1460
if ( str ) (*str) += "?>";
1464
void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
1466
TiXmlNode::CopyTo( target );
1468
target->version = version;
1469
target->encoding = encoding;
1470
target->standalone = standalone;
1474
bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const
1476
return visitor->Visit( *this );
1480
TiXmlNode* TiXmlDeclaration::Clone() const
1482
TiXmlDeclaration* clone = new TiXmlDeclaration();
1492
void TiXmlUnknown::Print( FILE* cfile, int depth ) const
1494
for ( int i=0; i<depth; i++ )
1495
fprintf( cfile, " " );
1496
fprintf( cfile, "<%s>", value.c_str() );
1500
void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
1502
TiXmlNode::CopyTo( target );
1506
bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const
1508
return visitor->Visit( *this );
1512
TiXmlNode* TiXmlUnknown::Clone() const
1514
TiXmlUnknown* clone = new TiXmlUnknown();
1524
TiXmlAttributeSet::TiXmlAttributeSet()
1526
sentinel.next = &sentinel;
1527
sentinel.prev = &sentinel;
1531
TiXmlAttributeSet::~TiXmlAttributeSet()
1533
assert( sentinel.next == &sentinel );
1534
assert( sentinel.prev == &sentinel );
1538
void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
1540
#ifdef TIXML_USE_STL
1541
assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set.
1543
assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set.
1546
addMe->next = &sentinel;
1547
addMe->prev = sentinel.prev;
1549
sentinel.prev->next = addMe;
1550
sentinel.prev = addMe;
1553
void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
1555
TiXmlAttribute* node;
1557
for( node = sentinel.next; node != &sentinel; node = node->next )
1559
if ( node == removeMe )
1561
node->prev->next = node->next;
1562
node->next->prev = node->prev;
1568
assert( 0 ); // we tried to remove a non-linked attribute.
1572
#ifdef TIXML_USE_STL
1573
const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
1575
for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1577
if ( node->name == name )
1584
TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name )
1586
for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1588
if ( node->name == name )
1597
const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const
1599
for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1601
if ( strcmp( node->name.c_str(), name ) == 0 )
1608
TiXmlAttribute* TiXmlAttributeSet::Find( const char* name )
1610
for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1612
if ( strcmp( node->name.c_str(), name ) == 0 )
1619
#ifdef TIXML_USE_STL
1620
std::istream& operator>> (std::istream & in, TiXmlNode & base)
1623
tag.reserve( 8 * 1000 );
1624
base.StreamIn( &in, &tag );
1626
base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
1632
#ifdef TIXML_USE_STL
1633
std::ostream& operator<< (std::ostream & out, const TiXmlNode & base)
1635
TiXmlPrinter printer;
1636
printer.SetStreamPrinting();
1637
base.Accept( &printer );
1638
out << printer.Str();
1644
std::string& operator<< (std::string& out, const TiXmlNode& base )
1646
TiXmlPrinter printer;
1647
printer.SetStreamPrinting();
1648
base.Accept( &printer );
1649
out.append( printer.Str() );
1656
TiXmlHandle TiXmlHandle::FirstChild() const
1660
TiXmlNode* child = node->FirstChild();
1662
return TiXmlHandle( child );
1664
return TiXmlHandle( 0 );
1668
TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
1672
TiXmlNode* child = node->FirstChild( value );
1674
return TiXmlHandle( child );
1676
return TiXmlHandle( 0 );
1680
TiXmlHandle TiXmlHandle::FirstChildElement() const
1684
TiXmlElement* child = node->FirstChildElement();
1686
return TiXmlHandle( child );
1688
return TiXmlHandle( 0 );
1692
TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
1696
TiXmlElement* child = node->FirstChildElement( value );
1698
return TiXmlHandle( child );
1700
return TiXmlHandle( 0 );
1704
TiXmlHandle TiXmlHandle::Child( int count ) const
1709
TiXmlNode* child = node->FirstChild();
1712
child = child->NextSibling(), ++i )
1717
return TiXmlHandle( child );
1719
return TiXmlHandle( 0 );
1723
TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
1728
TiXmlNode* child = node->FirstChild( value );
1731
child = child->NextSibling( value ), ++i )
1736
return TiXmlHandle( child );
1738
return TiXmlHandle( 0 );
1742
TiXmlHandle TiXmlHandle::ChildElement( int count ) const
1747
TiXmlElement* child = node->FirstChildElement();
1750
child = child->NextSiblingElement(), ++i )
1755
return TiXmlHandle( child );
1757
return TiXmlHandle( 0 );
1761
TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
1766
TiXmlElement* child = node->FirstChildElement( value );
1769
child = child->NextSiblingElement( value ), ++i )
1774
return TiXmlHandle( child );
1776
return TiXmlHandle( 0 );
1780
bool TiXmlPrinter::VisitEnter( const TiXmlDocument& )
1785
bool TiXmlPrinter::VisitExit( const TiXmlDocument& )
1790
bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute )
1794
buffer += element.Value();
1796
for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() )
1799
attrib->Print( 0, 0, &buffer );
1802
if ( !element.FirstChild() )
1810
if ( element.FirstChild()->ToText()
1811
&& element.LastChild() == element.FirstChild()
1812
&& element.FirstChild()->ToText()->CDATA() == false )
1814
simpleTextPrint = true;
1815
// no DoLineBreak()!
1827
bool TiXmlPrinter::VisitExit( const TiXmlElement& element )
1830
if ( !element.FirstChild() )
1836
if ( simpleTextPrint )
1838
simpleTextPrint = false;
1845
buffer += element.Value();
1853
bool TiXmlPrinter::Visit( const TiXmlText& text )
1858
buffer += "<![CDATA[";
1859
buffer += text.Value();
1863
else if ( simpleTextPrint )
1866
TiXmlBase::EncodeString( text.ValueTStr(), &str );
1873
TiXmlBase::EncodeString( text.ValueTStr(), &str );
1881
bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration )
1884
declaration.Print( 0, 0, &buffer );
1890
bool TiXmlPrinter::Visit( const TiXmlComment& comment )
1894
buffer += comment.Value();
1901
bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown )
1905
buffer += unknown.Value();
24
www.sourceforge.net/projects/tinyxml
25
Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
27
This software is provided 'as-is', without any express or implied
28
warranty. In no event will the authors be held liable for any
29
damages arising from the use of this software.
31
Permission is granted to anyone to use this software for any
32
purpose, including commercial applications, and to alter it and
33
redistribute it freely, subject to the following restrictions:
35
1. The origin of this software must not be misrepresented; you must
36
not claim that you wrote the original software. If you use this
37
software in a product, an acknowledgment in the product documentation
38
would be appreciated but is not required.
40
2. Altered source versions must be plainly marked as such, and
41
must not be misrepresented as being the original software.
43
3. This notice may not be removed or altered from any source
57
bool TiXmlBase::condenseWhiteSpace = true;
59
// Microsoft compiler security
60
FILE* TiXmlFOpen( const char* filename, const char* mode )
62
#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
64
errno_t err = fopen_s( &fp, filename, mode );
69
return fopen( filename, mode );
73
void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString )
77
while( i<(int)str.length() )
79
unsigned char c = (unsigned char) str[i];
82
&& i < ( (int)str.length() - 2 )
86
// Hexadecimal character reference.
87
// Pass through unchanged.
88
// © -- copyright symbol, for example.
90
// The -1 is a bug fix from Rob Laveaux. It keeps
91
// an overflow from happening if there is no ';'.
92
// There are actually 2 ways to exit this loop -
93
// while fails (error case) and break (semicolon found).
94
// However, there is no mechanism (currently) for
95
// this function to return an error.
96
while ( i<(int)str.length()-1 )
98
outString->append( str.c_str() + i, 1 );
106
outString->append( entity[0].str, entity[0].strLength );
111
outString->append( entity[1].str, entity[1].strLength );
116
outString->append( entity[2].str, entity[2].strLength );
119
else if ( c == '\"' )
121
outString->append( entity[3].str, entity[3].strLength );
124
else if ( c == '\'' )
126
outString->append( entity[4].str, entity[4].strLength );
131
// Easy pass at non-alpha/numeric/symbol
132
// Below 32 is symbolic.
135
#if defined(TIXML_SNPRINTF)
136
TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) );
138
sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
141
//*ME: warning C4267: convert 'size_t' to 'int'
142
//*ME: Int-Cast to make compiler happy ...
143
outString->append( buf, (int)strlen( buf ) );
148
//char realc = (char) c;
149
//outString->append( &realc, 1 );
150
*outString += (char) c; // somewhat more efficient function call.
157
TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
168
TiXmlNode::~TiXmlNode()
170
TiXmlNode* node = firstChild;
182
void TiXmlNode::CopyTo( TiXmlNode* target ) const
184
target->SetValue (value.c_str() );
185
target->userData = userData;
189
void TiXmlNode::Clear()
191
TiXmlNode* node = firstChild;
206
TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
208
assert( node->parent == 0 || node->parent == this );
209
assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
211
if ( node->Type() == TiXmlNode::DOCUMENT )
214
if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
220
node->prev = lastChild;
224
lastChild->next = node;
226
firstChild = node; // it was an empty list.
233
TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
235
if ( addThis.Type() == TiXmlNode::DOCUMENT )
237
if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
240
TiXmlNode* node = addThis.Clone();
244
return LinkEndChild( node );
248
TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
250
if ( !beforeThis || beforeThis->parent != this ) {
253
if ( addThis.Type() == TiXmlNode::DOCUMENT )
255
if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
259
TiXmlNode* node = addThis.Clone();
264
node->next = beforeThis;
265
node->prev = beforeThis->prev;
266
if ( beforeThis->prev )
268
beforeThis->prev->next = node;
272
assert( firstChild == beforeThis );
275
beforeThis->prev = node;
280
TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
282
if ( !afterThis || afterThis->parent != this ) {
285
if ( addThis.Type() == TiXmlNode::DOCUMENT )
287
if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
291
TiXmlNode* node = addThis.Clone();
296
node->prev = afterThis;
297
node->next = afterThis->next;
298
if ( afterThis->next )
300
afterThis->next->prev = node;
304
assert( lastChild == afterThis );
307
afterThis->next = node;
312
TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
314
if ( replaceThis->parent != this )
317
TiXmlNode* node = withThis.Clone();
321
node->next = replaceThis->next;
322
node->prev = replaceThis->prev;
324
if ( replaceThis->next )
325
replaceThis->next->prev = node;
329
if ( replaceThis->prev )
330
replaceThis->prev->next = node;
340
bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
342
if ( removeThis->parent != this )
348
if ( removeThis->next )
349
removeThis->next->prev = removeThis->prev;
351
lastChild = removeThis->prev;
353
if ( removeThis->prev )
354
removeThis->prev->next = removeThis->next;
356
firstChild = removeThis->next;
362
const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const
364
const TiXmlNode* node;
365
for ( node = firstChild; node; node = node->next )
367
if ( strcmp( node->Value(), _value ) == 0 )
374
const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
376
const TiXmlNode* node;
377
for ( node = lastChild; node; node = node->prev )
379
if ( strcmp( node->Value(), _value ) == 0 )
386
const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const
394
assert( previous->parent == this );
395
return previous->NextSibling();
400
const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const
404
return FirstChild( val );
408
assert( previous->parent == this );
409
return previous->NextSibling( val );
414
const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const
416
const TiXmlNode* node;
417
for ( node = next; node; node = node->next )
419
if ( strcmp( node->Value(), _value ) == 0 )
426
const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
428
const TiXmlNode* node;
429
for ( node = prev; node; node = node->prev )
431
if ( strcmp( node->Value(), _value ) == 0 )
438
void TiXmlElement::RemoveAttribute( const char * name )
441
TIXML_STRING str( name );
442
TiXmlAttribute* node = attributeSet.Find( str );
444
TiXmlAttribute* node = attributeSet.Find( name );
448
attributeSet.Remove( node );
453
const TiXmlElement* TiXmlNode::FirstChildElement() const
455
const TiXmlNode* node;
457
for ( node = FirstChild();
459
node = node->NextSibling() )
461
if ( node->ToElement() )
462
return node->ToElement();
468
const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
470
const TiXmlNode* node;
472
for ( node = FirstChild( _value );
474
node = node->NextSibling( _value ) )
476
if ( node->ToElement() )
477
return node->ToElement();
483
const TiXmlElement* TiXmlNode::NextSiblingElement() const
485
const TiXmlNode* node;
487
for ( node = NextSibling();
489
node = node->NextSibling() )
491
if ( node->ToElement() )
492
return node->ToElement();
498
const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
500
const TiXmlNode* node;
502
for ( node = NextSibling( _value );
504
node = node->NextSibling( _value ) )
506
if ( node->ToElement() )
507
return node->ToElement();
513
const TiXmlDocument* TiXmlNode::GetDocument() const
515
const TiXmlNode* node;
517
for( node = this; node; node = node->parent )
519
if ( node->ToDocument() )
520
return node->ToDocument();
526
TiXmlElement::TiXmlElement (const char * _value)
527
: TiXmlNode( TiXmlNode::ELEMENT )
529
firstChild = lastChild = 0;
535
TiXmlElement::TiXmlElement( const std::string& _value )
536
: TiXmlNode( TiXmlNode::ELEMENT )
538
firstChild = lastChild = 0;
544
TiXmlElement::TiXmlElement( const TiXmlElement& copy)
545
: TiXmlNode( TiXmlNode::ELEMENT )
547
firstChild = lastChild = 0;
552
void TiXmlElement::operator=( const TiXmlElement& base )
559
TiXmlElement::~TiXmlElement()
565
void TiXmlElement::ClearThis()
568
while( attributeSet.First() )
570
TiXmlAttribute* node = attributeSet.First();
571
attributeSet.Remove( node );
577
const char* TiXmlElement::Attribute( const char* name ) const
579
const TiXmlAttribute* node = attributeSet.Find( name );
581
return node->Value();
587
const std::string* TiXmlElement::Attribute( const std::string& name ) const
589
const TiXmlAttribute* node = attributeSet.Find( name );
591
return &node->ValueStr();
597
const char* TiXmlElement::Attribute( const char* name, int* i ) const
599
const char* s = Attribute( name );
614
const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const
616
const std::string* s = Attribute( name );
620
*i = atoi( s->c_str() );
631
const char* TiXmlElement::Attribute( const char* name, double* d ) const
633
const char* s = Attribute( name );
648
const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const
650
const std::string* s = Attribute( name );
654
*d = atof( s->c_str() );
665
int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
667
const TiXmlAttribute* node = attributeSet.Find( name );
669
return TIXML_NO_ATTRIBUTE;
670
return node->QueryIntValue( ival );
675
int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const
677
const TiXmlAttribute* node = attributeSet.Find( name );
679
return TIXML_NO_ATTRIBUTE;
680
return node->QueryIntValue( ival );
685
int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
687
const TiXmlAttribute* node = attributeSet.Find( name );
689
return TIXML_NO_ATTRIBUTE;
690
return node->QueryDoubleValue( dval );
695
int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const
697
const TiXmlAttribute* node = attributeSet.Find( name );
699
return TIXML_NO_ATTRIBUTE;
700
return node->QueryDoubleValue( dval );
705
void TiXmlElement::SetAttribute( const char * name, int val )
708
#if defined(TIXML_SNPRINTF)
709
TIXML_SNPRINTF( buf, sizeof(buf), "%d", val );
711
sprintf( buf, "%d", val );
713
SetAttribute( name, buf );
718
void TiXmlElement::SetAttribute( const std::string& name, int val )
720
std::ostringstream oss;
722
SetAttribute( name, oss.str() );
727
void TiXmlElement::SetDoubleAttribute( const char * name, double val )
730
#if defined(TIXML_SNPRINTF)
731
TIXML_SNPRINTF( buf, sizeof(buf), "%f", val );
733
sprintf( buf, "%f", val );
735
SetAttribute( name, buf );
739
void TiXmlElement::SetAttribute( const char * cname, const char * cvalue )
742
TIXML_STRING _name( cname );
743
TIXML_STRING _value( cvalue );
745
const char* _name = cname;
746
const char* _value = cvalue;
749
TiXmlAttribute* node = attributeSet.Find( _name );
752
node->SetValue( _value );
756
TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue );
759
attributeSet.Add( attrib );
763
TiXmlDocument* document = GetDocument();
764
if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
770
void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value )
772
TiXmlAttribute* node = attributeSet.Find( name );
775
node->SetValue( _value );
779
TiXmlAttribute* attrib = new TiXmlAttribute( name, _value );
782
attributeSet.Add( attrib );
786
TiXmlDocument* document = GetDocument();
787
if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
793
void TiXmlElement::Print( FILE* cfile, int depth ) const
797
for ( i=0; i<depth; i++ ) {
798
fprintf( cfile, " " );
801
fprintf( cfile, "<%s", value.c_str() );
803
const TiXmlAttribute* attrib;
804
for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
806
fprintf( cfile, " " );
807
attrib->Print( cfile, depth );
810
// There are 3 different formatting approaches:
811
// 1) An element without children is printed as a <foo /> node
812
// 2) An element with only a text child is printed as <foo> text </foo>
813
// 3) An element with children is printed on multiple lines.
817
fprintf( cfile, " />" );
819
else if ( firstChild == lastChild && firstChild->ToText() )
821
fprintf( cfile, ">" );
822
firstChild->Print( cfile, depth + 1 );
823
fprintf( cfile, "</%s>", value.c_str() );
827
fprintf( cfile, ">" );
829
for ( node = firstChild; node; node=node->NextSibling() )
831
if ( !node->ToText() )
833
fprintf( cfile, "\n" );
835
node->Print( cfile, depth+1 );
837
fprintf( cfile, "\n" );
838
for( i=0; i<depth; ++i ) {
839
fprintf( cfile, " " );
841
fprintf( cfile, "</%s>", value.c_str() );
846
void TiXmlElement::CopyTo( TiXmlElement* target ) const
849
TiXmlNode::CopyTo( target );
852
// Clone the attributes, then clone the children.
853
const TiXmlAttribute* attribute = 0;
854
for( attribute = attributeSet.First();
856
attribute = attribute->Next() )
858
target->SetAttribute( attribute->Name(), attribute->Value() );
862
for ( node = firstChild; node; node = node->NextSibling() )
864
target->LinkEndChild( node->Clone() );
868
bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const
870
if ( visitor->VisitEnter( *this, attributeSet.First() ) )
872
for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
874
if ( !node->Accept( visitor ) )
878
return visitor->VisitExit( *this );
882
TiXmlNode* TiXmlElement::Clone() const
884
TiXmlElement* clone = new TiXmlElement( Value() );
893
const char* TiXmlElement::GetText() const
895
const TiXmlNode* child = this->FirstChild();
897
const TiXmlText* childText = child->ToText();
899
return childText->Value();
906
TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
909
useMicrosoftBOM = false;
913
TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
916
useMicrosoftBOM = false;
917
value = documentName;
923
TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
926
useMicrosoftBOM = false;
927
value = documentName;
933
TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT )
939
void TiXmlDocument::operator=( const TiXmlDocument& copy )
946
bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
948
// See STL_STRING_BUG below.
949
//StringToBuffer buf( value );
951
return LoadFile( Value(), encoding );
955
bool TiXmlDocument::SaveFile() const
957
// See STL_STRING_BUG below.
958
// StringToBuffer buf( value );
960
// if ( buf.buffer && SaveFile( buf.buffer ) )
964
return SaveFile( Value() );
967
bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
969
// There was a really terrifying little bug here. The code:
971
// in the STL case, cause the assignment method of the std::string to
972
// be called. What is strange, is that the std::string had the same
973
// address as it's c_str() method, and so bad things happen. Looks
974
// like a bug in the Microsoft STL implementation.
975
// Add an extra string to avoid the crash.
976
TIXML_STRING filename( _filename );
979
// reading in binary mode so that tinyxml can normalize the EOL
980
FILE* file = TiXmlFOpen( value.c_str (), "rb" );
984
bool result = LoadFile( file, encoding );
990
SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
995
bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
999
SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
1003
// Delete the existing data:
1007
// Get the file size, so we can pre-allocate the string. HUGE speed impact.
1009
fseek( file, 0, SEEK_END );
1010
length = ftell( file );
1011
fseek( file, 0, SEEK_SET );
1013
// Strange case, but good to handle up front.
1016
SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
1020
// If we have a file, assume it is all one big XML file, and read it in.
1021
// The document parser may decide the document ends sooner than the entire file, however.
1023
data.reserve( length );
1025
// Subtle bug here. TinyXml did use fgets. But from the XML spec:
1026
// 2.11 End-of-Line Handling
1029
// ...the XML processor MUST behave as if it normalized all line breaks in external
1030
// parsed entities (including the document entity) on input, before parsing, by translating
1031
// both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
1032
// a single #xA character.
1035
// It is not clear fgets does that, and certainly isn't clear it works cross platform.
1036
// Generally, you expect fgets to translate from the convention of the OS to the c/unix
1037
// convention, and not work generally.
1040
while( fgets( buf, sizeof(buf), file ) )
1046
char* buf = new char[ length+1 ];
1049
if ( fread( buf, length, 1, file ) != 1 ) {
1051
SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
1055
const char* lastPos = buf;
1056
const char* p = buf;
1060
assert( p < (buf+length) );
1062
// Newline character. No special rules for this. Append all the characters
1063
// since the last string, and include the newline.
1064
data.append( lastPos, (p-lastPos+1) ); // append, include the newline
1065
++p; // move past the newline
1066
lastPos = p; // and point to the new buffer (may be 0)
1067
assert( p <= (buf+length) );
1069
else if ( *p == 0xd ) {
1070
// Carriage return. Append what we have so far, then
1071
// handle moving forward in the buffer.
1072
if ( (p-lastPos) > 0 ) {
1073
data.append( lastPos, p-lastPos ); // do not add the CR
1075
data += (char)0xa; // a proper newline
1077
if ( *(p+1) == 0xa ) {
1078
// Carriage return - new line sequence
1081
assert( p <= (buf+length) );
1084
// it was followed by something else...that is presumably characters again.
1087
assert( p <= (buf+length) );
1094
// Handle any left over characters.
1096
data.append( lastPos, p-lastPos );
1101
Parse( data.c_str(), 0, encoding );
1110
bool TiXmlDocument::SaveFile( const char * filename ) const
1112
// The old c stuff lives on...
1113
FILE* fp = TiXmlFOpen( filename, "w" );
1116
bool result = SaveFile( fp );
1124
bool TiXmlDocument::SaveFile( FILE* fp ) const
1126
if ( useMicrosoftBOM )
1128
const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
1129
const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
1130
const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
1132
fputc( TIXML_UTF_LEAD_0, fp );
1133
fputc( TIXML_UTF_LEAD_1, fp );
1134
fputc( TIXML_UTF_LEAD_2, fp );
1137
return (ferror(fp) == 0);
1141
void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
1143
TiXmlNode::CopyTo( target );
1145
target->error = error;
1146
target->errorId = errorId;
1147
target->errorDesc = errorDesc;
1148
target->tabsize = tabsize;
1149
target->errorLocation = errorLocation;
1150
target->useMicrosoftBOM = useMicrosoftBOM;
1152
TiXmlNode* node = 0;
1153
for ( node = firstChild; node; node = node->NextSibling() )
1155
target->LinkEndChild( node->Clone() );
1160
TiXmlNode* TiXmlDocument::Clone() const
1162
TiXmlDocument* clone = new TiXmlDocument();
1171
void TiXmlDocument::Print( FILE* cfile, int depth ) const
1174
for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
1176
node->Print( cfile, depth );
1177
fprintf( cfile, "\n" );
1182
bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const
1184
if ( visitor->VisitEnter( *this ) )
1186
for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
1188
if ( !node->Accept( visitor ) )
1192
return visitor->VisitExit( *this );
1196
const TiXmlAttribute* TiXmlAttribute::Next() const
1198
// We are using knowledge of the sentinel. The sentinel
1199
// have a value or name.
1200
if ( next->value.empty() && next->name.empty() )
1206
TiXmlAttribute* TiXmlAttribute::Next()
1208
// We are using knowledge of the sentinel. The sentinel
1209
// have a value or name.
1210
if ( next->value.empty() && next->name.empty() )
1216
const TiXmlAttribute* TiXmlAttribute::Previous() const
1218
// We are using knowledge of the sentinel. The sentinel
1219
// have a value or name.
1220
if ( prev->value.empty() && prev->name.empty() )
1226
TiXmlAttribute* TiXmlAttribute::Previous()
1228
// We are using knowledge of the sentinel. The sentinel
1229
// have a value or name.
1230
if ( prev->value.empty() && prev->name.empty() )
1236
void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
1240
EncodeString( name, &n );
1241
EncodeString( value, &v );
1243
if (value.find ('\"') == TIXML_STRING::npos) {
1245
fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
1248
(*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\"";
1253
fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
1256
(*str) += n; (*str) += "='"; (*str) += v; (*str) += "'";
1262
int TiXmlAttribute::QueryIntValue( int* ival ) const
1264
if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 )
1265
return TIXML_SUCCESS;
1266
return TIXML_WRONG_TYPE;
1269
int TiXmlAttribute::QueryDoubleValue( double* dval ) const
1271
if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 )
1272
return TIXML_SUCCESS;
1273
return TIXML_WRONG_TYPE;
1276
void TiXmlAttribute::SetIntValue( int _value )
1279
#if defined(TIXML_SNPRINTF)
1280
TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
1282
sprintf (buf, "%d", _value);
1287
void TiXmlAttribute::SetDoubleValue( double _value )
1290
#if defined(TIXML_SNPRINTF)
1291
TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value);
1293
sprintf (buf, "%lf", _value);
1298
int TiXmlAttribute::IntValue() const
1300
return atoi (value.c_str ());
1303
double TiXmlAttribute::DoubleValue() const
1305
return atof (value.c_str ());
1309
TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT )
1311
copy.CopyTo( this );
1315
void TiXmlComment::operator=( const TiXmlComment& base )
1318
base.CopyTo( this );
1322
void TiXmlComment::Print( FILE* cfile, int depth ) const
1325
for ( int i=0; i<depth; i++ )
1327
fprintf( cfile, " " );
1329
fprintf( cfile, "<!--%s-->", value.c_str() );
1333
void TiXmlComment::CopyTo( TiXmlComment* target ) const
1335
TiXmlNode::CopyTo( target );
1339
bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const
1341
return visitor->Visit( *this );
1345
TiXmlNode* TiXmlComment::Clone() const
1347
TiXmlComment* clone = new TiXmlComment();
1357
void TiXmlText::Print( FILE* cfile, int depth ) const
1363
fprintf( cfile, "\n" );
1364
for ( i=0; i<depth; i++ ) {
1365
fprintf( cfile, " " );
1367
fprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() ); // unformatted output
1371
TIXML_STRING buffer;
1372
EncodeString( value, &buffer );
1373
fprintf( cfile, "%s", buffer.c_str() );
1378
void TiXmlText::CopyTo( TiXmlText* target ) const
1380
TiXmlNode::CopyTo( target );
1381
target->cdata = cdata;
1385
bool TiXmlText::Accept( TiXmlVisitor* visitor ) const
1387
return visitor->Visit( *this );
1391
TiXmlNode* TiXmlText::Clone() const
1393
TiXmlText* clone = 0;
1394
clone = new TiXmlText( "" );
1404
TiXmlDeclaration::TiXmlDeclaration( const char * _version,
1405
const char * _encoding,
1406
const char * _standalone )
1407
: TiXmlNode( TiXmlNode::DECLARATION )
1410
encoding = _encoding;
1411
standalone = _standalone;
1415
#ifdef TIXML_USE_STL
1416
TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
1417
const std::string& _encoding,
1418
const std::string& _standalone )
1419
: TiXmlNode( TiXmlNode::DECLARATION )
1422
encoding = _encoding;
1423
standalone = _standalone;
1428
TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
1429
: TiXmlNode( TiXmlNode::DECLARATION )
1431
copy.CopyTo( this );
1435
void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
1438
copy.CopyTo( this );
1442
void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
1444
if ( cfile ) fprintf( cfile, "<?xml " );
1445
if ( str ) (*str) += "<?xml ";
1447
if ( !version.empty() ) {
1448
if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ());
1449
if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; }
1451
if ( !encoding.empty() ) {
1452
if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
1453
if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; }
1455
if ( !standalone.empty() ) {
1456
if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
1457
if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; }
1459
if ( cfile ) fprintf( cfile, "?>" );
1460
if ( str ) (*str) += "?>";
1464
void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
1466
TiXmlNode::CopyTo( target );
1468
target->version = version;
1469
target->encoding = encoding;
1470
target->standalone = standalone;
1474
bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const
1476
return visitor->Visit( *this );
1480
TiXmlNode* TiXmlDeclaration::Clone() const
1482
TiXmlDeclaration* clone = new TiXmlDeclaration();
1492
void TiXmlUnknown::Print( FILE* cfile, int depth ) const
1494
for ( int i=0; i<depth; i++ )
1495
fprintf( cfile, " " );
1496
fprintf( cfile, "<%s>", value.c_str() );
1500
void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
1502
TiXmlNode::CopyTo( target );
1506
bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const
1508
return visitor->Visit( *this );
1512
TiXmlNode* TiXmlUnknown::Clone() const
1514
TiXmlUnknown* clone = new TiXmlUnknown();
1524
TiXmlAttributeSet::TiXmlAttributeSet()
1526
sentinel.next = &sentinel;
1527
sentinel.prev = &sentinel;
1531
TiXmlAttributeSet::~TiXmlAttributeSet()
1533
assert( sentinel.next == &sentinel );
1534
assert( sentinel.prev == &sentinel );
1538
void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
1540
#ifdef TIXML_USE_STL
1541
assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set.
1543
assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set.
1546
addMe->next = &sentinel;
1547
addMe->prev = sentinel.prev;
1549
sentinel.prev->next = addMe;
1550
sentinel.prev = addMe;
1553
void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
1555
TiXmlAttribute* node;
1557
for( node = sentinel.next; node != &sentinel; node = node->next )
1559
if ( node == removeMe )
1561
node->prev->next = node->next;
1562
node->next->prev = node->prev;
1568
assert( 0 ); // we tried to remove a non-linked attribute.
1572
#ifdef TIXML_USE_STL
1573
const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
1575
for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1577
if ( node->name == name )
1584
TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name )
1586
for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1588
if ( node->name == name )
1597
const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const
1599
for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1601
if ( strcmp( node->name.c_str(), name ) == 0 )
1608
TiXmlAttribute* TiXmlAttributeSet::Find( const char* name )
1610
for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1612
if ( strcmp( node->name.c_str(), name ) == 0 )
1619
#ifdef TIXML_USE_STL
1620
std::istream& operator>> (std::istream & in, TiXmlNode & base)
1623
tag.reserve( 8 * 1000 );
1624
base.StreamIn( &in, &tag );
1626
base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
1632
#ifdef TIXML_USE_STL
1633
std::ostream& operator<< (std::ostream & out, const TiXmlNode & base)
1635
TiXmlPrinter printer;
1636
printer.SetStreamPrinting();
1637
base.Accept( &printer );
1638
out << printer.Str();
1644
std::string& operator<< (std::string& out, const TiXmlNode& base )
1646
TiXmlPrinter printer;
1647
printer.SetStreamPrinting();
1648
base.Accept( &printer );
1649
out.append( printer.Str() );
1656
TiXmlHandle TiXmlHandle::FirstChild() const
1660
TiXmlNode* child = node->FirstChild();
1662
return TiXmlHandle( child );
1664
return TiXmlHandle( 0 );
1668
TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
1672
TiXmlNode* child = node->FirstChild( value );
1674
return TiXmlHandle( child );
1676
return TiXmlHandle( 0 );
1680
TiXmlHandle TiXmlHandle::FirstChildElement() const
1684
TiXmlElement* child = node->FirstChildElement();
1686
return TiXmlHandle( child );
1688
return TiXmlHandle( 0 );
1692
TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
1696
TiXmlElement* child = node->FirstChildElement( value );
1698
return TiXmlHandle( child );
1700
return TiXmlHandle( 0 );
1704
TiXmlHandle TiXmlHandle::Child( int count ) const
1709
TiXmlNode* child = node->FirstChild();
1712
child = child->NextSibling(), ++i )
1717
return TiXmlHandle( child );
1719
return TiXmlHandle( 0 );
1723
TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
1728
TiXmlNode* child = node->FirstChild( value );
1731
child = child->NextSibling( value ), ++i )
1736
return TiXmlHandle( child );
1738
return TiXmlHandle( 0 );
1742
TiXmlHandle TiXmlHandle::ChildElement( int count ) const
1747
TiXmlElement* child = node->FirstChildElement();
1750
child = child->NextSiblingElement(), ++i )
1755
return TiXmlHandle( child );
1757
return TiXmlHandle( 0 );
1761
TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
1766
TiXmlElement* child = node->FirstChildElement( value );
1769
child = child->NextSiblingElement( value ), ++i )
1774
return TiXmlHandle( child );
1776
return TiXmlHandle( 0 );
1780
bool TiXmlPrinter::VisitEnter( const TiXmlDocument& )
1785
bool TiXmlPrinter::VisitExit( const TiXmlDocument& )
1790
bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute )
1794
buffer += element.Value();
1796
for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() )
1799
attrib->Print( 0, 0, &buffer );
1802
if ( !element.FirstChild() )
1810
if ( element.FirstChild()->ToText()
1811
&& element.LastChild() == element.FirstChild()
1812
&& element.FirstChild()->ToText()->CDATA() == false )
1814
simpleTextPrint = true;
1815
// no DoLineBreak()!
1827
bool TiXmlPrinter::VisitExit( const TiXmlElement& element )
1830
if ( !element.FirstChild() )
1836
if ( simpleTextPrint )
1838
simpleTextPrint = false;
1845
buffer += element.Value();
1853
bool TiXmlPrinter::Visit( const TiXmlText& text )
1858
buffer += "<![CDATA[";
1859
buffer += text.Value();
1863
else if ( simpleTextPrint )
1866
TiXmlBase::EncodeString( text.ValueTStr(), &str );
1873
TiXmlBase::EncodeString( text.ValueTStr(), &str );
1881
bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration )
1884
declaration.Print( 0, 0, &buffer );
1890
bool TiXmlPrinter::Visit( const TiXmlComment& comment )
1894
buffer += comment.Value();
1901
bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown )
1905
buffer += unknown.Value();