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