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