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), "%f", _value);
01327
01328 #else
01329 sprintf (buf, "%lf", _value);
01330 #endif
01331 SetValue (buf);
01332 }
01333
01334 int TiXmlAttribute::IntValue() const
01335 {
01336 return atoi (value.c_str ());
01337 }
01338
01339 double TiXmlAttribute::DoubleValue() const
01340 {
01341 return atof (value.c_str ());
01342 }
01343
01344
01345 TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT )
01346 {
01347 copy.CopyTo( this );
01348 }
01349
01350
01351 void TiXmlComment::operator=( const TiXmlComment& base )
01352 {
01353 Clear();
01354 base.CopyTo( this );
01355 }
01356
01357
01358 void TiXmlComment::Print( FILE* cfile, int depth ) const
01359 {
01360 for ( int i=0; i<depth; i++ )
01361 {
01362 fputs( " ", cfile );
01363 }
01364 fprintf( cfile, "<!--%s-->", value.c_str() );
01365 }
01366
01367 void TiXmlComment::StreamOut( TIXML_OSTREAM * stream ) const
01368 {
01369 (*stream) << "<!--";
01370
01371 (*stream) << value;
01372 (*stream) << "-->";
01373 }
01374
01375
01376 void TiXmlComment::CopyTo( TiXmlComment* target ) const
01377 {
01378 TiXmlNode::CopyTo( target );
01379 }
01380
01381
01382 TiXmlNode* TiXmlComment::Clone() const
01383 {
01384 TiXmlComment* clone = new TiXmlComment();
01385
01386 if ( !clone )
01387 return 0;
01388
01389 CopyTo( clone );
01390 return clone;
01391 }
01392
01393
01394 void TiXmlText::Print( FILE* cfile, int depth ) const
01395 {
01396 if ( cdata )
01397 {
01398 int i;
01399 fprintf( cfile, "\n" );
01400 for ( i=0; i<depth; i++ ) {
01401 fprintf( cfile, " " );
01402 }
01403 fprintf( cfile, "<![CDATA[" );
01404 fprintf( cfile, "%s", value.c_str() );
01405 fprintf( cfile, "]]>\n" );
01406 }
01407 else
01408 {
01409 TIXML_STRING buffer;
01410 PutString( value, &buffer );
01411 fprintf( cfile, "%s", buffer.c_str() );
01412 }
01413 }
01414
01415
01416 void TiXmlText::StreamOut( TIXML_OSTREAM * stream ) const
01417 {
01418 if ( cdata )
01419 {
01420 (*stream) << "<![CDATA[" << value << "]]>";
01421 }
01422 else
01423 {
01424 PutString( value, stream );
01425 }
01426 }
01427
01428
01429 void TiXmlText::CopyTo( TiXmlText* target ) const
01430 {
01431 TiXmlNode::CopyTo( target );
01432 target->cdata = cdata;
01433 }
01434
01435
01436 TiXmlNode* TiXmlText::Clone() const
01437 {
01438 TiXmlText* clone = 0;
01439 clone = new TiXmlText( "" );
01440
01441 if ( !clone )
01442 return 0;
01443
01444 CopyTo( clone );
01445 return clone;
01446 }
01447
01448
01449 TiXmlDeclaration::TiXmlDeclaration( const char * _version,
01450 const char * _encoding,
01451 const char * _standalone )
01452 : TiXmlNode( TiXmlNode::DECLARATION )
01453 {
01454 version = _version;
01455 encoding = _encoding;
01456 standalone = _standalone;
01457 }
01458
01459
01460 #ifdef TIXML_USE_STL
01461 TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
01462 const std::string& _encoding,
01463 const std::string& _standalone )
01464 : TiXmlNode( TiXmlNode::DECLARATION )
01465 {
01466 version = _version;
01467 encoding = _encoding;
01468 standalone = _standalone;
01469 }
01470 #endif
01471
01472
01473 TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
01474 : TiXmlNode( TiXmlNode::DECLARATION )
01475 {
01476 copy.CopyTo( this );
01477 }
01478
01479
01480 void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
01481 {
01482 Clear();
01483 copy.CopyTo( this );
01484 }
01485
01486
01487 void TiXmlDeclaration::Print( FILE* cfile, int ) const
01488 {
01489 fprintf (cfile, "<?xml ");
01490
01491 if ( !version.empty() )
01492 fprintf (cfile, "version=\"%s\" ", version.c_str ());
01493 if ( !encoding.empty() )
01494 fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
01495 if ( !standalone.empty() )
01496 fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
01497 fprintf (cfile, "?>");
01498 }
01499
01500 void TiXmlDeclaration::StreamOut( TIXML_OSTREAM * stream ) const
01501 {
01502 (*stream) << "<?xml ";
01503
01504 if ( !version.empty() )
01505 {
01506 (*stream) << "version=\"";
01507 PutString( version, stream );
01508 (*stream) << "\" ";
01509 }
01510 if ( !encoding.empty() )
01511 {
01512 (*stream) << "encoding=\"";
01513 PutString( encoding, stream );
01514 (*stream ) << "\" ";
01515 }
01516 if ( !standalone.empty() )
01517 {
01518 (*stream) << "standalone=\"";
01519 PutString( standalone, stream );
01520 (*stream) << "\" ";
01521 }
01522 (*stream) << "?>";
01523 }
01524
01525
01526 void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
01527 {
01528 TiXmlNode::CopyTo( target );
01529
01530 target->version = version;
01531 target->encoding = encoding;
01532 target->standalone = standalone;
01533 }
01534
01535
01536 TiXmlNode* TiXmlDeclaration::Clone() const
01537 {
01538 TiXmlDeclaration* clone = new TiXmlDeclaration();
01539
01540 if ( !clone )
01541 return 0;
01542
01543 CopyTo( clone );
01544 return clone;
01545 }
01546
01547
01548 void TiXmlUnknown::Print( FILE* cfile, int depth ) const
01549 {
01550 for ( int i=0; i<depth; i++ )
01551 fprintf( cfile, " " );
01552 fprintf( cfile, "<%s>", value.c_str() );
01553 }
01554
01555
01556 void TiXmlUnknown::StreamOut( TIXML_OSTREAM * stream ) const
01557 {
01558 (*stream) << "<" << value << ">";
01559 }
01560
01561
01562 void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
01563 {
01564 TiXmlNode::CopyTo( target );
01565 }
01566
01567
01568 TiXmlNode* TiXmlUnknown::Clone() const
01569 {
01570 TiXmlUnknown* clone = new TiXmlUnknown();
01571
01572 if ( !clone )
01573 return 0;
01574
01575 CopyTo( clone );
01576 return clone;
01577 }
01578
01579
01580 TiXmlAttributeSet::TiXmlAttributeSet()
01581 {
01582 sentinel.next = &sentinel;
01583 sentinel.prev = &sentinel;
01584 }
01585
01586
01587 TiXmlAttributeSet::~TiXmlAttributeSet()
01588 {
01589 assert( sentinel.next == &sentinel );
01590 assert( sentinel.prev == &sentinel );
01591 }
01592
01593
01594 void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
01595 {
01596 assert( !Find( TIXML_STRING( addMe->Name() ) ) );
01597
01598 addMe->next = &sentinel;
01599 addMe->prev = sentinel.prev;
01600
01601 sentinel.prev->next = addMe;
01602 sentinel.prev = addMe;
01603 }
01604
01605 void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
01606 {
01607 TiXmlAttribute* node;
01608
01609 for( node = sentinel.next; node != &sentinel; node = node->next )
01610 {
01611 if ( node == removeMe )
01612 {
01613 node->prev->next = node->next;
01614 node->next->prev = node->prev;
01615 node->next = 0;
01616 node->prev = 0;
01617 return;
01618 }
01619 }
01620 assert( 0 );
01621 }
01622
01623 const TiXmlAttribute* TiXmlAttributeSet::Find( const TIXML_STRING& name ) const
01624 {
01625 const TiXmlAttribute* node;
01626
01627 for( node = sentinel.next; node != &sentinel; node = node->next )
01628 {
01629 if ( node->name == name )
01630 return node;
01631 }
01632 return 0;
01633 }
01634
01635 TiXmlAttribute* TiXmlAttributeSet::Find( const TIXML_STRING& name )
01636 {
01637 TiXmlAttribute* node;
01638
01639 for( node = sentinel.next; node != &sentinel; node = node->next )
01640 {
01641 if ( node->name == name )
01642 return node;
01643 }
01644 return 0;
01645 }
01646
01647 #ifdef TIXML_USE_STL
01648 TIXML_ISTREAM & operator >> (TIXML_ISTREAM & in, TiXmlNode & base)
01649 {
01650 TIXML_STRING tag;
01651 tag.reserve( 8 * 1000 );
01652 base.StreamIn( &in, &tag );
01653
01654 base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
01655 return in;
01656 }
01657 #endif
01658
01659
01660 TIXML_OSTREAM & operator<< (TIXML_OSTREAM & out, const TiXmlNode & base)
01661 {
01662 base.StreamOut (& out);
01663 return out;
01664 }
01665
01666
01667 #ifdef TIXML_USE_STL
01668 std::string & operator<< (std::string& out, const TiXmlNode& base )
01669 {
01670 std::ostringstream os_stream( std::ostringstream::out );
01671 base.StreamOut( &os_stream );
01672
01673 out.append( os_stream.str() );
01674 return out;
01675 }
01676 #endif
01677
01678
01679 TiXmlHandle TiXmlHandle::FirstChild() const
01680 {
01681 if ( node )
01682 {
01683 TiXmlNode* child = node->FirstChild();
01684 if ( child )
01685 return TiXmlHandle( child );
01686 }
01687 return TiXmlHandle( 0 );
01688 }
01689
01690
01691 TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
01692 {
01693 if ( node )
01694 {
01695 TiXmlNode* child = node->FirstChild( value );
01696 if ( child )
01697 return TiXmlHandle( child );
01698 }
01699 return TiXmlHandle( 0 );
01700 }
01701
01702
01703 TiXmlHandle TiXmlHandle::FirstChildElement() const
01704 {
01705 if ( node )
01706 {
01707 TiXmlElement* child = node->FirstChildElement();
01708 if ( child )
01709 return TiXmlHandle( child );
01710 }
01711 return TiXmlHandle( 0 );
01712 }
01713
01714
01715 TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
01716 {
01717 if ( node )
01718 {
01719 TiXmlElement* child = node->FirstChildElement( value );
01720 if ( child )
01721 return TiXmlHandle( child );
01722 }
01723 return TiXmlHandle( 0 );
01724 }
01725
01726
01727 TiXmlHandle TiXmlHandle::Child( int count ) const
01728 {
01729 if ( node )
01730 {
01731 int i;
01732 TiXmlNode* child = node->FirstChild();
01733 for ( i=0;
01734 child && i<count;
01735 child = child->NextSibling(), ++i )
01736 {
01737
01738 }
01739 if ( child )
01740 return TiXmlHandle( child );
01741 }
01742 return TiXmlHandle( 0 );
01743 }
01744
01745
01746 TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
01747 {
01748 if ( node )
01749 {
01750 int i;
01751 TiXmlNode* child = node->FirstChild( value );
01752 for ( i=0;
01753 child && i<count;
01754 child = child->NextSibling( value ), ++i )
01755 {
01756
01757 }
01758 if ( child )
01759 return TiXmlHandle( child );
01760 }
01761 return TiXmlHandle( 0 );
01762 }
01763
01764
01765 TiXmlHandle TiXmlHandle::ChildElement( int count ) const
01766 {
01767 if ( node )
01768 {
01769 int i;
01770 TiXmlElement* child = node->FirstChildElement();
01771 for ( i=0;
01772 child && i<count;
01773 child = child->NextSiblingElement(), ++i )
01774 {
01775
01776 }
01777 if ( child )
01778 return TiXmlHandle( child );
01779 }
01780 return TiXmlHandle( 0 );
01781 }
01782
01783
01784 TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
01785 {
01786 if ( node )
01787 {
01788 int i;
01789 TiXmlElement* child = node->FirstChildElement( value );
01790 for ( i=0;
01791 child && i<count;
01792 child = child->NextSiblingElement( value ), ++i )
01793 {
01794
01795 }
01796 if ( child )
01797 return TiXmlHandle( child );
01798 }
01799 return TiXmlHandle( 0 );
01800 }