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();