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


sick_scan
Author(s): Michael Lehning , Jochen Sprickerhof , Martin Günther
autogenerated on Tue Jul 9 2019 05:05:35