00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <ctype.h>
00026 #include "tinyxml.h"
00027
00028 #ifdef TIXML_USE_STL
00029 #include <sstream>
00030 #include <iostream>
00031 #endif
00032
00033
00034 bool TiXmlBase::condenseWhiteSpace = true;
00035
00036 void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_OSTREAM* stream )
00037 {
00038 TIXML_STRING buffer;
00039 PutString( str, &buffer );
00040 (*stream) << buffer;
00041 }
00042
00043 void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_STRING* outString )
00044 {
00045 int i=0;
00046
00047 while( i<(int)str.length() )
00048 {
00049 unsigned char c = (unsigned char) str[i];
00050
00051 if ( c == '&'
00052 && i < ( (int)str.length() - 2 )
00053 && str[i+1] == '#'
00054 && str[i+2] == 'x' )
00055 {
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 while ( i<(int)str.length()-1 )
00067 {
00068 outString->append( str.c_str() + i, 1 );
00069 ++i;
00070 if ( str[i] == ';' )
00071 break;
00072 }
00073 }
00074 else if ( c == '&' )
00075 {
00076 outString->append( entity[0].str, entity[0].strLength );
00077 ++i;
00078 }
00079 else if ( c == '<' )
00080 {
00081 outString->append( entity[1].str, entity[1].strLength );
00082 ++i;
00083 }
00084 else if ( c == '>' )
00085 {
00086 outString->append( entity[2].str, entity[2].strLength );
00087 ++i;
00088 }
00089 else if ( c == '\"' )
00090 {
00091 outString->append( entity[3].str, entity[3].strLength );
00092 ++i;
00093 }
00094 else if ( c == '\'' )
00095 {
00096 outString->append( entity[4].str, entity[4].strLength );
00097 ++i;
00098 }
00099 else if ( c < 32 )
00100 {
00101
00102
00103 char buf[ 32 ];
00104
00105 #if defined(TIXML_SNPRINTF)
00106 TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) );
00107 #else
00108 sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
00109 #endif
00110
00111
00112
00113 outString->append( buf, (int)strlen( buf ) );
00114 ++i;
00115 }
00116 else
00117 {
00118
00119
00120 *outString += (char) c;
00121 ++i;
00122 }
00123 }
00124 }
00125
00126
00127
00128 TiXmlBase::StringToBuffer::StringToBuffer( const TIXML_STRING& str )
00129 {
00130 buffer = new char[ str.length()+1 ];
00131 if ( buffer )
00132 {
00133 strcpy( buffer, str.c_str() );
00134 }
00135 }
00136
00137
00138 TiXmlBase::StringToBuffer::~StringToBuffer()
00139 {
00140 delete [] buffer;
00141 }
00142
00143
00144
00145 TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
00146 {
00147 parent = 0;
00148 type = _type;
00149 firstChild = 0;
00150 lastChild = 0;
00151 prev = 0;
00152 next = 0;
00153 }
00154
00155
00156 TiXmlNode::~TiXmlNode()
00157 {
00158 TiXmlNode* node = firstChild;
00159 TiXmlNode* temp = 0;
00160
00161 while ( node )
00162 {
00163 temp = node;
00164 node = node->next;
00165 delete temp;
00166 }
00167 }
00168
00169
00170 void TiXmlNode::CopyTo( TiXmlNode* target ) const
00171 {
00172 target->SetValue (value.c_str() );
00173 target->userData = userData;
00174 }
00175
00176
00177 void TiXmlNode::Clear()
00178 {
00179 TiXmlNode* node = firstChild;
00180 TiXmlNode* temp = 0;
00181
00182 while ( node )
00183 {
00184 temp = node;
00185 node = node->next;
00186 delete temp;
00187 }
00188
00189 firstChild = 0;
00190 lastChild = 0;
00191 }
00192
00193
00194 TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
00195 {
00196 assert( node->parent == 0 || node->parent == this );
00197 assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
00198
00199 node->parent = this;
00200
00201 node->prev = lastChild;
00202 node->next = 0;
00203
00204 if ( lastChild )
00205 lastChild->next = node;
00206 else
00207 firstChild = node;
00208
00209 lastChild = node;
00210 return node;
00211 }
00212
00213
00214 TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
00215 {
00216 TiXmlNode* node = addThis.Clone();
00217 if ( !node )
00218 return 0;
00219
00220 return LinkEndChild( node );
00221 }
00222
00223
00224 TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
00225 {
00226 if ( !beforeThis || beforeThis->parent != this )
00227 return 0;
00228
00229 TiXmlNode* node = addThis.Clone();
00230 if ( !node )
00231 return 0;
00232 node->parent = this;
00233
00234 node->next = beforeThis;
00235 node->prev = beforeThis->prev;
00236 if ( beforeThis->prev )
00237 {
00238 beforeThis->prev->next = node;
00239 }
00240 else
00241 {
00242 assert( firstChild == beforeThis );
00243 firstChild = node;
00244 }
00245 beforeThis->prev = node;
00246 return node;
00247 }
00248
00249
00250 TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
00251 {
00252 if ( !afterThis || afterThis->parent != this )
00253 return 0;
00254
00255 TiXmlNode* node = addThis.Clone();
00256 if ( !node )
00257 return 0;
00258 node->parent = this;
00259
00260 node->prev = afterThis;
00261 node->next = afterThis->next;
00262 if ( afterThis->next )
00263 {
00264 afterThis->next->prev = node;
00265 }
00266 else
00267 {
00268 assert( lastChild == afterThis );
00269 lastChild = node;
00270 }
00271 afterThis->next = node;
00272 return node;
00273 }
00274
00275
00276 TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
00277 {
00278 if ( replaceThis->parent != this )
00279 return 0;
00280
00281 TiXmlNode* node = withThis.Clone();
00282 if ( !node )
00283 return 0;
00284
00285 node->next = replaceThis->next;
00286 node->prev = replaceThis->prev;
00287
00288 if ( replaceThis->next )
00289 replaceThis->next->prev = node;
00290 else
00291 lastChild = node;
00292
00293 if ( replaceThis->prev )
00294 replaceThis->prev->next = node;
00295 else
00296 firstChild = node;
00297
00298 delete replaceThis;
00299 node->parent = this;
00300 return node;
00301 }
00302
00303
00304 bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
00305 {
00306 if ( removeThis->parent != this )
00307 {
00308 assert( 0 );
00309 return false;
00310 }
00311
00312 if ( removeThis->next )
00313 removeThis->next->prev = removeThis->prev;
00314 else
00315 lastChild = removeThis->prev;
00316
00317 if ( removeThis->prev )
00318 removeThis->prev->next = removeThis->next;
00319 else
00320 firstChild = removeThis->next;
00321
00322 delete removeThis;
00323 return true;
00324 }
00325
00326 const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const
00327 {
00328 const TiXmlNode* node;
00329 for ( node = firstChild; node; node = node->next )
00330 {
00331 if ( strcmp( node->Value(), _value ) == 0 )
00332 return node;
00333 }
00334 return 0;
00335 }
00336
00337
00338 TiXmlNode* TiXmlNode::FirstChild( const char * _value )
00339 {
00340 TiXmlNode* node;
00341 for ( node = firstChild; node; node = node->next )
00342 {
00343 if ( strcmp( node->Value(), _value ) == 0 )
00344 return node;
00345 }
00346 return 0;
00347 }
00348
00349
00350 const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
00351 {
00352 const TiXmlNode* node;
00353 for ( node = lastChild; node; node = node->prev )
00354 {
00355 if ( strcmp( node->Value(), _value ) == 0 )
00356 return node;
00357 }
00358 return 0;
00359 }
00360
00361 TiXmlNode* TiXmlNode::LastChild( const char * _value )
00362 {
00363 TiXmlNode* node;
00364 for ( node = lastChild; node; node = node->prev )
00365 {
00366 if ( strcmp( node->Value(), _value ) == 0 )
00367 return node;
00368 }
00369 return 0;
00370 }
00371
00372 const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const
00373 {
00374 if ( !previous )
00375 {
00376 return FirstChild();
00377 }
00378 else
00379 {
00380 assert( previous->parent == this );
00381 return previous->NextSibling();
00382 }
00383 }
00384
00385 TiXmlNode* TiXmlNode::IterateChildren( TiXmlNode* previous )
00386 {
00387 if ( !previous )
00388 {
00389 return FirstChild();
00390 }
00391 else
00392 {
00393 assert( previous->parent == this );
00394 return previous->NextSibling();
00395 }
00396 }
00397
00398 const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const
00399 {
00400 if ( !previous )
00401 {
00402 return FirstChild( val );
00403 }
00404 else
00405 {
00406 assert( previous->parent == this );
00407 return previous->NextSibling( val );
00408 }
00409 }
00410
00411 TiXmlNode* TiXmlNode::IterateChildren( const char * val, TiXmlNode* previous )
00412 {
00413 if ( !previous )
00414 {
00415 return FirstChild( val );
00416 }
00417 else
00418 {
00419 assert( previous->parent == this );
00420 return previous->NextSibling( val );
00421 }
00422 }
00423
00424 const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const
00425 {
00426 const TiXmlNode* node;
00427 for ( node = next; node; node = node->next )
00428 {
00429 if ( strcmp( node->Value(), _value ) == 0 )
00430 return node;
00431 }
00432 return 0;
00433 }
00434
00435 TiXmlNode* TiXmlNode::NextSibling( const char * _value )
00436 {
00437 TiXmlNode* node;
00438 for ( node = next; node; node = node->next )
00439 {
00440 if ( strcmp( node->Value(), _value ) == 0 )
00441 return node;
00442 }
00443 return 0;
00444 }
00445
00446 const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
00447 {
00448 const TiXmlNode* node;
00449 for ( node = prev; node; node = node->prev )
00450 {
00451 if ( strcmp( node->Value(), _value ) == 0 )
00452 return node;
00453 }
00454 return 0;
00455 }
00456
00457 TiXmlNode* TiXmlNode::PreviousSibling( const char * _value )
00458 {
00459 TiXmlNode* node;
00460 for ( node = prev; node; node = node->prev )
00461 {
00462 if ( strcmp( node->Value(), _value ) == 0 )
00463 return node;
00464 }
00465 return 0;
00466 }
00467
00468 void TiXmlElement::RemoveAttribute( const char * name )
00469 {
00470 TIXML_STRING str( name );
00471 TiXmlAttribute* node = attributeSet.Find( str );
00472 if ( node )
00473 {
00474 attributeSet.Remove( node );
00475 delete node;
00476 }
00477 }
00478
00479 const TiXmlElement* TiXmlNode::FirstChildElement() const
00480 {
00481 const TiXmlNode* node;
00482
00483 for ( node = FirstChild();
00484 node;
00485 node = node->NextSibling() )
00486 {
00487 if ( node->ToElement() )
00488 return node->ToElement();
00489 }
00490 return 0;
00491 }
00492
00493 TiXmlElement* TiXmlNode::FirstChildElement()
00494 {
00495 TiXmlNode* node;
00496
00497 for ( node = FirstChild();
00498 node;
00499 node = node->NextSibling() )
00500 {
00501 if ( node->ToElement() )
00502 return node->ToElement();
00503 }
00504 return 0;
00505 }
00506
00507 const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
00508 {
00509 const TiXmlNode* node;
00510
00511 for ( node = FirstChild( _value );
00512 node;
00513 node = node->NextSibling( _value ) )
00514 {
00515 if ( node->ToElement() )
00516 return node->ToElement();
00517 }
00518 return 0;
00519 }
00520
00521 TiXmlElement* TiXmlNode::FirstChildElement( const char * _value )
00522 {
00523 TiXmlNode* node;
00524
00525 for ( node = FirstChild( _value );
00526 node;
00527 node = node->NextSibling( _value ) )
00528 {
00529 if ( node->ToElement() )
00530 return node->ToElement();
00531 }
00532 return 0;
00533 }
00534
00535 const TiXmlElement* TiXmlNode::NextSiblingElement() const
00536 {
00537 const TiXmlNode* node;
00538
00539 for ( node = NextSibling();
00540 node;
00541 node = node->NextSibling() )
00542 {
00543 if ( node->ToElement() )
00544 return node->ToElement();
00545 }
00546 return 0;
00547 }
00548
00549 TiXmlElement* TiXmlNode::NextSiblingElement()
00550 {
00551 TiXmlNode* node;
00552
00553 for ( node = NextSibling();
00554 node;
00555 node = node->NextSibling() )
00556 {
00557 if ( node->ToElement() )
00558 return node->ToElement();
00559 }
00560 return 0;
00561 }
00562
00563 const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
00564 {
00565 const TiXmlNode* node;
00566
00567 for ( node = NextSibling( _value );
00568 node;
00569 node = node->NextSibling( _value ) )
00570 {
00571 if ( node->ToElement() )
00572 return node->ToElement();
00573 }
00574 return 0;
00575 }
00576
00577 TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value )
00578 {
00579 TiXmlNode* node;
00580
00581 for ( node = NextSibling( _value );
00582 node;
00583 node = node->NextSibling( _value ) )
00584 {
00585 if ( node->ToElement() )
00586 return node->ToElement();
00587 }
00588 return 0;
00589 }
00590
00591
00592 const TiXmlDocument* TiXmlNode::GetDocument() const
00593 {
00594 const TiXmlNode* node;
00595
00596 for( node = this; node; node = node->parent )
00597 {
00598 if ( node->ToDocument() )
00599 return node->ToDocument();
00600 }
00601 return 0;
00602 }
00603
00604 TiXmlDocument* TiXmlNode::GetDocument()
00605 {
00606 TiXmlNode* node;
00607
00608 for( node = this; node; node = node->parent )
00609 {
00610 if ( node->ToDocument() )
00611 return node->ToDocument();
00612 }
00613 return 0;
00614 }
00615
00616 TiXmlElement::TiXmlElement (const char * _value)
00617 : TiXmlNode( TiXmlNode::ELEMENT )
00618 {
00619 firstChild = lastChild = 0;
00620 value = _value;
00621 }
00622
00623
00624 #ifdef TIXML_USE_STL
00625 TiXmlElement::TiXmlElement( const std::string& _value )
00626 : TiXmlNode( TiXmlNode::ELEMENT )
00627 {
00628 firstChild = lastChild = 0;
00629 value = _value;
00630 }
00631 #endif
00632
00633
00634 TiXmlElement::TiXmlElement( const TiXmlElement& copy)
00635 : TiXmlNode( TiXmlNode::ELEMENT )
00636 {
00637 firstChild = lastChild = 0;
00638 copy.CopyTo( this );
00639 }
00640
00641
00642 void TiXmlElement::operator=( const TiXmlElement& base )
00643 {
00644 ClearThis();
00645 base.CopyTo( this );
00646 }
00647
00648
00649 TiXmlElement::~TiXmlElement()
00650 {
00651 ClearThis();
00652 }
00653
00654
00655 void TiXmlElement::ClearThis()
00656 {
00657 Clear();
00658 while( attributeSet.First() )
00659 {
00660 TiXmlAttribute* node = attributeSet.First();
00661 attributeSet.Remove( node );
00662 delete node;
00663 }
00664 }
00665
00666
00667 const char * TiXmlElement::Attribute( const char * name ) const
00668 {
00669 TIXML_STRING str( name );
00670 const TiXmlAttribute* node = attributeSet.Find( str );
00671
00672 if ( node )
00673 return node->Value();
00674
00675 return 0;
00676 }
00677
00678
00679 const char * TiXmlElement::Attribute( const char * name, int* i ) const
00680 {
00681 const char * s = Attribute( name );
00682 if ( i )
00683 {
00684 if ( s )
00685 *i = atoi( s );
00686 else
00687 *i = 0;
00688 }
00689 return s;
00690 }
00691
00692
00693 const char * TiXmlElement::Attribute( const char * name, double* d ) const
00694 {
00695 const char * s = Attribute( name );
00696 if ( d )
00697 {
00698 if ( s )
00699 *d = atof( s );
00700 else
00701 *d = 0;
00702 }
00703 return s;
00704 }
00705
00706
00707 int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
00708 {
00709 TIXML_STRING str( name );
00710 const TiXmlAttribute* node = attributeSet.Find( str );
00711 if ( !node )
00712 return TIXML_NO_ATTRIBUTE;
00713
00714 return node->QueryIntValue( ival );
00715 }
00716
00717
00718 int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
00719 {
00720 TIXML_STRING str( name );
00721 const TiXmlAttribute* node = attributeSet.Find( str );
00722 if ( !node )
00723 return TIXML_NO_ATTRIBUTE;
00724
00725 return node->QueryDoubleValue( dval );
00726 }
00727
00728
00729 void TiXmlElement::SetAttribute( const char * name, int val )
00730 {
00731 char buf[64];
00732 #if defined(TIXML_SNPRINTF)
00733 TIXML_SNPRINTF( buf, sizeof(buf), "%d", val );
00734 #else
00735 sprintf( buf, "%d", val );
00736 #endif
00737 SetAttribute( name, buf );
00738 }
00739
00740
00741 #ifdef TIXML_USE_STL
00742 void TiXmlElement::SetAttribute( const std::string& name, int val )
00743 {
00744 std::ostringstream oss;
00745 oss << val;
00746 SetAttribute( name, oss.str() );
00747 }
00748 #endif
00749
00750
00751 void TiXmlElement::SetDoubleAttribute( const char * name, double val )
00752 {
00753 char buf[256];
00754 #if defined(TIXML_SNPRINTF)
00755 TIXML_SNPRINTF( buf, sizeof(buf), "%f", val );
00756 #else
00757 sprintf( buf, "%f", val );
00758 #endif
00759 SetAttribute( name, buf );
00760 }
00761
00762
00763 void TiXmlElement::SetAttribute( const char * cname, const char * cvalue )
00764 {
00765 TIXML_STRING _name( cname );
00766 TIXML_STRING _value( cvalue );
00767
00768 TiXmlAttribute* node = attributeSet.Find( _name );
00769 if ( node )
00770 {
00771 node->SetValue( cvalue );
00772 return;
00773 }
00774
00775 TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue );
00776 if ( attrib )
00777 {
00778 attributeSet.Add( attrib );
00779 }
00780 else
00781 {
00782 TiXmlDocument* document = GetDocument();
00783 if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
00784 }
00785 }
00786
00787
00788 #ifdef TIXML_USE_STL
00789 void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value )
00790 {
00791 TiXmlAttribute* node = attributeSet.Find( name );
00792 if ( node )
00793 {
00794 node->SetValue( _value );
00795 return;
00796 }
00797
00798 TiXmlAttribute* attrib = new TiXmlAttribute( name, _value );
00799 if ( attrib )
00800 {
00801 attributeSet.Add( attrib );
00802 }
00803 else
00804 {
00805 TiXmlDocument* document = GetDocument();
00806 if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
00807 }
00808 }
00809 #endif
00810
00811
00812 void TiXmlElement::Print( FILE* cfile, int depth ) const
00813 {
00814 int i;
00815 for ( i=0; i<depth; i++ )
00816 {
00817 fprintf( cfile, " " );
00818 }
00819
00820 fprintf( cfile, "<%s", value.c_str() );
00821
00822 const TiXmlAttribute* attrib;
00823 for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
00824 {
00825 fprintf( cfile, " " );
00826 attrib->Print( cfile, depth );
00827 }
00828
00829
00830
00831
00832
00833 TiXmlNode* node;
00834 if ( !firstChild )
00835 {
00836 fprintf( cfile, " />" );
00837 }
00838 else if ( firstChild == lastChild && firstChild->ToText() )
00839 {
00840 fprintf( cfile, ">" );
00841 firstChild->Print( cfile, depth + 1 );
00842 fprintf( cfile, "</%s>", value.c_str() );
00843 }
00844 else
00845 {
00846 fprintf( cfile, ">" );
00847
00848 for ( node = firstChild; node; node=node->NextSibling() )
00849 {
00850 if ( !node->ToText() )
00851 {
00852 fprintf( cfile, "\n" );
00853 }
00854 node->Print( cfile, depth+1 );
00855 }
00856 fprintf( cfile, "\n" );
00857 for( i=0; i<depth; ++i )
00858 fprintf( cfile, " " );
00859 fprintf( cfile, "</%s>", value.c_str() );
00860 }
00861 }
00862
00863 void TiXmlElement::StreamOut( TIXML_OSTREAM * stream ) const
00864 {
00865 (*stream) << "<" << value;
00866
00867 const TiXmlAttribute* attrib;
00868 for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
00869 {
00870 (*stream) << " ";
00871 attrib->StreamOut( stream );
00872 }
00873
00874
00875
00876 TiXmlNode* node;
00877 if ( firstChild )
00878 {
00879 (*stream) << ">";
00880
00881 for ( node = firstChild; node; node=node->NextSibling() )
00882 {
00883 node->StreamOut( stream );
00884 }
00885 (*stream) << "</" << value << ">";
00886 }
00887 else
00888 {
00889 (*stream) << " />";
00890 }
00891 }
00892
00893
00894 void TiXmlElement::CopyTo( TiXmlElement* target ) const
00895 {
00896
00897 TiXmlNode::CopyTo( target );
00898
00899
00900
00901 const TiXmlAttribute* attribute = 0;
00902 for( attribute = attributeSet.First();
00903 attribute;
00904 attribute = attribute->Next() )
00905 {
00906 target->SetAttribute( attribute->Name(), attribute->Value() );
00907 }
00908
00909 TiXmlNode* node = 0;
00910 for ( node = firstChild; node; node = node->NextSibling() )
00911 {
00912 target->LinkEndChild( node->Clone() );
00913 }
00914 }
00915
00916
00917 TiXmlNode* TiXmlElement::Clone() const
00918 {
00919 TiXmlElement* clone = new TiXmlElement( Value() );
00920 if ( !clone )
00921 return 0;
00922
00923 CopyTo( clone );
00924 return clone;
00925 }
00926
00927
00928 const char* TiXmlElement::GetText() const
00929 {
00930 const TiXmlNode* child = this->FirstChild();
00931 if ( child ) {
00932 const TiXmlText* childText = child->ToText();
00933 if ( childText ) {
00934 return childText->Value();
00935 }
00936 }
00937 return 0;
00938 }
00939
00940
00941 TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
00942 {
00943 tabsize = 4;
00944 useMicrosoftBOM = false;
00945 ClearError();
00946 }
00947
00948 TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
00949 {
00950 tabsize = 4;
00951 useMicrosoftBOM = false;
00952 value = documentName;
00953 ClearError();
00954 }
00955
00956
00957 #ifdef TIXML_USE_STL
00958 TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
00959 {
00960 tabsize = 4;
00961 useMicrosoftBOM = false;
00962 value = documentName;
00963 ClearError();
00964 }
00965 #endif
00966
00967
00968 TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT )
00969 {
00970 copy.CopyTo( this );
00971 }
00972
00973
00974 void TiXmlDocument::operator=( const TiXmlDocument& copy )
00975 {
00976 Clear();
00977 copy.CopyTo( this );
00978 }
00979
00980
00981 bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
00982 {
00983
00984 StringToBuffer buf( value );
00985
00986 if ( buf.buffer && LoadFile( buf.buffer, encoding ) )
00987 return true;
00988
00989 return false;
00990 }
00991
00992
00993 bool TiXmlDocument::SaveFile() const
00994 {
00995
00996 StringToBuffer buf( value );
00997
00998 if ( buf.buffer && SaveFile( buf.buffer ) )
00999 return true;
01000
01001 return false;
01002 }
01003
01004 bool TiXmlDocument::LoadFile( const char* filename, TiXmlEncoding encoding )
01005 {
01006
01007
01008
01009
01010
01011
01012
01013
01014 value = filename;
01015
01016
01017 FILE* file = fopen( value.c_str (), "rb" );
01018
01019 if ( file )
01020 {
01021 bool result = LoadFile( file, encoding );
01022 fclose( file );
01023 return result;
01024 }
01025 else
01026 {
01027 SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
01028 return false;
01029 }
01030 }
01031
01032 bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
01033 {
01034 if ( !file )
01035 {
01036 SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
01037 return false;
01038 }
01039
01040
01041 Clear();
01042 location.Clear();
01043
01044
01045 long length = 0;
01046 fseek( file, 0, SEEK_END );
01047 length = ftell( file );
01048 fseek( file, 0, SEEK_SET );
01049
01050
01051 if ( length == 0 )
01052 {
01053 SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
01054 return false;
01055 }
01056
01057
01058
01059 TIXML_STRING data;
01060 data.reserve( length );
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083 char* buf = new char[ length+1 ];
01084 buf[0] = 0;
01085
01086 if ( fread( buf, length, 1, file ) != 1 ) {
01087 SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
01088 return false;
01089 }
01090
01091 const char* lastPos = buf;
01092 const char* p = buf;
01093
01094 buf[length] = 0;
01095 while( *p ) {
01096 assert( p < (buf+length) );
01097 if ( *p == 0xa ) {
01098
01099
01100 data.append( lastPos, (p-lastPos+1) );
01101 ++p;
01102 lastPos = p;
01103 assert( p <= (buf+length) );
01104 }
01105 else if ( *p == 0xd ) {
01106
01107
01108 if ( (p-lastPos) > 0 ) {
01109 data.append( lastPos, p-lastPos );
01110 }
01111 data += (char)0xa;
01112
01113 if ( *(p+1) == 0xa ) {
01114
01115 p += 2;
01116 lastPos = p;
01117 assert( p <= (buf+length) );
01118 }
01119 else {
01120
01121 ++p;
01122 lastPos = p;
01123 assert( p <= (buf+length) );
01124 }
01125 }
01126 else {
01127 ++p;
01128 }
01129 }
01130
01131 if ( p-lastPos ) {
01132 data.append( lastPos, p-lastPos );
01133 }
01134 delete [] buf;
01135 buf = 0;
01136
01137 Parse( data.c_str(), 0, encoding );
01138
01139 if ( Error() )
01140 return false;
01141 else
01142 return true;
01143 }
01144
01145
01146 bool TiXmlDocument::SaveFile( const char * filename ) const
01147 {
01148
01149 FILE* fp = fopen( filename, "w" );
01150 if ( fp )
01151 {
01152 bool result = SaveFile( fp );
01153 fclose( fp );
01154 return result;
01155 }
01156 return false;
01157 }
01158
01159
01160 bool TiXmlDocument::SaveFile( FILE* fp ) const
01161 {
01162 if ( useMicrosoftBOM )
01163 {
01164 const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
01165 const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
01166 const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
01167
01168 fputc( TIXML_UTF_LEAD_0, fp );
01169 fputc( TIXML_UTF_LEAD_1, fp );
01170 fputc( TIXML_UTF_LEAD_2, fp );
01171 }
01172 Print( fp, 0 );
01173 return true;
01174 }
01175
01176
01177 void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
01178 {
01179 TiXmlNode::CopyTo( target );
01180
01181 target->error = error;
01182 target->errorDesc = errorDesc.c_str ();
01183
01184 TiXmlNode* node = 0;
01185 for ( node = firstChild; node; node = node->NextSibling() )
01186 {
01187 target->LinkEndChild( node->Clone() );
01188 }
01189 }
01190
01191
01192 TiXmlNode* TiXmlDocument::Clone() const
01193 {
01194 TiXmlDocument* clone = new TiXmlDocument();
01195 if ( !clone )
01196 return 0;
01197
01198 CopyTo( clone );
01199 return clone;
01200 }
01201
01202
01203 void TiXmlDocument::Print( FILE* cfile, int depth ) const
01204 {
01205 const TiXmlNode* node;
01206 for ( node=FirstChild(); node; node=node->NextSibling() )
01207 {
01208 node->Print( cfile, depth );
01209 fprintf( cfile, "\n" );
01210 }
01211 }
01212
01213 void TiXmlDocument::StreamOut( TIXML_OSTREAM * out ) const
01214 {
01215 const TiXmlNode* node;
01216 for ( node=FirstChild(); node; node=node->NextSibling() )
01217 {
01218 node->StreamOut( out );
01219
01220
01221
01222
01223 if ( node->ToElement() )
01224 break;
01225 }
01226 }
01227
01228
01229 const TiXmlAttribute* TiXmlAttribute::Next() const
01230 {
01231
01232
01233 if ( next->value.empty() && next->name.empty() )
01234 return 0;
01235 return next;
01236 }
01237
01238 TiXmlAttribute* TiXmlAttribute::Next()
01239 {
01240
01241
01242 if ( next->value.empty() && next->name.empty() )
01243 return 0;
01244 return next;
01245 }
01246
01247 const TiXmlAttribute* TiXmlAttribute::Previous() const
01248 {
01249
01250
01251 if ( prev->value.empty() && prev->name.empty() )
01252 return 0;
01253 return prev;
01254 }
01255
01256 TiXmlAttribute* TiXmlAttribute::Previous()
01257 {
01258
01259
01260 if ( prev->value.empty() && prev->name.empty() )
01261 return 0;
01262 return prev;
01263 }
01264
01265 void TiXmlAttribute::Print( FILE* cfile, int ) const
01266 {
01267 TIXML_STRING n, v;
01268
01269 PutString( name, &n );
01270 PutString( value, &v );
01271
01272 if (value.find ('\"') == TIXML_STRING::npos)
01273 fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
01274 else
01275 fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
01276 }
01277
01278
01279 void TiXmlAttribute::StreamOut( TIXML_OSTREAM * stream ) const
01280 {
01281 if (value.find( '\"' ) != TIXML_STRING::npos)
01282 {
01283 PutString( name, stream );
01284 (*stream) << "=" << "'";
01285 PutString( value, stream );
01286 (*stream) << "'";
01287 }
01288 else
01289 {
01290 PutString( name, stream );
01291 (*stream) << "=" << "\"";
01292 PutString( value, stream );
01293 (*stream) << "\"";
01294 }
01295 }
01296
01297 int TiXmlAttribute::QueryIntValue( int* ival ) const
01298 {
01299 if ( sscanf( value.c_str(), "%d", ival ) == 1 )
01300 return TIXML_SUCCESS;
01301 return TIXML_WRONG_TYPE;
01302 }
01303
01304 int TiXmlAttribute::QueryDoubleValue( double* dval ) const
01305 {
01306 if ( sscanf( value.c_str(), "%lf", dval ) == 1 )
01307 return TIXML_SUCCESS;
01308 return TIXML_WRONG_TYPE;
01309 }
01310
01311 void TiXmlAttribute::SetIntValue( int _value )
01312 {
01313 char buf [64];
01314 #if defined(TIXML_SNPRINTF)
01315 TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
01316 #else
01317 sprintf (buf, "%d", _value);
01318 #endif
01319 SetValue (buf);
01320 }
01321
01322 void TiXmlAttribute::SetDoubleValue( double _value )
01323 {
01324 char buf [256];
01325 #if defined(TIXML_SNPRINTF)
01326 TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value);
01327 #else
01328 sprintf (buf, "%lf", _value);
01329 #endif
01330 SetValue (buf);
01331 }
01332
01333 int TiXmlAttribute::IntValue() const
01334 {
01335 return atoi (value.c_str ());
01336 }
01337
01338 double TiXmlAttribute::DoubleValue() const
01339 {
01340 return atof (value.c_str ());
01341 }
01342
01343
01344 TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT )
01345 {
01346 copy.CopyTo( this );
01347 }
01348
01349
01350 void TiXmlComment::operator=( const TiXmlComment& base )
01351 {
01352 Clear();
01353 base.CopyTo( this );
01354 }
01355
01356
01357 void TiXmlComment::Print( FILE* cfile, int depth ) const
01358 {
01359 for ( int i=0; i<depth; i++ )
01360 {
01361 fputs( " ", cfile );
01362 }
01363 fprintf( cfile, "<!--%s-->", value.c_str() );
01364 }
01365
01366 void TiXmlComment::StreamOut( TIXML_OSTREAM * stream ) const
01367 {
01368 (*stream) << "<!--";
01369
01370 (*stream) << value;
01371 (*stream) << "-->";
01372 }
01373
01374
01375 void TiXmlComment::CopyTo( TiXmlComment* target ) const
01376 {
01377 TiXmlNode::CopyTo( target );
01378 }
01379
01380
01381 TiXmlNode* TiXmlComment::Clone() const
01382 {
01383 TiXmlComment* clone = new TiXmlComment();
01384
01385 if ( !clone )
01386 return 0;
01387
01388 CopyTo( clone );
01389 return clone;
01390 }
01391
01392
01393 void TiXmlText::Print( FILE* cfile, int depth ) const
01394 {
01395 if ( cdata )
01396 {
01397 int i;
01398 fprintf( cfile, "\n" );
01399 for ( i=0; i<depth; i++ ) {
01400 fprintf( cfile, " " );
01401 }
01402 fprintf( cfile, "<![CDATA[" );
01403 fprintf( cfile, "%s", value.c_str() );
01404 fprintf( cfile, "]]>\n" );
01405 }
01406 else
01407 {
01408 TIXML_STRING buffer;
01409 PutString( value, &buffer );
01410 fprintf( cfile, "%s", buffer.c_str() );
01411 }
01412 }
01413
01414
01415 void TiXmlText::StreamOut( TIXML_OSTREAM * stream ) const
01416 {
01417 if ( cdata )
01418 {
01419 (*stream) << "<![CDATA[" << value << "]]>";
01420 }
01421 else
01422 {
01423 PutString( value, stream );
01424 }
01425 }
01426
01427
01428 void TiXmlText::CopyTo( TiXmlText* target ) const
01429 {
01430 TiXmlNode::CopyTo( target );
01431 target->cdata = cdata;
01432 }
01433
01434
01435 TiXmlNode* TiXmlText::Clone() const
01436 {
01437 TiXmlText* clone = 0;
01438 clone = new TiXmlText( "" );
01439
01440 if ( !clone )
01441 return 0;
01442
01443 CopyTo( clone );
01444 return clone;
01445 }
01446
01447
01448 TiXmlDeclaration::TiXmlDeclaration( const char * _version,
01449 const char * _encoding,
01450 const char * _standalone )
01451 : TiXmlNode( TiXmlNode::DECLARATION )
01452 {
01453 version = _version;
01454 encoding = _encoding;
01455 standalone = _standalone;
01456 }
01457
01458
01459 #ifdef TIXML_USE_STL
01460 TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
01461 const std::string& _encoding,
01462 const std::string& _standalone )
01463 : TiXmlNode( TiXmlNode::DECLARATION )
01464 {
01465 version = _version;
01466 encoding = _encoding;
01467 standalone = _standalone;
01468 }
01469 #endif
01470
01471
01472 TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
01473 : TiXmlNode( TiXmlNode::DECLARATION )
01474 {
01475 copy.CopyTo( this );
01476 }
01477
01478
01479 void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
01480 {
01481 Clear();
01482 copy.CopyTo( this );
01483 }
01484
01485
01486 void TiXmlDeclaration::Print( FILE* cfile, int ) const
01487 {
01488 fprintf (cfile, "<?xml ");
01489
01490 if ( !version.empty() )
01491 fprintf (cfile, "version=\"%s\" ", version.c_str ());
01492 if ( !encoding.empty() )
01493 fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
01494 if ( !standalone.empty() )
01495 fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
01496 fprintf (cfile, "?>");
01497 }
01498
01499 void TiXmlDeclaration::StreamOut( TIXML_OSTREAM * stream ) const
01500 {
01501 (*stream) << "<?xml ";
01502
01503 if ( !version.empty() )
01504 {
01505 (*stream) << "version=\"";
01506 PutString( version, stream );
01507 (*stream) << "\" ";
01508 }
01509 if ( !encoding.empty() )
01510 {
01511 (*stream) << "encoding=\"";
01512 PutString( encoding, stream );
01513 (*stream ) << "\" ";
01514 }
01515 if ( !standalone.empty() )
01516 {
01517 (*stream) << "standalone=\"";
01518 PutString( standalone, stream );
01519 (*stream) << "\" ";
01520 }
01521 (*stream) << "?>";
01522 }
01523
01524
01525 void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
01526 {
01527 TiXmlNode::CopyTo( target );
01528
01529 target->version = version;
01530 target->encoding = encoding;
01531 target->standalone = standalone;
01532 }
01533
01534
01535 TiXmlNode* TiXmlDeclaration::Clone() const
01536 {
01537 TiXmlDeclaration* clone = new TiXmlDeclaration();
01538
01539 if ( !clone )
01540 return 0;
01541
01542 CopyTo( clone );
01543 return clone;
01544 }
01545
01546
01547 void TiXmlUnknown::Print( FILE* cfile, int depth ) const
01548 {
01549 for ( int i=0; i<depth; i++ )
01550 fprintf( cfile, " " );
01551 fprintf( cfile, "<%s>", value.c_str() );
01552 }
01553
01554
01555 void TiXmlUnknown::StreamOut( TIXML_OSTREAM * stream ) const
01556 {
01557 (*stream) << "<" << value << ">";
01558 }
01559
01560
01561 void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
01562 {
01563 TiXmlNode::CopyTo( target );
01564 }
01565
01566
01567 TiXmlNode* TiXmlUnknown::Clone() const
01568 {
01569 TiXmlUnknown* clone = new TiXmlUnknown();
01570
01571 if ( !clone )
01572 return 0;
01573
01574 CopyTo( clone );
01575 return clone;
01576 }
01577
01578
01579 TiXmlAttributeSet::TiXmlAttributeSet()
01580 {
01581 sentinel.next = &sentinel;
01582 sentinel.prev = &sentinel;
01583 }
01584
01585
01586 TiXmlAttributeSet::~TiXmlAttributeSet()
01587 {
01588 assert( sentinel.next == &sentinel );
01589 assert( sentinel.prev == &sentinel );
01590 }
01591
01592
01593 void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
01594 {
01595 assert( !Find( TIXML_STRING( addMe->Name() ) ) );
01596
01597 addMe->next = &sentinel;
01598 addMe->prev = sentinel.prev;
01599
01600 sentinel.prev->next = addMe;
01601 sentinel.prev = addMe;
01602 }
01603
01604 void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
01605 {
01606 TiXmlAttribute* node;
01607
01608 for( node = sentinel.next; node != &sentinel; node = node->next )
01609 {
01610 if ( node == removeMe )
01611 {
01612 node->prev->next = node->next;
01613 node->next->prev = node->prev;
01614 node->next = 0;
01615 node->prev = 0;
01616 return;
01617 }
01618 }
01619 assert( 0 );
01620 }
01621
01622 const TiXmlAttribute* TiXmlAttributeSet::Find( const TIXML_STRING& name ) const
01623 {
01624 const TiXmlAttribute* node;
01625
01626 for( node = sentinel.next; node != &sentinel; node = node->next )
01627 {
01628 if ( node->name == name )
01629 return node;
01630 }
01631 return 0;
01632 }
01633
01634 TiXmlAttribute* TiXmlAttributeSet::Find( const TIXML_STRING& name )
01635 {
01636 TiXmlAttribute* node;
01637
01638 for( node = sentinel.next; node != &sentinel; node = node->next )
01639 {
01640 if ( node->name == name )
01641 return node;
01642 }
01643 return 0;
01644 }
01645
01646 #ifdef TIXML_USE_STL
01647 TIXML_ISTREAM & operator >> (TIXML_ISTREAM & in, TiXmlNode & base)
01648 {
01649 TIXML_STRING tag;
01650 tag.reserve( 8 * 1000 );
01651 base.StreamIn( &in, &tag );
01652
01653 base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
01654 return in;
01655 }
01656 #endif
01657
01658
01659 TIXML_OSTREAM & operator<< (TIXML_OSTREAM & out, const TiXmlNode & base)
01660 {
01661 base.StreamOut (& out);
01662 return out;
01663 }
01664
01665
01666 #ifdef TIXML_USE_STL
01667 std::string & operator<< (std::string& out, const TiXmlNode& base )
01668 {
01669 std::ostringstream os_stream( std::ostringstream::out );
01670 base.StreamOut( &os_stream );
01671
01672 out.append( os_stream.str() );
01673 return out;
01674 }
01675 #endif
01676
01677
01678 TiXmlHandle TiXmlHandle::FirstChild() const
01679 {
01680 if ( node )
01681 {
01682 TiXmlNode* child = node->FirstChild();
01683 if ( child )
01684 return TiXmlHandle( child );
01685 }
01686 return TiXmlHandle( 0 );
01687 }
01688
01689
01690 TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
01691 {
01692 if ( node )
01693 {
01694 TiXmlNode* child = node->FirstChild( value );
01695 if ( child )
01696 return TiXmlHandle( child );
01697 }
01698 return TiXmlHandle( 0 );
01699 }
01700
01701
01702 TiXmlHandle TiXmlHandle::FirstChildElement() const
01703 {
01704 if ( node )
01705 {
01706 TiXmlElement* child = node->FirstChildElement();
01707 if ( child )
01708 return TiXmlHandle( child );
01709 }
01710 return TiXmlHandle( 0 );
01711 }
01712
01713
01714 TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
01715 {
01716 if ( node )
01717 {
01718 TiXmlElement* child = node->FirstChildElement( value );
01719 if ( child )
01720 return TiXmlHandle( child );
01721 }
01722 return TiXmlHandle( 0 );
01723 }
01724
01725
01726 TiXmlHandle TiXmlHandle::Child( int count ) const
01727 {
01728 if ( node )
01729 {
01730 int i;
01731 TiXmlNode* child = node->FirstChild();
01732 for ( i=0;
01733 child && i<count;
01734 child = child->NextSibling(), ++i )
01735 {
01736
01737 }
01738 if ( child )
01739 return TiXmlHandle( child );
01740 }
01741 return TiXmlHandle( 0 );
01742 }
01743
01744
01745 TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
01746 {
01747 if ( node )
01748 {
01749 int i;
01750 TiXmlNode* child = node->FirstChild( value );
01751 for ( i=0;
01752 child && i<count;
01753 child = child->NextSibling( value ), ++i )
01754 {
01755
01756 }
01757 if ( child )
01758 return TiXmlHandle( child );
01759 }
01760 return TiXmlHandle( 0 );
01761 }
01762
01763
01764 TiXmlHandle TiXmlHandle::ChildElement( int count ) const
01765 {
01766 if ( node )
01767 {
01768 int i;
01769 TiXmlElement* child = node->FirstChildElement();
01770 for ( i=0;
01771 child && i<count;
01772 child = child->NextSiblingElement(), ++i )
01773 {
01774
01775 }
01776 if ( child )
01777 return TiXmlHandle( child );
01778 }
01779 return TiXmlHandle( 0 );
01780 }
01781
01782
01783 TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
01784 {
01785 if ( node )
01786 {
01787 int i;
01788 TiXmlElement* child = node->FirstChildElement( value );
01789 for ( i=0;
01790 child && i<count;
01791 child = child->NextSiblingElement( value ), ++i )
01792 {
01793
01794 }
01795 if ( child )
01796 return TiXmlHandle( child );
01797 }
01798 return TiXmlHandle( 0 );
01799 }