Panda3D

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 
 All Classes Functions Variables Enumerations