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