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