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