2
www.sourceforge.net/projects/tinyxml
3
Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
5
This software is provided 'as-is', without any express or implied
6
warranty. In no event will the authors be held liable for any
7
damages arising from the use of this software.
9
Permission is granted to anyone to use this software for any
10
purpose, including commercial applications, and to alter it and
11
redistribute it freely, subject to the following restrictions:
13
1. The origin of this software must not be misrepresented; you must
14
not claim that you wrote the original software. If you use this
15
software in a product, an acknowledgment in the product documentation
16
would be appreciated but is not required.
18
2. Altered source versions must be plainly marked as such, and
19
must not be misrepresented as being the original software.
21
3. This notice may not be removed or altered from any source
35
bool TiXmlBase::condenseWhiteSpace = true;
37
// Microsoft compiler security
38
FILE* TiXmlFOpen( const char* filename, const char* mode )
40
#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
42
errno_t err = fopen_s( &fp, filename, mode );
47
return fopen( filename, mode );
51
void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString )
55
while( i<(int)str.length() )
57
unsigned char c = (unsigned char) str[i];
60
&& i < ( (int)str.length() - 2 )
64
// Hexadecimal character reference.
65
// Pass through unchanged.
66
// © -- copyright symbol, for example.
68
// The -1 is a bug fix from Rob Laveaux. It keeps
69
// an overflow from happening if there is no ';'.
70
// There are actually 2 ways to exit this loop -
71
// while fails (error case) and break (semicolon found).
72
// However, there is no mechanism (currently) for
73
// this function to return an error.
74
while ( i<(int)str.length()-1 )
76
outString->append( str.c_str() + i, 1 );
84
outString->append( entity[0].str, entity[0].strLength );
89
outString->append( entity[1].str, entity[1].strLength );
94
outString->append( entity[2].str, entity[2].strLength );
99
outString->append( entity[3].str, entity[3].strLength );
102
else if ( c == '\'' )
104
outString->append( entity[4].str, entity[4].strLength );
109
// Easy pass at non-alpha/numeric/symbol
110
// Below 32 is symbolic.
113
#if defined(TIXML_SNPRINTF)
114
TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) );
116
sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
119
//*ME: warning C4267: convert 'size_t' to 'int'
120
//*ME: Int-Cast to make compiler happy ...
121
outString->append( buf, (int)strlen( buf ) );
126
//char realc = (char) c;
127
//outString->append( &realc, 1 );
128
*outString += (char) c; // somewhat more efficient function call.
135
TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
146
TiXmlNode::~TiXmlNode()
148
TiXmlNode* node = firstChild;
160
void TiXmlNode::CopyTo( TiXmlNode* target ) const
162
target->SetValue (value.c_str() );
163
target->userData = userData;
167
void TiXmlNode::Clear()
169
TiXmlNode* node = firstChild;
184
TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
186
assert( node->parent == 0 || node->parent == this );
187
assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
189
if ( node->Type() == TiXmlNode::DOCUMENT )
192
if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
198
node->prev = lastChild;
202
lastChild->next = node;
204
firstChild = node; // it was an empty list.
211
TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
213
if ( addThis.Type() == TiXmlNode::DOCUMENT )
215
if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
218
TiXmlNode* node = addThis.Clone();
222
return LinkEndChild( node );
226
TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
228
if ( !beforeThis || beforeThis->parent != this ) {
231
if ( addThis.Type() == TiXmlNode::DOCUMENT )
233
if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
237
TiXmlNode* node = addThis.Clone();
242
node->next = beforeThis;
243
node->prev = beforeThis->prev;
244
if ( beforeThis->prev )
246
beforeThis->prev->next = node;
250
assert( firstChild == beforeThis );
253
beforeThis->prev = node;
258
TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
260
if ( !afterThis || afterThis->parent != this ) {
263
if ( addThis.Type() == TiXmlNode::DOCUMENT )
265
if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
269
TiXmlNode* node = addThis.Clone();
274
node->prev = afterThis;
275
node->next = afterThis->next;
276
if ( afterThis->next )
278
afterThis->next->prev = node;
282
assert( lastChild == afterThis );
285
afterThis->next = node;
290
TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
292
if ( replaceThis->parent != this )
295
TiXmlNode* node = withThis.Clone();
299
node->next = replaceThis->next;
300
node->prev = replaceThis->prev;
302
if ( replaceThis->next )
303
replaceThis->next->prev = node;
307
if ( replaceThis->prev )
308
replaceThis->prev->next = node;
318
bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
320
if ( removeThis->parent != this )
326
if ( removeThis->next )
327
removeThis->next->prev = removeThis->prev;
329
lastChild = removeThis->prev;
331
if ( removeThis->prev )
332
removeThis->prev->next = removeThis->next;
334
firstChild = removeThis->next;
340
const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const
342
const TiXmlNode* node;
343
for ( node = firstChild; node; node = node->next )
345
if ( strcmp( node->Value(), _value ) == 0 )
352
const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
354
const TiXmlNode* node;
355
for ( node = lastChild; node; node = node->prev )
357
if ( strcmp( node->Value(), _value ) == 0 )
364
const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const
372
assert( previous->parent == this );
373
return previous->NextSibling();
378
const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const
382
return FirstChild( val );
386
assert( previous->parent == this );
387
return previous->NextSibling( val );
392
const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const
394
const TiXmlNode* node;
395
for ( node = next; node; node = node->next )
397
if ( strcmp( node->Value(), _value ) == 0 )
404
const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
406
const TiXmlNode* node;
407
for ( node = prev; node; node = node->prev )
409
if ( strcmp( node->Value(), _value ) == 0 )
416
void TiXmlElement::RemoveAttribute( const char * name )
419
TIXML_STRING str( name );
420
TiXmlAttribute* node = attributeSet.Find( str );
422
TiXmlAttribute* node = attributeSet.Find( name );
426
attributeSet.Remove( node );
431
const TiXmlElement* TiXmlNode::FirstChildElement() const
433
const TiXmlNode* node;
435
for ( node = FirstChild();
437
node = node->NextSibling() )
439
if ( node->ToElement() )
440
return node->ToElement();
446
const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
448
const TiXmlNode* node;
450
for ( node = FirstChild( _value );
452
node = node->NextSibling( _value ) )
454
if ( node->ToElement() )
455
return node->ToElement();
461
const TiXmlElement* TiXmlNode::NextSiblingElement() const
463
const TiXmlNode* node;
465
for ( node = NextSibling();
467
node = node->NextSibling() )
469
if ( node->ToElement() )
470
return node->ToElement();
476
const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
478
const TiXmlNode* node;
480
for ( node = NextSibling( _value );
482
node = node->NextSibling( _value ) )
484
if ( node->ToElement() )
485
return node->ToElement();
491
const TiXmlDocument* TiXmlNode::GetDocument() const
493
const TiXmlNode* node;
495
for( node = this; node; node = node->parent )
497
if ( node->ToDocument() )
498
return node->ToDocument();
504
TiXmlElement::TiXmlElement (const char * _value)
505
: TiXmlNode( TiXmlNode::ELEMENT )
507
firstChild = lastChild = 0;
513
TiXmlElement::TiXmlElement( const std::string& _value )
514
: TiXmlNode( TiXmlNode::ELEMENT )
516
firstChild = lastChild = 0;
522
TiXmlElement::TiXmlElement( const TiXmlElement& copy)
523
: TiXmlNode( TiXmlNode::ELEMENT )
525
firstChild = lastChild = 0;
530
void TiXmlElement::operator=( const TiXmlElement& base )
537
TiXmlElement::~TiXmlElement()
543
void TiXmlElement::ClearThis()
546
while( attributeSet.First() )
548
TiXmlAttribute* node = attributeSet.First();
549
attributeSet.Remove( node );
555
const char* TiXmlElement::Attribute( const char* name ) const
557
const TiXmlAttribute* node = attributeSet.Find( name );
559
return node->Value();
565
const std::string* TiXmlElement::Attribute( const std::string& name ) const
567
const TiXmlAttribute* node = attributeSet.Find( name );
569
return &node->ValueStr();
575
const char* TiXmlElement::Attribute( const char* name, int* i ) const
577
const char* s = Attribute( name );
592
const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const
594
const std::string* s = Attribute( name );
598
*i = atoi( s->c_str() );
609
const char* TiXmlElement::Attribute( const char* name, double* d ) const
611
const char* s = Attribute( name );
626
const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const
628
const std::string* s = Attribute( name );
632
*d = atof( s->c_str() );
643
int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
645
const TiXmlAttribute* node = attributeSet.Find( name );
647
return TIXML_NO_ATTRIBUTE;
648
return node->QueryIntValue( ival );
653
int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const
655
const TiXmlAttribute* node = attributeSet.Find( name );
657
return TIXML_NO_ATTRIBUTE;
658
return node->QueryIntValue( ival );
663
int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
665
const TiXmlAttribute* node = attributeSet.Find( name );
667
return TIXML_NO_ATTRIBUTE;
668
return node->QueryDoubleValue( dval );
673
int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const
675
const TiXmlAttribute* node = attributeSet.Find( name );
677
return TIXML_NO_ATTRIBUTE;
678
return node->QueryDoubleValue( dval );
683
void TiXmlElement::SetAttribute( const char * name, int val )
686
#if defined(TIXML_SNPRINTF)
687
TIXML_SNPRINTF( buf, sizeof(buf), "%d", val );
689
sprintf( buf, "%d", val );
691
SetAttribute( name, buf );
696
void TiXmlElement::SetAttribute( const std::string& name, int val )
698
std::ostringstream oss;
700
SetAttribute( name, oss.str() );
705
void TiXmlElement::SetDoubleAttribute( const char * name, double val )
708
#if defined(TIXML_SNPRINTF)
709
TIXML_SNPRINTF( buf, sizeof(buf), "%f", val );
711
sprintf( buf, "%f", val );
713
SetAttribute( name, buf );
717
void TiXmlElement::SetAttribute( const char * cname, const char * cvalue )
720
TIXML_STRING _name( cname );
721
TIXML_STRING _value( cvalue );
723
const char* _name = cname;
724
const char* _value = cvalue;
727
TiXmlAttribute* node = attributeSet.Find( _name );
730
node->SetValue( _value );
734
TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue );
737
attributeSet.Add( attrib );
741
TiXmlDocument* document = GetDocument();
742
if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
748
void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value )
750
TiXmlAttribute* node = attributeSet.Find( name );
753
node->SetValue( _value );
757
TiXmlAttribute* attrib = new TiXmlAttribute( name, _value );
760
attributeSet.Add( attrib );
764
TiXmlDocument* document = GetDocument();
765
if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
771
void TiXmlElement::Print( FILE* cfile, int depth ) const
775
for ( i=0; i<depth; i++ ) {
776
fprintf( cfile, " " );
779
fprintf( cfile, "<%s", value.c_str() );
781
const TiXmlAttribute* attrib;
782
for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
784
fprintf( cfile, " " );
785
attrib->Print( cfile, depth );
788
// There are 3 different formatting approaches:
789
// 1) An element without children is printed as a <foo /> node
790
// 2) An element with only a text child is printed as <foo> text </foo>
791
// 3) An element with children is printed on multiple lines.
795
fprintf( cfile, " />" );
797
else if ( firstChild == lastChild && firstChild->ToText() )
799
fprintf( cfile, ">" );
800
firstChild->Print( cfile, depth + 1 );
801
fprintf( cfile, "</%s>", value.c_str() );
805
fprintf( cfile, ">" );
807
for ( node = firstChild; node; node=node->NextSibling() )
809
if ( !node->ToText() )
811
fprintf( cfile, "\n" );
813
node->Print( cfile, depth+1 );
815
fprintf( cfile, "\n" );
816
for( i=0; i<depth; ++i ) {
817
fprintf( cfile, " " );
819
fprintf( cfile, "</%s>", value.c_str() );
824
void TiXmlElement::CopyTo( TiXmlElement* target ) const
827
TiXmlNode::CopyTo( target );
830
// Clone the attributes, then clone the children.
831
const TiXmlAttribute* attribute = 0;
832
for( attribute = attributeSet.First();
834
attribute = attribute->Next() )
836
target->SetAttribute( attribute->Name(), attribute->Value() );
840
for ( node = firstChild; node; node = node->NextSibling() )
842
target->LinkEndChild( node->Clone() );
846
bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const
848
if ( visitor->VisitEnter( *this, attributeSet.First() ) )
850
for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
852
if ( !node->Accept( visitor ) )
856
return visitor->VisitExit( *this );
860
TiXmlNode* TiXmlElement::Clone() const
862
TiXmlElement* clone = new TiXmlElement( Value() );
871
const char* TiXmlElement::GetText() const
873
const TiXmlNode* child = this->FirstChild();
875
const TiXmlText* childText = child->ToText();
877
return childText->Value();
884
TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
887
useMicrosoftBOM = false;
891
TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
894
useMicrosoftBOM = false;
895
value = documentName;
901
TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
904
useMicrosoftBOM = false;
905
value = documentName;
911
TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT )
917
void TiXmlDocument::operator=( const TiXmlDocument& copy )
924
bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
926
// See STL_STRING_BUG below.
927
//StringToBuffer buf( value );
929
return LoadFile( Value(), encoding );
933
bool TiXmlDocument::SaveFile() const
935
// See STL_STRING_BUG below.
936
// StringToBuffer buf( value );
938
// if ( buf.buffer && SaveFile( buf.buffer ) )
942
return SaveFile( Value() );
945
bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
947
// There was a really terrifying little bug here. The code:
949
// in the STL case, cause the assignment method of the std::string to
950
// be called. What is strange, is that the std::string had the same
951
// address as it's c_str() method, and so bad things happen. Looks
952
// like a bug in the Microsoft STL implementation.
953
// Add an extra string to avoid the crash.
954
TIXML_STRING filename( _filename );
957
// reading in binary mode so that tinyxml can normalize the EOL
958
FILE* file = TiXmlFOpen( value.c_str (), "rb" );
962
bool result = LoadFile( file, encoding );
968
SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
973
bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
977
SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
981
// Delete the existing data:
985
// Get the file size, so we can pre-allocate the string. HUGE speed impact.
987
fseek( file, 0, SEEK_END );
988
length = ftell( file );
989
fseek( file, 0, SEEK_SET );
991
// Strange case, but good to handle up front.
994
SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
998
// If we have a file, assume it is all one big XML file, and read it in.
999
// The document parser may decide the document ends sooner than the entire file, however.
1001
data.reserve( length );
1003
// Subtle bug here. TinyXml did use fgets. But from the XML spec:
1004
// 2.11 End-of-Line Handling
1007
// ...the XML processor MUST behave as if it normalized all line breaks in external
1008
// parsed entities (including the document entity) on input, before parsing, by translating
1009
// both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
1010
// a single #xA character.
1013
// It is not clear fgets does that, and certainly isn't clear it works cross platform.
1014
// Generally, you expect fgets to translate from the convention of the OS to the c/unix
1015
// convention, and not work generally.
1018
while( fgets( buf, sizeof(buf), file ) )
1024
char* buf = new char[ length+1 ];
1027
if ( fread( buf, length, 1, file ) != 1 ) {
1029
SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
1033
const char* lastPos = buf;
1034
const char* p = buf;
1038
assert( p < (buf+length) );
1040
// Newline character. No special rules for this. Append all the characters
1041
// since the last string, and include the newline.
1042
data.append( lastPos, (p-lastPos+1) ); // append, include the newline
1043
++p; // move past the newline
1044
lastPos = p; // and point to the new buffer (may be 0)
1045
assert( p <= (buf+length) );
1047
else if ( *p == 0xd ) {
1048
// Carriage return. Append what we have so far, then
1049
// handle moving forward in the buffer.
1050
if ( (p-lastPos) > 0 ) {
1051
data.append( lastPos, p-lastPos ); // do not add the CR
1053
data += (char)0xa; // a proper newline
1055
if ( *(p+1) == 0xa ) {
1056
// Carriage return - new line sequence
1059
assert( p <= (buf+length) );
1062
// it was followed by something else...that is presumably characters again.
1065
assert( p <= (buf+length) );
1072
// Handle any left over characters.
1074
data.append( lastPos, p-lastPos );
1079
Parse( data.c_str(), 0, encoding );
1088
bool TiXmlDocument::SaveFile( const char * filename ) const
1090
// The old c stuff lives on...
1091
FILE* fp = TiXmlFOpen( filename, "w" );
1094
bool result = SaveFile( fp );
1102
bool TiXmlDocument::SaveFile( FILE* fp ) const
1104
if ( useMicrosoftBOM )
1106
const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
1107
const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
1108
const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
1110
fputc( TIXML_UTF_LEAD_0, fp );
1111
fputc( TIXML_UTF_LEAD_1, fp );
1112
fputc( TIXML_UTF_LEAD_2, fp );
1115
return (ferror(fp) == 0);
1119
void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
1121
TiXmlNode::CopyTo( target );
1123
target->error = error;
1124
target->errorId = errorId;
1125
target->errorDesc = errorDesc;
1126
target->tabsize = tabsize;
1127
target->errorLocation = errorLocation;
1128
target->useMicrosoftBOM = useMicrosoftBOM;
1130
TiXmlNode* node = 0;
1131
for ( node = firstChild; node; node = node->NextSibling() )
1133
target->LinkEndChild( node->Clone() );
1138
TiXmlNode* TiXmlDocument::Clone() const
1140
TiXmlDocument* clone = new TiXmlDocument();
1149
void TiXmlDocument::Print( FILE* cfile, int depth ) const
1152
for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
1154
node->Print( cfile, depth );
1155
fprintf( cfile, "\n" );
1160
bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const
1162
if ( visitor->VisitEnter( *this ) )
1164
for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
1166
if ( !node->Accept( visitor ) )
1170
return visitor->VisitExit( *this );
1174
const TiXmlAttribute* TiXmlAttribute::Next() const
1176
// We are using knowledge of the sentinel. The sentinel
1177
// have a value or name.
1178
if ( next->value.empty() && next->name.empty() )
1184
TiXmlAttribute* TiXmlAttribute::Next()
1186
// We are using knowledge of the sentinel. The sentinel
1187
// have a value or name.
1188
if ( next->value.empty() && next->name.empty() )
1194
const TiXmlAttribute* TiXmlAttribute::Previous() const
1196
// We are using knowledge of the sentinel. The sentinel
1197
// have a value or name.
1198
if ( prev->value.empty() && prev->name.empty() )
1204
TiXmlAttribute* TiXmlAttribute::Previous()
1206
// We are using knowledge of the sentinel. The sentinel
1207
// have a value or name.
1208
if ( prev->value.empty() && prev->name.empty() )
1214
void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
1218
EncodeString( name, &n );
1219
EncodeString( value, &v );
1221
if (value.find ('\"') == TIXML_STRING::npos) {
1223
fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
1226
(*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\"";
1231
fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
1234
(*str) += n; (*str) += "='"; (*str) += v; (*str) += "'";
1240
int TiXmlAttribute::QueryIntValue( int* ival ) const
1242
if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 )
1243
return TIXML_SUCCESS;
1244
return TIXML_WRONG_TYPE;
1247
int TiXmlAttribute::QueryDoubleValue( double* dval ) const
1249
if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 )
1250
return TIXML_SUCCESS;
1251
return TIXML_WRONG_TYPE;
1254
void TiXmlAttribute::SetIntValue( int _value )
1257
#if defined(TIXML_SNPRINTF)
1258
TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
1260
sprintf (buf, "%d", _value);
1265
void TiXmlAttribute::SetDoubleValue( double _value )
1268
#if defined(TIXML_SNPRINTF)
1269
TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value);
1271
sprintf (buf, "%lf", _value);
1276
int TiXmlAttribute::IntValue() const
1278
return atoi (value.c_str ());
1281
double TiXmlAttribute::DoubleValue() const
1283
return atof (value.c_str ());
1287
TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT )
1289
copy.CopyTo( this );
1293
void TiXmlComment::operator=( const TiXmlComment& base )
1296
base.CopyTo( this );
1300
void TiXmlComment::Print( FILE* cfile, int depth ) const
1303
for ( int i=0; i<depth; i++ )
1305
fprintf( cfile, " " );
1307
fprintf( cfile, "<!--%s-->", value.c_str() );
1311
void TiXmlComment::CopyTo( TiXmlComment* target ) const
1313
TiXmlNode::CopyTo( target );
1317
bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const
1319
return visitor->Visit( *this );
1323
TiXmlNode* TiXmlComment::Clone() const
1325
TiXmlComment* clone = new TiXmlComment();
1335
void TiXmlText::Print( FILE* cfile, int depth ) const
1341
fprintf( cfile, "\n" );
1342
for ( i=0; i<depth; i++ ) {
1343
fprintf( cfile, " " );
1345
fprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() ); // unformatted output
1349
TIXML_STRING buffer;
1350
EncodeString( value, &buffer );
1351
fprintf( cfile, "%s", buffer.c_str() );
1356
void TiXmlText::CopyTo( TiXmlText* target ) const
1358
TiXmlNode::CopyTo( target );
1359
target->cdata = cdata;
1363
bool TiXmlText::Accept( TiXmlVisitor* visitor ) const
1365
return visitor->Visit( *this );
1369
TiXmlNode* TiXmlText::Clone() const
1371
TiXmlText* clone = 0;
1372
clone = new TiXmlText( "" );
1382
TiXmlDeclaration::TiXmlDeclaration( const char * _version,
1383
const char * _encoding,
1384
const char * _standalone )
1385
: TiXmlNode( TiXmlNode::DECLARATION )
1388
encoding = _encoding;
1389
standalone = _standalone;
1393
#ifdef TIXML_USE_STL
1394
TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
1395
const std::string& _encoding,
1396
const std::string& _standalone )
1397
: TiXmlNode( TiXmlNode::DECLARATION )
1400
encoding = _encoding;
1401
standalone = _standalone;
1406
TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
1407
: TiXmlNode( TiXmlNode::DECLARATION )
1409
copy.CopyTo( this );
1413
void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
1416
copy.CopyTo( this );
1420
void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
1422
if ( cfile ) fprintf( cfile, "<?xml " );
1423
if ( str ) (*str) += "<?xml ";
1425
if ( !version.empty() ) {
1426
if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ());
1427
if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; }
1429
if ( !encoding.empty() ) {
1430
if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
1431
if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; }
1433
if ( !standalone.empty() ) {
1434
if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
1435
if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; }
1437
if ( cfile ) fprintf( cfile, "?>" );
1438
if ( str ) (*str) += "?>";
1442
void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
1444
TiXmlNode::CopyTo( target );
1446
target->version = version;
1447
target->encoding = encoding;
1448
target->standalone = standalone;
1452
bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const
1454
return visitor->Visit( *this );
1458
TiXmlNode* TiXmlDeclaration::Clone() const
1460
TiXmlDeclaration* clone = new TiXmlDeclaration();
1470
void TiXmlUnknown::Print( FILE* cfile, int depth ) const
1472
for ( int i=0; i<depth; i++ )
1473
fprintf( cfile, " " );
1474
fprintf( cfile, "<%s>", value.c_str() );
1478
void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
1480
TiXmlNode::CopyTo( target );
1484
bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const
1486
return visitor->Visit( *this );
1490
TiXmlNode* TiXmlUnknown::Clone() const
1492
TiXmlUnknown* clone = new TiXmlUnknown();
1502
TiXmlAttributeSet::TiXmlAttributeSet()
1504
sentinel.next = &sentinel;
1505
sentinel.prev = &sentinel;
1509
TiXmlAttributeSet::~TiXmlAttributeSet()
1511
assert( sentinel.next == &sentinel );
1512
assert( sentinel.prev == &sentinel );
1516
void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
1518
#ifdef TIXML_USE_STL
1519
assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set.
1521
assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set.
1524
addMe->next = &sentinel;
1525
addMe->prev = sentinel.prev;
1527
sentinel.prev->next = addMe;
1528
sentinel.prev = addMe;
1531
void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
1533
TiXmlAttribute* node;
1535
for( node = sentinel.next; node != &sentinel; node = node->next )
1537
if ( node == removeMe )
1539
node->prev->next = node->next;
1540
node->next->prev = node->prev;
1546
assert( 0 ); // we tried to remove a non-linked attribute.
1550
#ifdef TIXML_USE_STL
1551
const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
1553
for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1555
if ( node->name == name )
1562
TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name )
1564
for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1566
if ( node->name == name )
1575
const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const
1577
for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1579
if ( strcmp( node->name.c_str(), name ) == 0 )
1586
TiXmlAttribute* TiXmlAttributeSet::Find( const char* name )
1588
for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1590
if ( strcmp( node->name.c_str(), name ) == 0 )
1597
#ifdef TIXML_USE_STL
1598
std::istream& operator>> (std::istream & in, TiXmlNode & base)
1601
tag.reserve( 8 * 1000 );
1602
base.StreamIn( &in, &tag );
1604
base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
1610
#ifdef TIXML_USE_STL
1611
std::ostream& operator<< (std::ostream & out, const TiXmlNode & base)
1613
TiXmlPrinter printer;
1614
printer.SetStreamPrinting();
1615
base.Accept( &printer );
1616
out << printer.Str();
1622
std::string& operator<< (std::string& out, const TiXmlNode& base )
1624
TiXmlPrinter printer;
1625
printer.SetStreamPrinting();
1626
base.Accept( &printer );
1627
out.append( printer.Str() );
1634
TiXmlHandle TiXmlHandle::FirstChild() const
1638
TiXmlNode* child = node->FirstChild();
1640
return TiXmlHandle( child );
1642
return TiXmlHandle( 0 );
1646
TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
1650
TiXmlNode* child = node->FirstChild( value );
1652
return TiXmlHandle( child );
1654
return TiXmlHandle( 0 );
1658
TiXmlHandle TiXmlHandle::FirstChildElement() const
1662
TiXmlElement* child = node->FirstChildElement();
1664
return TiXmlHandle( child );
1666
return TiXmlHandle( 0 );
1670
TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
1674
TiXmlElement* child = node->FirstChildElement( value );
1676
return TiXmlHandle( child );
1678
return TiXmlHandle( 0 );
1682
TiXmlHandle TiXmlHandle::Child( int count ) const
1687
TiXmlNode* child = node->FirstChild();
1690
child = child->NextSibling(), ++i )
1695
return TiXmlHandle( child );
1697
return TiXmlHandle( 0 );
1701
TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
1706
TiXmlNode* child = node->FirstChild( value );
1709
child = child->NextSibling( value ), ++i )
1714
return TiXmlHandle( child );
1716
return TiXmlHandle( 0 );
1720
TiXmlHandle TiXmlHandle::ChildElement( int count ) const
1725
TiXmlElement* child = node->FirstChildElement();
1728
child = child->NextSiblingElement(), ++i )
1733
return TiXmlHandle( child );
1735
return TiXmlHandle( 0 );
1739
TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
1744
TiXmlElement* child = node->FirstChildElement( value );
1747
child = child->NextSiblingElement( value ), ++i )
1752
return TiXmlHandle( child );
1754
return TiXmlHandle( 0 );
1758
bool TiXmlPrinter::VisitEnter( const TiXmlDocument& )
1763
bool TiXmlPrinter::VisitExit( const TiXmlDocument& )
1768
bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute )
1772
buffer += element.Value();
1774
for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() )
1777
attrib->Print( 0, 0, &buffer );
1780
if ( !element.FirstChild() )
1788
if ( element.FirstChild()->ToText()
1789
&& element.LastChild() == element.FirstChild()
1790
&& element.FirstChild()->ToText()->CDATA() == false )
1792
simpleTextPrint = true;
1793
// no DoLineBreak()!
1805
bool TiXmlPrinter::VisitExit( const TiXmlElement& element )
1808
if ( !element.FirstChild() )
1814
if ( simpleTextPrint )
1816
simpleTextPrint = false;
1823
buffer += element.Value();
1831
bool TiXmlPrinter::Visit( const TiXmlText& text )
1836
buffer += "<![CDATA[";
1837
buffer += text.Value();
1841
else if ( simpleTextPrint )
1844
TiXmlBase::EncodeString( text.ValueTStr(), &str );
1851
TiXmlBase::EncodeString( text.ValueTStr(), &str );
1859
bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration )
1862
declaration.Print( 0, 0, &buffer );
1868
bool TiXmlPrinter::Visit( const TiXmlComment& comment )
1872
buffer += comment.Value();
1879
bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown )
1883
buffer += unknown.Value();