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