tinyxml.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This program is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU General Public License as published by the Free  *
00007 * Software Foundation; either version 2 of the License, or (at your option)   *
00008 * any later version.                                                          *
00009 *                                                                             *
00010 * This program is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    *
00013 * more details.                                                               *
00014 *                                                                             *
00015 * You should have received a copy of the GNU General Public License along     *
00016 * with this program; if not, write to the Free Software Foundation, Inc., 51  *
00017 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.                   *
00018 *******************************************************************************
00019 *                            SOFA :: Applications                             *
00020 *                                                                             *
00021 * Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
00022 * H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
00023 * M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
00024 *                                                                             *
00025 * Contact information: contact@sofa-framework.org                             *
00026 ******************************************************************************/
00027 /*
00028 www.sourceforge.net/projects/tinyxml
00029 Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
00030 
00031 This software is provided 'as-is', without any express or implied
00032 warranty. In no event will the authors be held liable for any
00033 damages arising from the use of this software.
00034 
00035 Permission is granted to anyone to use this software for any
00036 purpose, including commercial applications, and to alter it and
00037 redistribute it freely, subject to the following restrictions:
00038 
00039 1. The origin of this software must not be misrepresented; you must
00040 not claim that you wrote the original software. If you use this
00041 software in a product, an acknowledgment in the product documentation
00042 would be appreciated but is not required.
00043 
00044 2. Altered source versions must be plainly marked as such, and
00045 must not be misrepresented as being the original software.
00046 
00047 3. This notice may not be removed or altered from any source
00048 distribution.
00049 */
00050 
00051 #include <ctype.h>
00052 #include "tinyxml.h"
00053 
00054 bool TiXmlBase::condenseWhiteSpace = true;
00055 
00056 void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_OSTREAM* stream )
00057 {
00058     TIXML_STRING buffer;
00059     PutString( str, &buffer );
00060     (*stream) << buffer;
00061 }
00062 
00063 void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_STRING* outString )
00064 {
00065     int i=0;
00066 
00067     while( i<(int)str.length() )
00068     {
00069         int c = str[i];
00070 
00071         if (    c == '&' 
00072              && i < ( (int)str.length() - 2 )
00073              && str[i+1] == '#'
00074              && str[i+2] == 'x' )
00075         {
00076             // Hexadecimal character reference.
00077             // Pass through unchanged.
00078             // &#xA9;   -- copyright symbol, for example.
00079             while ( i<(int)str.length() )
00080             {
00081                 outString->append( str.c_str() + i, 1 );
00082                 ++i;
00083                 if ( str[i] == ';' )
00084                     break;
00085             }
00086         }
00087         else if ( c == '&' )
00088         {
00089             outString->append( entity[0].str, entity[0].strLength );
00090             ++i;
00091         }
00092         else if ( c == '<' )
00093         {
00094             outString->append( entity[1].str, entity[1].strLength );
00095             ++i;
00096         }
00097         else if ( c == '>' )
00098         {
00099             outString->append( entity[2].str, entity[2].strLength );
00100             ++i;
00101         }
00102         else if ( c == '\"' )
00103         {
00104             outString->append( entity[3].str, entity[3].strLength );
00105             ++i;
00106         }
00107         else if ( c == '\'' )
00108         {
00109             outString->append( entity[4].str, entity[4].strLength );
00110             ++i;
00111         }
00112         else if ( c < 32 || c > 126 )
00113         {
00114             // Easy pass at non-alpha/numeric/symbol
00115             // 127 is the delete key. Below 32 is symbolic.
00116             char buf[ 32 ];
00117             sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
00118             outString->append( buf, strlen( buf ) );
00119             ++i;
00120         }
00121         else
00122         {
00123             char realc = (char) c;
00124             outString->append( &realc, 1 );
00125             ++i;
00126         }
00127     }
00128 }
00129 
00130 
00131 TiXmlNode::TiXmlNode( NodeType _type )
00132 {
00133     parent = 0;
00134     type = _type;
00135     firstChild = 0;
00136     lastChild = 0;
00137     prev = 0;
00138     next = 0;
00139     userData = 0;
00140 }
00141 
00142 
00143 TiXmlNode::~TiXmlNode()
00144 {
00145     TiXmlNode* node = firstChild;
00146     TiXmlNode* temp = 0;
00147 
00148     while ( node )
00149     {
00150         temp = node;
00151         node = node->next;
00152         delete temp;
00153     }   
00154 }
00155 
00156 
00157 void TiXmlNode::Clear()
00158 {
00159     TiXmlNode* node = firstChild;
00160     TiXmlNode* temp = 0;
00161 
00162     while ( node )
00163     {
00164         temp = node;
00165         node = node->next;
00166         delete temp;
00167     }   
00168 
00169     firstChild = 0;
00170     lastChild = 0;
00171 }
00172 
00173 
00174 TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
00175 {
00176     node->parent = this;
00177 
00178     node->prev = lastChild;
00179     node->next = 0;
00180 
00181     if ( lastChild )
00182         lastChild->next = node;
00183     else
00184         firstChild = node;          // it was an empty list.
00185 
00186     lastChild = node;
00187     return node;
00188 }
00189 
00190 
00191 TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
00192 {
00193     TiXmlNode* node = addThis.Clone();
00194     if ( !node )
00195         return 0;
00196 
00197     return LinkEndChild( node );
00198 }
00199 
00200 
00201 TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
00202 {   
00203     if ( !beforeThis || beforeThis->parent != this )
00204         return 0;
00205 
00206     TiXmlNode* node = addThis.Clone();
00207     if ( !node )
00208         return 0;
00209     node->parent = this;
00210 
00211     node->next = beforeThis;
00212     node->prev = beforeThis->prev;
00213     if ( beforeThis->prev )
00214     {
00215         beforeThis->prev->next = node;
00216     }
00217     else
00218     {
00219         assert( firstChild == beforeThis );
00220         firstChild = node;
00221     }
00222     beforeThis->prev = node;
00223     return node;
00224 }
00225 
00226 
00227 TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
00228 {
00229     if ( !afterThis || afterThis->parent != this )
00230         return 0;
00231 
00232     TiXmlNode* node = addThis.Clone();
00233     if ( !node )
00234         return 0;
00235     node->parent = this;
00236 
00237     node->prev = afterThis;
00238     node->next = afterThis->next;
00239     if ( afterThis->next )
00240     {
00241         afterThis->next->prev = node;
00242     }
00243     else
00244     {
00245         assert( lastChild == afterThis );
00246         lastChild = node;
00247     }
00248     afterThis->next = node;
00249     return node;
00250 }
00251 
00252 
00253 TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
00254 {
00255     if ( replaceThis->parent != this )
00256         return 0;
00257 
00258     TiXmlNode* node = withThis.Clone();
00259     if ( !node )
00260         return 0;
00261 
00262     node->next = replaceThis->next;
00263     node->prev = replaceThis->prev;
00264 
00265     if ( replaceThis->next )
00266         replaceThis->next->prev = node;
00267     else
00268         lastChild = node;
00269 
00270     if ( replaceThis->prev )
00271         replaceThis->prev->next = node;
00272     else
00273         firstChild = node;
00274 
00275     delete replaceThis;
00276     node->parent = this;
00277     return node;
00278 }
00279 
00280 
00281 bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
00282 {
00283     if ( removeThis->parent != this )
00284     {   
00285         assert( 0 );
00286         return false;
00287     }
00288 
00289     if ( removeThis->next )
00290         removeThis->next->prev = removeThis->prev;
00291     else
00292         lastChild = removeThis->prev;
00293 
00294     if ( removeThis->prev )
00295         removeThis->prev->next = removeThis->next;
00296     else
00297         firstChild = removeThis->next;
00298 
00299     delete removeThis;
00300     return true;
00301 }
00302 
00303 TiXmlNode* TiXmlNode::FirstChild( const char * value ) const
00304 {
00305     TiXmlNode* node;
00306     for ( node = firstChild; node; node = node->next )
00307     {
00308         if ( node->SValue() == TIXML_STRING( value ))
00309             return node;
00310     }
00311     return 0;
00312 }
00313 
00314 TiXmlNode* TiXmlNode::LastChild( const char * value ) const
00315 {
00316     TiXmlNode* node;
00317     for ( node = lastChild; node; node = node->prev )
00318     {
00319         if ( node->SValue() == TIXML_STRING (value))
00320             return node;
00321     }
00322     return 0;
00323 }
00324 
00325 TiXmlNode* TiXmlNode::IterateChildren( TiXmlNode* previous ) const
00326 {
00327     if ( !previous )
00328     {
00329         return FirstChild();
00330     }
00331     else
00332     {
00333         assert( previous->parent == this );
00334         return previous->NextSibling();
00335     }
00336 }
00337 
00338 TiXmlNode* TiXmlNode::IterateChildren( const char * val, TiXmlNode* previous ) const
00339 {
00340     if ( !previous )
00341     {
00342         return FirstChild( val );
00343     }
00344     else
00345     {
00346         assert( previous->parent == this );
00347         return previous->NextSibling( val );
00348     }
00349 }
00350 
00351 TiXmlNode* TiXmlNode::NextSibling( const char * value ) const
00352 {
00353     TiXmlNode* node;
00354     for ( node = next; node; node = node->next )
00355     {
00356         if ( node->SValue() == TIXML_STRING (value))
00357             return node;
00358     }
00359     return 0;
00360 }
00361 
00362 
00363 TiXmlNode* TiXmlNode::PreviousSibling( const char * value ) const
00364 {
00365     TiXmlNode* node;
00366     for ( node = prev; node; node = node->prev )
00367     {
00368         if ( node->SValue() == TIXML_STRING (value))
00369             return node;
00370     }
00371     return 0;
00372 }
00373 
00374 void TiXmlElement::RemoveAttribute( const char * name )
00375 {
00376     TiXmlAttribute* node = attributeSet.Find( name );
00377     if ( node )
00378     {
00379         attributeSet.Remove( node );
00380         delete node;
00381     }
00382 }
00383 
00384 TiXmlElement* TiXmlNode::FirstChildElement() const
00385 {
00386     TiXmlNode* node;
00387 
00388     for (   node = FirstChild();
00389     node;
00390     node = node->NextSibling() )
00391     {
00392         if ( node->ToElement() )
00393             return node->ToElement();
00394     }
00395     return 0;
00396 }
00397 
00398 TiXmlElement* TiXmlNode::FirstChildElement( const char * value ) const
00399 {
00400     TiXmlNode* node;
00401 
00402     for (   node = FirstChild( value );
00403     node;
00404     node = node->NextSibling( value ) )
00405     {
00406         if ( node->ToElement() )
00407             return node->ToElement();
00408     }
00409     return 0;
00410 }
00411 
00412 
00413 TiXmlElement* TiXmlNode::NextSiblingElement() const
00414 {
00415     TiXmlNode* node;
00416 
00417     for (   node = NextSibling();
00418     node;
00419     node = node->NextSibling() )
00420     {
00421         if ( node->ToElement() )
00422             return node->ToElement();
00423     }
00424     return 0;
00425 }
00426 
00427 TiXmlElement* TiXmlNode::NextSiblingElement( const char * value ) const
00428 {
00429     TiXmlNode* node;
00430 
00431     for (   node = NextSibling( value );
00432     node;
00433     node = node->NextSibling( value ) )
00434     {
00435         if ( node->ToElement() )
00436             return node->ToElement();
00437     }
00438     return 0;
00439 }
00440 
00441 
00442 
00443 TiXmlDocument* TiXmlNode::GetDocument() const
00444 {
00445     const TiXmlNode* node;
00446 
00447     for( node = this; node; node = node->parent )
00448     {
00449         if ( node->ToDocument() )
00450             return node->ToDocument();
00451     }
00452     return 0;
00453 }
00454 
00455 
00456 TiXmlElement::TiXmlElement (const char * _value)
00457 : TiXmlNode( TiXmlNode::ELEMENT )
00458 {
00459     firstChild = lastChild = 0;
00460     value = _value;
00461 }
00462 
00463 TiXmlElement::~TiXmlElement()
00464 {
00465     while( attributeSet.First() )
00466     {
00467         TiXmlAttribute* node = attributeSet.First();
00468         attributeSet.Remove( node );
00469         delete node;
00470     }
00471 }
00472 
00473 // BEGIN OGRE CHANGES
00474 // USE STL ALONE
00475 #ifndef TIXML_USE_STL
00476 const char * TiXmlElement::Attribute( const char * name ) const
00477 {
00478     TiXmlAttribute* node = attributeSet.Find( name );
00479 
00480     if ( node )
00481         return node->Value();
00482 
00483     return 0;
00484 }
00485 
00486 
00487 const char * TiXmlElement::Attribute( const char * name, int* i ) const
00488 {
00489     const char * s = Attribute( name );
00490     if ( i )
00491     {
00492         if ( s )
00493             *i = atoi( s );
00494         else
00495             *i = 0;
00496     }
00497     return s;
00498 }
00499 
00500 
00501 void TiXmlElement::SetAttribute( const char * name, int val )
00502 {   
00503     char buf[64];
00504     sprintf( buf, "%d", val );
00505     SetAttribute( name, buf );
00506 }
00507 
00508 
00509 void TiXmlElement::SetAttribute( const char * name, const char * value )
00510 {
00511     TiXmlAttribute* node = attributeSet.Find( name );
00512     if ( node )
00513     {
00514         node->SetValue( value );
00515         return;
00516     }
00517 
00518     TiXmlAttribute* attrib = new TiXmlAttribute( name, value );
00519     if ( attrib )
00520     {
00521         attributeSet.Add( attrib );
00522     }
00523     else
00524     {
00525         TiXmlDocument* document = GetDocument();
00526         if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY );
00527     }
00528 }
00529 
00530 #endif
00531 
00532 #ifdef TIXML_USE_STL
00533 
00534 const char * TiXmlElement::Attribute( const std::string& name ) const
00535 {
00536     TiXmlAttribute* node = attributeSet.Find( name.c_str() );
00537 
00538     if ( node )
00539         return node->Value();
00540 
00541     return 0;
00542 }
00543 
00544 
00545 const char * TiXmlElement::Attribute( const std::string& name, int* i ) const
00546 {
00547     const char * s = Attribute( name );
00548     if ( i )
00549     {
00550         if ( s )
00551             *i = atoi( s );
00552         else
00553             *i = 0;
00554     }
00555     return s;
00556 }
00557 
00558 
00559 void TiXmlElement::SetAttribute( const std::string& name, int val )
00560 {   
00561     char buf[64];
00562     sprintf( buf, "%d", val );
00563     SetAttribute( name, buf );
00564 }
00565 
00566 
00567 void TiXmlElement::SetAttribute( const std::string& name, const std::string& value )
00568 {
00569     TiXmlAttribute* node = attributeSet.Find( name.c_str() );
00570     if ( node )
00571     {
00572         node->SetValue( value );
00573         return;
00574     }
00575 
00576     TiXmlAttribute* attrib = new TiXmlAttribute( name, value );
00577     if ( attrib )
00578     {
00579         attributeSet.Add( attrib );
00580     }
00581     else
00582     {
00583         TiXmlDocument* document = GetDocument();
00584         if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY );
00585     }
00586 }
00587 
00588 #endif
00589 // END OGRE CHANGES
00590 void TiXmlElement::Print( FILE* cfile, int depth ) const
00591 {
00592     int i;
00593     for ( i=0; i<depth; i++ )
00594     {
00595         fprintf( cfile, "    " );
00596     }
00597 
00598     fprintf( cfile, "<%s", value.c_str() );
00599 
00600     TiXmlAttribute* attrib;
00601     for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
00602     {
00603         fprintf( cfile, " " );
00604         attrib->Print( cfile, depth );
00605     }
00606 
00607     // There are 3 different formatting approaches:
00608     // 1) An element without children is printed as a <foo /> node
00609     // 2) An element with only a text child is printed as <foo> text </foo>
00610     // 3) An element with children is printed on multiple lines.
00611     TiXmlNode* node;
00612     if ( !firstChild )
00613     {
00614         fprintf( cfile, " />" );
00615     }
00616     else if ( firstChild == lastChild && firstChild->ToText() )
00617     {
00618         fprintf( cfile, ">" );
00619         firstChild->Print( cfile, depth + 1 );
00620         fprintf( cfile, "</%s>", value.c_str() );
00621     }
00622     else
00623     {
00624         fprintf( cfile, ">" );
00625 
00626         for ( node = firstChild; node; node=node->NextSibling() )
00627         {
00628             if ( !node->ToText() )
00629             {
00630                 fprintf( cfile, "\n" );
00631             }
00632             node->Print( cfile, depth+1 );
00633         }
00634         fprintf( cfile, "\n" );
00635         for( i=0; i<depth; ++i )
00636         fprintf( cfile, "    " );
00637         fprintf( cfile, "</%s>", value.c_str() );
00638     }
00639 }
00640 
00641 void TiXmlElement::StreamOut( TIXML_OSTREAM * stream ) const
00642 {
00643     (*stream) << "<" << value;
00644 
00645     TiXmlAttribute* attrib;
00646     for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
00647     {   
00648         (*stream) << " ";
00649         attrib->StreamOut( stream );
00650     }
00651 
00652     // If this node has children, give it a closing tag. Else
00653     // make it an empty tag.
00654     TiXmlNode* node;
00655     if ( firstChild )
00656     {       
00657         (*stream) << ">";
00658 
00659         for ( node = firstChild; node; node=node->NextSibling() )
00660         {
00661             node->StreamOut( stream );
00662         }
00663         (*stream) << "</" << value << ">";
00664     }
00665     else
00666     {
00667         (*stream) << " />";
00668     }
00669 }
00670 
00671 TiXmlNode* TiXmlElement::Clone() const
00672 {
00673     TiXmlElement* clone = new TiXmlElement( Value() );
00674     if ( !clone )
00675         return 0;
00676 
00677     CopyToClone( clone );
00678 
00679     // Clone the attributes, then clone the children.
00680     TiXmlAttribute* attribute = 0;
00681     for(    attribute = attributeSet.First();
00682     attribute;
00683     attribute = attribute->Next() )
00684     {
00685         clone->SetAttribute( attribute->Name(), attribute->Value() );
00686     }
00687 
00688     TiXmlNode* node = 0;
00689     for ( node = firstChild; node; node = node->NextSibling() )
00690     {
00691         clone->LinkEndChild( node->Clone() );
00692     }
00693     return clone;
00694 }
00695 
00696 
00697 TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
00698 {
00699     error = false;
00700     //  ignoreWhiteSpace = true;
00701 }
00702 
00703 TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
00704 {
00705     //  ignoreWhiteSpace = true;
00706     value = documentName;
00707     error = false;
00708 }
00709 
00710 bool TiXmlDocument::LoadFile()
00711 {
00712     if ( LoadFile( value.c_str() ) )
00713         return true;
00714 
00715     return false;
00716 }
00717 
00718 
00719 bool TiXmlDocument::SaveFile() const
00720 {
00721     if ( SaveFile( value.c_str() ) )
00722         return true;
00723 
00724     return false;
00725 }
00726 
00727 bool TiXmlDocument::LoadFile( const char* filename )
00728 {
00729     // Delete the existing data:
00730     Clear();
00731 
00732     // There was a really terrifying little bug here. The code:
00733     //      value = filename
00734     // in the STL case, cause the assignment method of the std::string to
00735     // be called. What is strange, is that the std::string had the same
00736     // address as it's c_str() method, and so bad things happen. Looks
00737     // like a bug in the Microsoft STL implementation.
00738     // See STL_STRING_BUG above.
00739     // Fixed with the StringToBuffer class.
00740     value = filename;
00741 
00742     FILE* file = fopen( value.c_str (), "r" );
00743 
00744     if ( file )
00745     {
00746         // Get the file size, so we can pre-allocate the string. HUGE speed impact.
00747         long length = 0;
00748         fseek( file, 0, SEEK_END );
00749         length = ftell( file );
00750         fseek( file, 0, SEEK_SET );
00751 
00752         // Strange case, but good to handle up front.
00753         if ( length == 0 )
00754         {
00755             fclose( file );
00756             return false;
00757         }
00758 
00759         // If we have a file, assume it is all one big XML file, and read it in.
00760         // The document parser may decide the document ends sooner than the entire file, however.
00761         TIXML_STRING data;
00762         data.reserve( length );
00763 
00764         const int BUF_SIZE = 2048;
00765         char buf[BUF_SIZE];
00766 
00767         while( fgets( buf, BUF_SIZE, file ) )
00768         {
00769             data += buf;
00770         }
00771         fclose( file );
00772 
00773         Parse( data.c_str() );
00774         if (  !Error() )
00775         {
00776             return true;
00777         }
00778     }
00779     SetError( TIXML_ERROR_OPENING_FILE );
00780     return false;
00781 }
00782 
00783 bool TiXmlDocument::SaveFile( const char * filename ) const
00784 {
00785     // The old c stuff lives on...
00786     FILE* fp = fopen( filename, "w" );
00787     if ( fp )
00788     {
00789         Print( fp, 0 );
00790         fclose( fp );
00791         return true;
00792     }
00793     return false;
00794 }
00795 
00796 
00797 TiXmlNode* TiXmlDocument::Clone() const
00798 {
00799     TiXmlDocument* clone = new TiXmlDocument();
00800     if ( !clone )
00801         return 0;
00802 
00803     CopyToClone( clone );
00804     clone->error = error;
00805     clone->errorDesc = errorDesc.c_str ();
00806 
00807     TiXmlNode* node = 0;
00808     for ( node = firstChild; node; node = node->NextSibling() )
00809     {
00810         clone->LinkEndChild( node->Clone() );
00811     }
00812     return clone;
00813 }
00814 
00815 
00816 void TiXmlDocument::Print( FILE* cfile, int depth ) const
00817 {
00818     TiXmlNode* node;
00819     for ( node=FirstChild(); node; node=node->NextSibling() )
00820     {
00821         node->Print( cfile, depth );
00822         fprintf( cfile, "\n" );
00823     }
00824 }
00825 
00826 void TiXmlDocument::StreamOut( TIXML_OSTREAM * out ) const
00827 {
00828     TiXmlNode* node;
00829     for ( node=FirstChild(); node; node=node->NextSibling() )
00830     {
00831         node->StreamOut( out );
00832 
00833         // Special rule for streams: stop after the root element.
00834         // The stream in code will only read one element, so don't
00835         // write more than one.
00836         if ( node->ToElement() )
00837             break;
00838     }
00839 }
00840 
00841 TiXmlAttribute* TiXmlAttribute::Next() const
00842 {
00843     // We are using knowledge of the sentinel. The sentinel
00844     // have a value or name.
00845     if ( next->value.empty() && next->name.empty() )
00846         return 0;
00847     return next;
00848 }
00849 
00850 
00851 TiXmlAttribute* TiXmlAttribute::Previous() const
00852 {
00853     // We are using knowledge of the sentinel. The sentinel
00854     // have a value or name.
00855     if ( prev->value.empty() && prev->name.empty() )
00856         return 0;
00857     return prev;
00858 }
00859 
00860 
00861 void TiXmlAttribute::Print( FILE* cfile, int /*depth*/ ) const
00862 {
00863     TIXML_STRING n, v;
00864 
00865     PutString( Name(), &n );
00866     PutString( Value(), &v );
00867 
00868     if (value.find ('\"') == TIXML_STRING::npos)
00869         fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
00870     else
00871         fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
00872 }
00873 
00874 
00875 void TiXmlAttribute::StreamOut( TIXML_OSTREAM * stream ) const
00876 {
00877     if (value.find( '\"' ) != TIXML_STRING::npos)
00878     {
00879         PutString( name, stream );
00880         (*stream) << "=" << "'";
00881         PutString( value, stream );
00882         (*stream) << "'";
00883     }
00884     else
00885     {
00886         PutString( name, stream );
00887         (*stream) << "=" << "\"";
00888         PutString( value, stream );
00889         (*stream) << "\"";
00890     }
00891 }
00892 
00893 void TiXmlAttribute::SetIntValue( int value )
00894 {
00895     char buf [64];
00896     sprintf (buf, "%d", value);
00897     SetValue (buf);
00898 }
00899 
00900 void TiXmlAttribute::SetDoubleValue( double value )
00901 {
00902     char buf [64];
00903     sprintf (buf, "%lf", value);
00904     SetValue (buf);
00905 }
00906 
00907 const int TiXmlAttribute::IntValue() const
00908 {
00909     return atoi (value.c_str ());
00910 }
00911 
00912 const double  TiXmlAttribute::DoubleValue() const
00913 {
00914     return atof (value.c_str ());
00915 }
00916 
00917 void TiXmlComment::Print( FILE* cfile, int depth ) const
00918 {
00919     for ( int i=0; i<depth; i++ )
00920     {
00921         fputs( "    ", cfile );
00922     }
00923     fprintf( cfile, "<!--%s-->", value.c_str() );
00924 }
00925 
00926 void TiXmlComment::StreamOut( TIXML_OSTREAM * stream ) const
00927 {
00928     (*stream) << "<!--";
00929     PutString( value, stream );
00930     (*stream) << "-->";
00931 }
00932 
00933 TiXmlNode* TiXmlComment::Clone() const
00934 {
00935     TiXmlComment* clone = new TiXmlComment();
00936 
00937     if ( !clone )
00938         return 0;
00939 
00940     CopyToClone( clone );
00941     return clone;
00942 }
00943 
00944 
00945 void TiXmlText::Print( FILE* cfile, int /*depth*/ ) const
00946 {
00947     TIXML_STRING buffer;
00948     PutString( value, &buffer );
00949     fprintf( cfile, "%s", buffer.c_str() );
00950 }
00951 
00952 
00953 void TiXmlText::StreamOut( TIXML_OSTREAM * stream ) const
00954 {
00955     PutString( value, stream );
00956 }
00957 
00958 
00959 TiXmlNode* TiXmlText::Clone() const
00960 {   
00961     TiXmlText* clone = 0;
00962     clone = new TiXmlText( "" );
00963 
00964     if ( !clone )
00965         return 0;
00966 
00967     CopyToClone( clone );
00968     return clone;
00969 }
00970 
00971 
00972 TiXmlDeclaration::TiXmlDeclaration( const char * _version,
00973     const char * _encoding,
00974     const char * _standalone )
00975 : TiXmlNode( TiXmlNode::DECLARATION )
00976 {
00977     version = _version;
00978     encoding = _encoding;
00979     standalone = _standalone;
00980 }
00981 
00982 
00983 void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/ ) const
00984 {
00985     fprintf (cfile, "<?xml ");
00986 
00987     if ( !version.empty() )
00988         fprintf (cfile, "version=\"%s\" ", version.c_str ());
00989     if ( !encoding.empty() )
00990         fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
00991     if ( !standalone.empty() )
00992         fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
00993     fprintf (cfile, "?>");
00994 }
00995 
00996 void TiXmlDeclaration::StreamOut( TIXML_OSTREAM * stream ) const
00997 {
00998     (*stream) << "<?xml ";
00999 
01000     if ( !version.empty() )
01001     {
01002         (*stream) << "version=\"";
01003         PutString( version, stream );
01004         (*stream) << "\" ";
01005     }
01006     if ( !encoding.empty() )
01007     {
01008         (*stream) << "encoding=\"";
01009         PutString( encoding, stream );
01010         (*stream ) << "\" ";
01011     }
01012     if ( !standalone.empty() )
01013     {
01014         (*stream) << "standalone=\"";
01015         PutString( standalone, stream );
01016         (*stream) << "\" ";
01017     }
01018     (*stream) << "?>";
01019 }
01020 
01021 TiXmlNode* TiXmlDeclaration::Clone() const
01022 {   
01023     TiXmlDeclaration* clone = new TiXmlDeclaration();
01024 
01025     if ( !clone )
01026         return 0;
01027 
01028     CopyToClone( clone );
01029     clone->version = version;
01030     clone->encoding = encoding;
01031     clone->standalone = standalone;
01032     return clone;
01033 }
01034 
01035 
01036 void TiXmlUnknown::Print( FILE* cfile, int depth ) const
01037 {
01038     for ( int i=0; i<depth; i++ )
01039         fprintf( cfile, "    " );
01040     fprintf( cfile, "%s", value.c_str() );
01041 }
01042 
01043 void TiXmlUnknown::StreamOut( TIXML_OSTREAM * stream ) const
01044 {
01045     (*stream) << "<" << value << ">";       // Don't use entities hear! It is unknown.
01046 }
01047 
01048 TiXmlNode* TiXmlUnknown::Clone() const
01049 {
01050     TiXmlUnknown* clone = new TiXmlUnknown();
01051 
01052     if ( !clone )
01053         return 0;
01054 
01055     CopyToClone( clone );
01056     return clone;
01057 }
01058 
01059 
01060 TiXmlAttributeSet::TiXmlAttributeSet()
01061 {
01062     sentinel.next = &sentinel;
01063     sentinel.prev = &sentinel;
01064 }
01065 
01066 
01067 TiXmlAttributeSet::~TiXmlAttributeSet()
01068 {
01069     assert( sentinel.next == &sentinel );
01070     assert( sentinel.prev == &sentinel );
01071 }
01072 
01073 
01074 void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
01075 {
01076     assert( !Find( addMe->Name() ) );   // Shouldn't be multiply adding to the set.
01077 
01078     addMe->next = &sentinel;
01079     addMe->prev = sentinel.prev;
01080 
01081     sentinel.prev->next = addMe;
01082     sentinel.prev      = addMe;
01083 }
01084 
01085 void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
01086 {
01087     TiXmlAttribute* node;
01088 
01089     for( node = sentinel.next; node != &sentinel; node = node->next )
01090     {
01091         if ( node == removeMe )
01092         {
01093             node->prev->next = node->next;
01094             node->next->prev = node->prev;
01095             node->next = 0;
01096             node->prev = 0;
01097             return;
01098         }
01099     }
01100     assert( 0 );        // we tried to remove a non-linked attribute.
01101 }
01102 
01103 TiXmlAttribute* TiXmlAttributeSet::Find( const char * name ) const
01104 {
01105     TiXmlAttribute* node;
01106 
01107     for( node = sentinel.next; node != &sentinel; node = node->next )
01108     {
01109         if ( node->name == name )
01110             return node;
01111     }
01112     return 0;
01113 }
01114 
01115 
01116 #ifdef TIXML_USE_STL    
01117 TIXML_ISTREAM & operator >> (TIXML_ISTREAM & in, TiXmlNode & base)
01118 {
01119     TIXML_STRING tag;
01120     tag.reserve( 8 * 1000 );
01121     base.StreamIn( &in, &tag );
01122 
01123     base.Parse( tag.c_str() );
01124     return in;
01125 }
01126 #endif
01127 
01128 
01129 TIXML_OSTREAM & operator<< (TIXML_OSTREAM & out, const TiXmlNode & base)
01130 {
01131     base.StreamOut (& out);
01132     return out;
01133 }
01134 

Generated on Sun Nov 23 02:28:38 2008 for Sofa by  doxygen 1.5.7.1