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