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
34 FILE* TiXmlFOpen( const char* filename, const char* mode );
36 bool TiXmlBase::condenseWhiteSpace = true;
38 // Microsoft compiler security
39 FILE* TiXmlFOpen( const char* filename, const char* mode )
41 #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
43 errno_t err = fopen_s( &fp, filename, mode );
48 return fopen( filename, mode );
52 void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString )
56 while( i<(int)str.length() )
58 unsigned char c = (unsigned char) str[i];
61 && i < ( (int)str.length() - 2 )
65 // Hexadecimal character reference.
66 // Pass through unchanged.
67 // © -- copyright symbol, for example.
69 // The -1 is a bug fix from Rob Laveaux. It keeps
70 // an overflow from happening if there is no ';'.
71 // There are actually 2 ways to exit this loop -
72 // while fails (error case) and break (semicolon found).
73 // However, there is no mechanism (currently) for
74 // this function to return an error.
75 while ( i<(int)str.length()-1 )
77 outString->append( str.c_str() + i, 1 );
85 outString->append( entity[0].str, entity[0].strLength );
90 outString->append( entity[1].str, entity[1].strLength );
95 outString->append( entity[2].str, entity[2].strLength );
100 outString->append( entity[3].str, entity[3].strLength );
103 else if ( c == '\'' )
105 outString->append( entity[4].str, entity[4].strLength );
110 // Easy pass at non-alpha/numeric/symbol
111 // Below 32 is symbolic.
114 #if defined(TIXML_SNPRINTF)
115 TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) );
117 sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
120 //*ME: warning C4267: convert 'size_t' to 'int'
121 //*ME: Int-Cast to make compiler happy ...
122 outString->append( buf, (int)strlen( buf ) );
127 //char realc = (char) c;
128 //outString->append( &realc, 1 );
129 *outString += (char) c; // somewhat more efficient function call.
136 TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
147 TiXmlNode::~TiXmlNode()
149 TiXmlNode* node = firstChild;
161 void TiXmlNode::CopyTo( TiXmlNode* target ) const
163 target->SetValue (value.c_str() );
164 target->userData = userData;
165 target->location = location;
169 void TiXmlNode::Clear()
171 TiXmlNode* node = firstChild;
186 TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
188 assert( node->parent == 0 || node->parent == this );
189 assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
191 if ( node->Type() == TiXmlNode::TINYXML_DOCUMENT )
194 if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
200 node->prev = lastChild;
204 lastChild->next = node;
206 firstChild = node; // it was an empty list.
213 TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
215 if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
217 if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
220 TiXmlNode* node = addThis.Clone();
224 return LinkEndChild( node );
228 TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
230 if ( !beforeThis || beforeThis->parent != this ) {
233 if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
235 if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
239 TiXmlNode* node = addThis.Clone();
244 node->next = beforeThis;
245 node->prev = beforeThis->prev;
246 if ( beforeThis->prev )
248 beforeThis->prev->next = node;
252 assert( firstChild == beforeThis );
255 beforeThis->prev = node;
260 TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
262 if ( !afterThis || afterThis->parent != this ) {
265 if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
267 if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
271 TiXmlNode* node = addThis.Clone();
276 node->prev = afterThis;
277 node->next = afterThis->next;
278 if ( afterThis->next )
280 afterThis->next->prev = node;
284 assert( lastChild == afterThis );
287 afterThis->next = node;
292 TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
297 if ( replaceThis->parent != this )
300 if ( withThis.ToDocument() ) {
301 // A document can never be a child. Thanks to Noam.
302 TiXmlDocument* document = GetDocument();
304 document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
308 TiXmlNode* node = withThis.Clone();
312 node->next = replaceThis->next;
313 node->prev = replaceThis->prev;
315 if ( replaceThis->next )
316 replaceThis->next->prev = node;
320 if ( replaceThis->prev )
321 replaceThis->prev->next = node;
331 bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
337 if ( removeThis->parent != this )
343 if ( removeThis->next )
344 removeThis->next->prev = removeThis->prev;
346 lastChild = removeThis->prev;
348 if ( removeThis->prev )
349 removeThis->prev->next = removeThis->next;
351 firstChild = removeThis->next;
357 const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const
359 const TiXmlNode* node;
360 for ( node = firstChild; node; node = node->next )
362 if ( strcmp( node->Value(), _value ) == 0 )
369 const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
371 const TiXmlNode* node;
372 for ( node = lastChild; node; node = node->prev )
374 if ( strcmp( node->Value(), _value ) == 0 )
381 const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const
389 assert( previous->parent == this );
390 return previous->NextSibling();
395 const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const
399 return FirstChild( val );
403 assert( previous->parent == this );
404 return previous->NextSibling( val );
409 const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const
411 const TiXmlNode* node;
412 for ( node = next; node; node = node->next )
414 if ( strcmp( node->Value(), _value ) == 0 )
421 const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
423 const TiXmlNode* node;
424 for ( node = prev; node; node = node->prev )
426 if ( strcmp( node->Value(), _value ) == 0 )
433 void TiXmlElement::RemoveAttribute( const char * name )
436 TIXML_STRING str( name );
437 TiXmlAttribute* node = attributeSet.Find( str );
439 TiXmlAttribute* node = attributeSet.Find( name );
443 attributeSet.Remove( node );
448 const TiXmlElement* TiXmlNode::FirstChildElement() const
450 const TiXmlNode* node;
452 for ( node = FirstChild();
454 node = node->NextSibling() )
456 if ( node->ToElement() )
457 return node->ToElement();
463 const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
465 const TiXmlNode* node;
467 for ( node = FirstChild( _value );
469 node = node->NextSibling( _value ) )
471 if ( node->ToElement() )
472 return node->ToElement();
478 const TiXmlElement* TiXmlNode::NextSiblingElement() const
480 const TiXmlNode* node;
482 for ( node = NextSibling();
484 node = node->NextSibling() )
486 if ( node->ToElement() )
487 return node->ToElement();
493 const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
495 const TiXmlNode* node;
497 for ( node = NextSibling( _value );
499 node = node->NextSibling( _value ) )
501 if ( node->ToElement() )
502 return node->ToElement();
508 const TiXmlDocument* TiXmlNode::GetDocument() const
510 const TiXmlNode* node;
512 for( node = this; node; node = node->parent )
514 if ( node->ToDocument() )
515 return node->ToDocument();
521 TiXmlElement::TiXmlElement (const char * _value)
522 : TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
524 firstChild = lastChild = 0;
530 TiXmlElement::TiXmlElement( const std::string& _value )
531 : TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
533 firstChild = lastChild = 0;
539 TiXmlElement::TiXmlElement( const TiXmlElement& copy)
540 : TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
542 firstChild = lastChild = 0;
547 void TiXmlElement::operator=( const TiXmlElement& base )
554 TiXmlElement::~TiXmlElement()
560 void TiXmlElement::ClearThis()
563 while( attributeSet.First() )
565 TiXmlAttribute* node = attributeSet.First();
566 attributeSet.Remove( node );
572 const char* TiXmlElement::Attribute( const char* name ) const
574 const TiXmlAttribute* node = attributeSet.Find( name );
576 return node->Value();
582 const std::string* TiXmlElement::Attribute( const std::string& name ) const
584 const TiXmlAttribute* attrib = attributeSet.Find( name );
586 return &attrib->ValueStr();
592 const char* TiXmlElement::Attribute( const char* name, int* i ) const
594 const TiXmlAttribute* attrib = attributeSet.Find( name );
595 const char* result = 0;
598 result = attrib->Value();
600 attrib->QueryIntValue( i );
608 const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const
610 const TiXmlAttribute* attrib = attributeSet.Find( name );
611 const std::string* result = 0;
614 result = &attrib->ValueStr();
616 attrib->QueryIntValue( i );
624 const char* TiXmlElement::Attribute( const char* name, double* d ) const
626 const TiXmlAttribute* attrib = attributeSet.Find( name );
627 const char* result = 0;
630 result = attrib->Value();
632 attrib->QueryDoubleValue( d );
640 const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const
642 const TiXmlAttribute* attrib = attributeSet.Find( name );
643 const std::string* result = 0;
646 result = &attrib->ValueStr();
648 attrib->QueryDoubleValue( d );
656 int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
658 const TiXmlAttribute* attrib = attributeSet.Find( name );
660 return TIXML_NO_ATTRIBUTE;
661 return attrib->QueryIntValue( ival );
666 int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const
668 const TiXmlAttribute* attrib = attributeSet.Find( name );
670 return TIXML_NO_ATTRIBUTE;
671 return attrib->QueryIntValue( ival );
676 int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
678 const TiXmlAttribute* attrib = attributeSet.Find( name );
680 return TIXML_NO_ATTRIBUTE;
681 return attrib->QueryDoubleValue( dval );
686 int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const
688 const TiXmlAttribute* attrib = attributeSet.Find( name );
690 return TIXML_NO_ATTRIBUTE;
691 return attrib->QueryDoubleValue( dval );
696 void TiXmlElement::SetAttribute( const char * name, int val )
698 TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
700 attrib->SetIntValue( val );
706 void TiXmlElement::SetAttribute( const std::string& name, int val )
708 TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
710 attrib->SetIntValue( val );
716 void TiXmlElement::SetDoubleAttribute( const char * name, double val )
718 TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
720 attrib->SetDoubleValue( val );
726 void TiXmlElement::SetDoubleAttribute( const std::string& name, double val )
728 TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
730 attrib->SetDoubleValue( val );
736 void TiXmlElement::SetAttribute( const char * cname, const char * cvalue )
738 TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname );
740 attrib->SetValue( cvalue );
746 void TiXmlElement::SetAttribute( const std::string& _name, const std::string& _value )
748 TiXmlAttribute* attrib = attributeSet.FindOrCreate( _name );
750 attrib->SetValue( _value );
756 void TiXmlElement::Print( FILE* cfile, int depth ) const
760 for ( i=0; i<depth; i++ ) {
761 fprintf( cfile, " " );
764 fprintf( cfile, "<%s", value.c_str() );
766 const TiXmlAttribute* attrib;
767 for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
769 fprintf( cfile, " " );
770 attrib->Print( cfile, depth );
773 // There are 3 different formatting approaches:
774 // 1) An element without children is printed as a <foo /> node
775 // 2) An element with only a text child is printed as <foo> text </foo>
776 // 3) An element with children is printed on multiple lines.
780 fprintf( cfile, " />" );
782 else if ( firstChild == lastChild && firstChild->ToText() )
784 fprintf( cfile, ">" );
785 firstChild->Print( cfile, depth + 1 );
786 fprintf( cfile, "</%s>", value.c_str() );
790 fprintf( cfile, ">" );
792 for ( node = firstChild; node; node=node->NextSibling() )
794 if ( !node->ToText() )
796 fprintf( cfile, "\n" );
798 node->Print( cfile, depth+1 );
800 fprintf( cfile, "\n" );
801 for( i=0; i<depth; ++i ) {
802 fprintf( cfile, " " );
804 fprintf( cfile, "</%s>", value.c_str() );
809 void TiXmlElement::CopyTo( TiXmlElement* target ) const
812 TiXmlNode::CopyTo( target );
815 // Clone the attributes, then clone the children.
816 const TiXmlAttribute* attribute = 0;
817 for( attribute = attributeSet.First();
819 attribute = attribute->Next() )
821 target->SetAttribute( attribute->Name(), attribute->Value() );
825 for ( node = firstChild; node; node = node->NextSibling() )
827 target->LinkEndChild( node->Clone() );
831 bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const
833 if ( visitor->VisitEnter( *this, attributeSet.First() ) )
835 for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
837 if ( !node->Accept( visitor ) )
841 return visitor->VisitExit( *this );
845 TiXmlNode* TiXmlElement::Clone() const
847 TiXmlElement* clone = new TiXmlElement( Value() );
856 const char* TiXmlElement::GetText() const
858 const TiXmlNode* child = this->FirstChild();
860 const TiXmlText* childText = child->ToText();
862 return childText->Value();
869 TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
872 useMicrosoftBOM = false;
876 TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
879 useMicrosoftBOM = false;
880 value = documentName;
886 TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
889 useMicrosoftBOM = false;
890 value = documentName;
896 TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
902 void TiXmlDocument::operator=( const TiXmlDocument& copy )
909 bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
911 return LoadFile( Value(), encoding );
915 bool TiXmlDocument::SaveFile() const
917 return SaveFile( Value() );
920 bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
922 TIXML_STRING filename( _filename );
925 // reading in binary mode so that tinyxml can normalize the EOL
926 FILE* file = TiXmlFOpen( value.c_str (), "rb" );
930 bool result = LoadFile( file, encoding );
936 SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
941 bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
945 SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
949 // Delete the existing data:
953 // Get the file size, so we can pre-allocate the string. HUGE speed impact.
955 fseek( file, 0, SEEK_END );
956 length = ftell( file );
957 fseek( file, 0, SEEK_SET );
959 // Strange case, but good to handle up front.
962 SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
966 // Subtle bug here. TinyXml did use fgets. But from the XML spec:
967 // 2.11 End-of-Line Handling
970 // ...the XML processor MUST behave as if it normalized all line breaks in external
971 // parsed entities (including the document entity) on input, before parsing, by translating
972 // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
973 // a single #xA character.
976 // It is not clear fgets does that, and certainly isn't clear it works cross platform.
977 // Generally, you expect fgets to translate from the convention of the OS to the c/unix
978 // convention, and not work generally.
981 while( fgets( buf, sizeof(buf), file ) )
987 char* buf = new char[ length+1 ];
990 if ( fread( buf, length, 1, file ) != 1 ) {
992 SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
996 // Process the buffer in place to normalize new lines. (See comment above.)
997 // Copies from the 'p' to 'q' pointer, where p can advance faster if
998 // a newline-carriage return is hit.
1001 // Systems based on ASCII or a compatible character set use either LF (Line feed, '\n', 0x0A, 10 in decimal) or
1002 // CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)...
1003 // * LF: Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others
1004 // * CR+LF: DEC RT-11 and most other early non-Unix, non-IBM OSes, CP/M, MP/M, DOS, OS/2, Microsoft Windows, Symbian OS
1005 // * CR: Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9
1007 const char* p = buf; // the read head
1008 char* q = buf; // the write head
1009 const char CR = 0x0d;
1010 const char LF = 0x0a;
1014 assert( p < (buf+length) );
1015 assert( q <= (buf+length) );
1021 if ( *p == LF ) { // check for CR+LF (and skip LF)
1029 assert( q <= (buf+length) );
1032 Parse( buf, 0, encoding );
1039 bool TiXmlDocument::SaveFile( const char * filename ) const
1041 // The old c stuff lives on...
1042 FILE* fp = TiXmlFOpen( filename, "w" );
1045 bool result = SaveFile( fp );
1053 bool TiXmlDocument::SaveFile( FILE* fp ) const
1055 if ( useMicrosoftBOM )
1057 const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
1058 const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
1059 const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
1061 fputc( TIXML_UTF_LEAD_0, fp );
1062 fputc( TIXML_UTF_LEAD_1, fp );
1063 fputc( TIXML_UTF_LEAD_2, fp );
1066 return (ferror(fp) == 0);
1070 void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
1072 TiXmlNode::CopyTo( target );
1074 target->error = error;
1075 target->errorId = errorId;
1076 target->errorDesc = errorDesc;
1077 target->tabsize = tabsize;
1078 target->errorLocation = errorLocation;
1079 target->useMicrosoftBOM = useMicrosoftBOM;
1081 TiXmlNode* node = 0;
1082 for ( node = firstChild; node; node = node->NextSibling() )
1084 target->LinkEndChild( node->Clone() );
1089 TiXmlNode* TiXmlDocument::Clone() const
1091 TiXmlDocument* clone = new TiXmlDocument();
1100 void TiXmlDocument::Print( FILE* cfile, int depth ) const
1103 for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
1105 node->Print( cfile, depth );
1106 fprintf( cfile, "\n" );
1111 bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const
1113 if ( visitor->VisitEnter( *this ) )
1115 for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
1117 if ( !node->Accept( visitor ) )
1121 return visitor->VisitExit( *this );
1125 const TiXmlAttribute* TiXmlAttribute::Next() const
1127 // We are using knowledge of the sentinel. The sentinel
1128 // have a value or name.
1129 if ( next->value.empty() && next->name.empty() )
1135 TiXmlAttribute* TiXmlAttribute::Next()
1137 // We are using knowledge of the sentinel. The sentinel
1138 // have a value or name.
1139 if ( next->value.empty() && next->name.empty() )
1145 const TiXmlAttribute* TiXmlAttribute::Previous() const
1147 // We are using knowledge of the sentinel. The sentinel
1148 // have a value or name.
1149 if ( prev->value.empty() && prev->name.empty() )
1155 TiXmlAttribute* TiXmlAttribute::Previous()
1157 // We are using knowledge of the sentinel. The sentinel
1158 // have a value or name.
1159 if ( prev->value.empty() && prev->name.empty() )
1165 void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
1169 EncodeString( name, &n );
1170 EncodeString( value, &v );
1172 if (value.find ('\"') == TIXML_STRING::npos) {
1174 fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
1177 (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\"";
1182 fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
1185 (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'";
1191 int TiXmlAttribute::QueryIntValue( int* ival ) const
1193 if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 )
1194 return TIXML_SUCCESS;
1195 return TIXML_WRONG_TYPE;
1198 int TiXmlAttribute::QueryDoubleValue( double* dval ) const
1200 if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 )
1201 return TIXML_SUCCESS;
1202 return TIXML_WRONG_TYPE;
1205 void TiXmlAttribute::SetIntValue( int _value )
1208 #if defined(TIXML_SNPRINTF)
1209 TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
1211 sprintf (buf, "%d", _value);
1216 void TiXmlAttribute::SetDoubleValue( double _value )
1219 #if defined(TIXML_SNPRINTF)
1220 TIXML_SNPRINTF( buf, sizeof(buf), "%g", _value);
1222 sprintf (buf, "%g", _value);
1227 int TiXmlAttribute::IntValue() const
1229 return atoi (value.c_str ());
1232 double TiXmlAttribute::DoubleValue() const
1234 return atof (value.c_str ());
1238 TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT )
1240 copy.CopyTo( this );
1244 void TiXmlComment::operator=( const TiXmlComment& base )
1247 base.CopyTo( this );
1251 void TiXmlComment::Print( FILE* cfile, int depth ) const
1254 for ( int i=0; i<depth; i++ )
1256 fprintf( cfile, " " );
1258 fprintf( cfile, "<!--%s-->", value.c_str() );
1262 void TiXmlComment::CopyTo( TiXmlComment* target ) const
1264 TiXmlNode::CopyTo( target );
1268 bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const
1270 return visitor->Visit( *this );
1274 TiXmlNode* TiXmlComment::Clone() const
1276 TiXmlComment* clone = new TiXmlComment();
1286 void TiXmlText::Print( FILE* cfile, int depth ) const
1292 fprintf( cfile, "\n" );
1293 for ( i=0; i<depth; i++ ) {
1294 fprintf( cfile, " " );
1296 fprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() ); // unformatted output
1300 TIXML_STRING buffer;
1301 EncodeString( value, &buffer );
1302 fprintf( cfile, "%s", buffer.c_str() );
1307 void TiXmlText::CopyTo( TiXmlText* target ) const
1309 TiXmlNode::CopyTo( target );
1310 target->cdata = cdata;
1314 bool TiXmlText::Accept( TiXmlVisitor* visitor ) const
1316 return visitor->Visit( *this );
1320 TiXmlNode* TiXmlText::Clone() const
1322 TiXmlText* clone = 0;
1323 clone = new TiXmlText( "" );
1333 TiXmlDeclaration::TiXmlDeclaration( const char * _version,
1334 const char * _encoding,
1335 const char * _standalone )
1336 : TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
1339 encoding = _encoding;
1340 standalone = _standalone;
1344 #ifdef TIXML_USE_STL
1345 TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
1346 const std::string& _encoding,
1347 const std::string& _standalone )
1348 : TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
1351 encoding = _encoding;
1352 standalone = _standalone;
1357 TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
1358 : TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
1360 copy.CopyTo( this );
1364 void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
1367 copy.CopyTo( this );
1371 void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
1373 if ( cfile ) fprintf( cfile, "<?xml " );
1374 if ( str ) (*str) += "<?xml ";
1376 if ( !version.empty() ) {
1377 if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ());
1378 if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; }
1380 if ( !encoding.empty() ) {
1381 if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
1382 if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; }
1384 if ( !standalone.empty() ) {
1385 if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
1386 if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; }
1388 if ( cfile ) fprintf( cfile, "?>" );
1389 if ( str ) (*str) += "?>";
1393 void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
1395 TiXmlNode::CopyTo( target );
1397 target->version = version;
1398 target->encoding = encoding;
1399 target->standalone = standalone;
1403 bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const
1405 return visitor->Visit( *this );
1409 TiXmlNode* TiXmlDeclaration::Clone() const
1411 TiXmlDeclaration* clone = new TiXmlDeclaration();
1421 void TiXmlUnknown::Print( FILE* cfile, int depth ) const
1423 for ( int i=0; i<depth; i++ )
1424 fprintf( cfile, " " );
1425 fprintf( cfile, "<%s>", value.c_str() );
1429 void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
1431 TiXmlNode::CopyTo( target );
1435 bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const
1437 return visitor->Visit( *this );
1441 TiXmlNode* TiXmlUnknown::Clone() const
1443 TiXmlUnknown* clone = new TiXmlUnknown();
1453 TiXmlAttributeSet::TiXmlAttributeSet()
1455 sentinel.next = &sentinel;
1456 sentinel.prev = &sentinel;
1460 TiXmlAttributeSet::~TiXmlAttributeSet()
1462 assert( sentinel.next == &sentinel );
1463 assert( sentinel.prev == &sentinel );
1467 void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
1469 #ifdef TIXML_USE_STL
1470 assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set.
1472 assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set.
1475 addMe->next = &sentinel;
1476 addMe->prev = sentinel.prev;
1478 sentinel.prev->next = addMe;
1479 sentinel.prev = addMe;
1482 void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
1484 TiXmlAttribute* node;
1486 for( node = sentinel.next; node != &sentinel; node = node->next )
1488 if ( node == removeMe )
1490 node->prev->next = node->next;
1491 node->next->prev = node->prev;
1497 assert( 0 ); // we tried to remove a non-linked attribute.
1501 #ifdef TIXML_USE_STL
1502 TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
1504 for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1506 if ( node->name == name )
1512 TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const std::string& _name )
1514 TiXmlAttribute* attrib = Find( _name );
1516 attrib = new TiXmlAttribute();
1518 attrib->SetName( _name );
1525 TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const
1527 for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1529 if ( strcmp( node->name.c_str(), name ) == 0 )
1536 TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name )
1538 TiXmlAttribute* attrib = Find( _name );
1540 attrib = new TiXmlAttribute();
1542 attrib->SetName( _name );
1548 #ifdef TIXML_USE_STL
1549 std::istream& operator>> (std::istream & in, TiXmlNode & base)
1552 tag.reserve( 8 * 1000 );
1553 base.StreamIn( &in, &tag );
1555 base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
1561 #ifdef TIXML_USE_STL
1562 std::ostream& operator<< (std::ostream & out, const TiXmlNode & base)
1564 TiXmlPrinter printer;
1565 printer.SetStreamPrinting();
1566 base.Accept( &printer );
1567 out << printer.Str();
1573 std::string& operator<< (std::string& out, const TiXmlNode& base )
1575 TiXmlPrinter printer;
1576 printer.SetStreamPrinting();
1577 base.Accept( &printer );
1578 out.append( printer.Str() );
1585 TiXmlHandle TiXmlHandle::FirstChild() const
1589 TiXmlNode* child = node->FirstChild();
1591 return TiXmlHandle( child );
1593 return TiXmlHandle( 0 );
1597 TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
1601 TiXmlNode* child = node->FirstChild( value );
1603 return TiXmlHandle( child );
1605 return TiXmlHandle( 0 );
1609 TiXmlHandle TiXmlHandle::FirstChildElement() const
1613 TiXmlElement* child = node->FirstChildElement();
1615 return TiXmlHandle( child );
1617 return TiXmlHandle( 0 );
1621 TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
1625 TiXmlElement* child = node->FirstChildElement( value );
1627 return TiXmlHandle( child );
1629 return TiXmlHandle( 0 );
1633 TiXmlHandle TiXmlHandle::Child( int count ) const
1638 TiXmlNode* child = node->FirstChild();
1641 child = child->NextSibling(), ++i )
1646 return TiXmlHandle( child );
1648 return TiXmlHandle( 0 );
1652 TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
1657 TiXmlNode* child = node->FirstChild( value );
1660 child = child->NextSibling( value ), ++i )
1665 return TiXmlHandle( child );
1667 return TiXmlHandle( 0 );
1671 TiXmlHandle TiXmlHandle::ChildElement( int count ) const
1676 TiXmlElement* child = node->FirstChildElement();
1679 child = child->NextSiblingElement(), ++i )
1684 return TiXmlHandle( child );
1686 return TiXmlHandle( 0 );
1690 TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
1695 TiXmlElement* child = node->FirstChildElement( value );
1698 child = child->NextSiblingElement( value ), ++i )
1703 return TiXmlHandle( child );
1705 return TiXmlHandle( 0 );
1709 bool TiXmlPrinter::VisitEnter( const TiXmlDocument& )
1714 bool TiXmlPrinter::VisitExit( const TiXmlDocument& )
1719 bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute )
1723 buffer += element.Value();
1725 for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() )
1728 attrib->Print( 0, 0, &buffer );
1731 if ( !element.FirstChild() )
1739 if ( element.FirstChild()->ToText()
1740 && element.LastChild() == element.FirstChild()
1741 && element.FirstChild()->ToText()->CDATA() == false )
1743 simpleTextPrint = true;
1744 // no DoLineBreak()!
1756 bool TiXmlPrinter::VisitExit( const TiXmlElement& element )
1759 if ( !element.FirstChild() )
1765 if ( simpleTextPrint )
1767 simpleTextPrint = false;
1774 buffer += element.Value();
1782 bool TiXmlPrinter::Visit( const TiXmlText& text )
1787 buffer += "<![CDATA[";
1788 buffer += text.Value();
1792 else if ( simpleTextPrint )
1795 TiXmlBase::EncodeString( text.ValueTStr(), &str );
1802 TiXmlBase::EncodeString( text.ValueTStr(), &str );
1810 bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration )
1813 declaration.Print( 0, 0, &buffer );
1819 bool TiXmlPrinter::Visit( const TiXmlComment& comment )
1823 buffer += comment.Value();
1830 bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown )
1834 buffer += unknown.Value();