Wim van der Vegt / TINYXML

Dependents:   tinyxml_test

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers tinyxml.cpp Source File

tinyxml.cpp

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