Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/ogreode/tinyxml/tinyxml.cpp @ 61

Last change on this file since 61 was 21, checked in by nicolasc, 16 years ago

added ogreode and Colladaplugin

File size: 35.5 KB
Line 
1/*
2www.sourceforge.net/projects/tinyxml
3Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
4
5This software is provided 'as-is', without any express or implied
6warranty. In no event will the authors be held liable for any
7damages arising from the use of this software.
8
9Permission is granted to anyone to use this software for any
10purpose, including commercial applications, and to alter it and
11redistribute it freely, subject to the following restrictions:
12
131. The origin of this software must not be misrepresented; you must
14not claim that you wrote the original software. If you use this
15software in a product, an acknowledgment in the product documentation
16would be appreciated but is not required.
17
182. Altered source versions must be plainly marked as such, and
19must not be misrepresented as being the original software.
20
213. This notice may not be removed or altered from any source
22distribution.
23*/
24
25#include <ctype.h>
26
27#ifdef TIXML_USE_STL
28#include <sstream>
29#include <iostream>
30#endif
31
32#include "tinyxml.h"
33
34
35bool TiXmlBase::condenseWhiteSpace = true;
36
37void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_STRING* outString )
38{
39        int i=0;
40
41        while( i<(int)str.length() )
42        {
43                unsigned char c = (unsigned char) str[i];
44
45                if (    c == '&' 
46                     && i < ( (int)str.length() - 2 )
47                         && str[i+1] == '#'
48                         && str[i+2] == 'x' )
49                {
50                        // Hexadecimal character reference.
51                        // Pass through unchanged.
52                        // &#xA9;       -- copyright symbol, for example.
53                        //
54                        // The -1 is a bug fix from Rob Laveaux. It keeps
55                        // an overflow from happening if there is no ';'.
56                        // There are actually 2 ways to exit this loop -
57                        // while fails (error case) and break (semicolon found).
58                        // However, there is no mechanism (currently) for
59                        // this function to return an error.
60                        while ( i<(int)str.length()-1 )
61                        {
62                                outString->append( str.c_str() + i, 1 );
63                                ++i;
64                                if ( str[i] == ';' )
65                                        break;
66                        }
67                }
68                else if ( c == '&' )
69                {
70                        outString->append( entity[0].str, entity[0].strLength );
71                        ++i;
72                }
73                else if ( c == '<' )
74                {
75                        outString->append( entity[1].str, entity[1].strLength );
76                        ++i;
77                }
78                else if ( c == '>' )
79                {
80                        outString->append( entity[2].str, entity[2].strLength );
81                        ++i;
82                }
83                else if ( c == '\"' )
84                {
85                        outString->append( entity[3].str, entity[3].strLength );
86                        ++i;
87                }
88                else if ( c == '\'' )
89                {
90                        outString->append( entity[4].str, entity[4].strLength );
91                        ++i;
92                }
93                else if ( c < 32 )
94                {
95                        // Easy pass at non-alpha/numeric/symbol
96                        // Below 32 is symbolic.
97                        char buf[ 32 ];
98                       
99                        #if defined(TIXML_SNPRINTF)             
100                                TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) );
101                        #else
102                                sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
103                        #endif         
104
105                        //*ME:  warning C4267: convert 'size_t' to 'int'
106                        //*ME:  Int-Cast to make compiler happy ...
107                        outString->append( buf, (int)strlen( buf ) );
108                        ++i;
109                }
110                else
111                {
112                        //char realc = (char) c;
113                        //outString->append( &realc, 1 );
114                        *outString += (char) c; // somewhat more efficient function call.
115                        ++i;
116                }
117        }
118}
119
120
121TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
122{
123        parent = 0;
124        type = _type;
125        firstChild = 0;
126        lastChild = 0;
127        prev = 0;
128        next = 0;
129}
130
131
132TiXmlNode::~TiXmlNode()
133{
134        TiXmlNode* node = firstChild;
135        TiXmlNode* temp = 0;
136
137        while ( node )
138        {
139                temp = node;
140                node = node->next;
141                delete temp;
142        }       
143}
144
145
146void TiXmlNode::CopyTo( TiXmlNode* target ) const
147{
148        target->SetValue (value.c_str() );
149        target->userData = userData; 
150}
151
152
153void TiXmlNode::Clear()
154{
155        TiXmlNode* node = firstChild;
156        TiXmlNode* temp = 0;
157
158        while ( node )
159        {
160                temp = node;
161                node = node->next;
162                delete temp;
163        }       
164
165        firstChild = 0;
166        lastChild = 0;
167}
168
169
170TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
171{
172        assert( node->parent == 0 || node->parent == this );
173        assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
174
175        if ( node->Type() == TiXmlNode::DOCUMENT )
176        {
177                delete node;
178                if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
179                return 0;
180        }
181
182        node->parent = this;
183
184        node->prev = lastChild;
185        node->next = 0;
186
187        if ( lastChild )
188                lastChild->next = node;
189        else
190                firstChild = node;                      // it was an empty list.
191
192        lastChild = node;
193        return node;
194}
195
196
197TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
198{
199        if ( addThis.Type() == TiXmlNode::DOCUMENT )
200        {
201                if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
202                return 0;
203        }
204        TiXmlNode* node = addThis.Clone();
205        if ( !node )
206                return 0;
207
208        return LinkEndChild( node );
209}
210
211
212TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
213{       
214        if ( !beforeThis || beforeThis->parent != this ) {
215                return 0;
216        }
217        if ( addThis.Type() == TiXmlNode::DOCUMENT )
218        {
219                if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
220                return 0;
221        }
222
223        TiXmlNode* node = addThis.Clone();
224        if ( !node )
225                return 0;
226        node->parent = this;
227
228        node->next = beforeThis;
229        node->prev = beforeThis->prev;
230        if ( beforeThis->prev )
231        {
232                beforeThis->prev->next = node;
233        }
234        else
235        {
236                assert( firstChild == beforeThis );
237                firstChild = node;
238        }
239        beforeThis->prev = node;
240        return node;
241}
242
243
244TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
245{
246        if ( !afterThis || afterThis->parent != this ) {
247                return 0;
248        }
249        if ( addThis.Type() == TiXmlNode::DOCUMENT )
250        {
251                if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
252                return 0;
253        }
254
255        TiXmlNode* node = addThis.Clone();
256        if ( !node )
257                return 0;
258        node->parent = this;
259
260        node->prev = afterThis;
261        node->next = afterThis->next;
262        if ( afterThis->next )
263        {
264                afterThis->next->prev = node;
265        }
266        else
267        {
268                assert( lastChild == afterThis );
269                lastChild = node;
270        }
271        afterThis->next = node;
272        return node;
273}
274
275
276TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
277{
278        if ( replaceThis->parent != this )
279                return 0;
280
281        TiXmlNode* node = withThis.Clone();
282        if ( !node )
283                return 0;
284
285        node->next = replaceThis->next;
286        node->prev = replaceThis->prev;
287
288        if ( replaceThis->next )
289                replaceThis->next->prev = node;
290        else
291                lastChild = node;
292
293        if ( replaceThis->prev )
294                replaceThis->prev->next = node;
295        else
296                firstChild = node;
297
298        delete replaceThis;
299        node->parent = this;
300        return node;
301}
302
303
304bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
305{
306        if ( removeThis->parent != this )
307        {       
308                assert( 0 );
309                return false;
310        }
311
312        if ( removeThis->next )
313                removeThis->next->prev = removeThis->prev;
314        else
315                lastChild = removeThis->prev;
316
317        if ( removeThis->prev )
318                removeThis->prev->next = removeThis->next;
319        else
320                firstChild = removeThis->next;
321
322        delete removeThis;
323        return true;
324}
325
326const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const
327{
328        const TiXmlNode* node;
329        for ( node = firstChild; node; node = node->next )
330        {
331                if ( strcmp( node->Value(), _value ) == 0 )
332                        return node;
333        }
334        return 0;
335}
336
337
338const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
339{
340        const TiXmlNode* node;
341        for ( node = lastChild; node; node = node->prev )
342        {
343                if ( strcmp( node->Value(), _value ) == 0 )
344                        return node;
345        }
346        return 0;
347}
348
349
350const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const
351{
352        if ( !previous )
353        {
354                return FirstChild();
355        }
356        else
357        {
358                assert( previous->parent == this );
359                return previous->NextSibling();
360        }
361}
362
363
364const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const
365{
366        if ( !previous )
367        {
368                return FirstChild( val );
369        }
370        else
371        {
372                assert( previous->parent == this );
373                return previous->NextSibling( val );
374        }
375}
376
377
378const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const 
379{
380        const TiXmlNode* node;
381        for ( node = next; node; node = node->next )
382        {
383                if ( strcmp( node->Value(), _value ) == 0 )
384                        return node;
385        }
386        return 0;
387}
388
389
390const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
391{
392        const TiXmlNode* node;
393        for ( node = prev; node; node = node->prev )
394        {
395                if ( strcmp( node->Value(), _value ) == 0 )
396                        return node;
397        }
398        return 0;
399}
400
401
402void TiXmlElement::RemoveAttribute( const char * name )
403{
404    #ifdef TIXML_USE_STL
405        TIXML_STRING str( name );
406        TiXmlAttribute* node = attributeSet.Find( str );
407        #else
408        TiXmlAttribute* node = attributeSet.Find( name );
409        #endif
410        if ( node )
411        {
412                attributeSet.Remove( node );
413                delete node;
414        }
415}
416
417const TiXmlElement* TiXmlNode::FirstChildElement() const
418{
419        const TiXmlNode* node;
420
421        for (   node = FirstChild();
422                        node;
423                        node = node->NextSibling() )
424        {
425                if ( node->ToElement() )
426                        return node->ToElement();
427        }
428        return 0;
429}
430
431
432const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
433{
434        const TiXmlNode* node;
435
436        for (   node = FirstChild( _value );
437                        node;
438                        node = node->NextSibling( _value ) )
439        {
440                if ( node->ToElement() )
441                        return node->ToElement();
442        }
443        return 0;
444}
445
446
447const TiXmlElement* TiXmlNode::NextSiblingElement() const
448{
449        const TiXmlNode* node;
450
451        for (   node = NextSibling();
452                        node;
453                        node = node->NextSibling() )
454        {
455                if ( node->ToElement() )
456                        return node->ToElement();
457        }
458        return 0;
459}
460
461
462const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
463{
464        const TiXmlNode* node;
465
466        for (   node = NextSibling( _value );
467                        node;
468                        node = node->NextSibling( _value ) )
469        {
470                if ( node->ToElement() )
471                        return node->ToElement();
472        }
473        return 0;
474}
475
476
477const TiXmlDocument* TiXmlNode::GetDocument() const
478{
479        const TiXmlNode* node;
480
481        for( node = this; node; node = node->parent )
482        {
483                if ( node->ToDocument() )
484                        return node->ToDocument();
485        }
486        return 0;
487}
488
489
490TiXmlElement::TiXmlElement (const char * _value)
491        : TiXmlNode( TiXmlNode::ELEMENT )
492{
493        firstChild = lastChild = 0;
494        value = _value;
495}
496
497
498#ifdef TIXML_USE_STL
499TiXmlElement::TiXmlElement( const std::string& _value ) 
500        : TiXmlNode( TiXmlNode::ELEMENT )
501{
502        firstChild = lastChild = 0;
503        value = _value;
504}
505#endif
506
507
508TiXmlElement::TiXmlElement( const TiXmlElement& copy)
509        : TiXmlNode( TiXmlNode::ELEMENT )
510{
511        firstChild = lastChild = 0;
512        copy.CopyTo( this );   
513}
514
515
516void TiXmlElement::operator=( const TiXmlElement& base )
517{
518        ClearThis();
519        base.CopyTo( this );
520}
521
522
523TiXmlElement::~TiXmlElement()
524{
525        ClearThis();
526}
527
528
529void TiXmlElement::ClearThis()
530{
531        Clear();
532        while( attributeSet.First() )
533        {
534                TiXmlAttribute* node = attributeSet.First();
535                attributeSet.Remove( node );
536                delete node;
537        }
538}
539
540
541const char* TiXmlElement::Attribute( const char* name ) const
542{
543        const TiXmlAttribute* node = attributeSet.Find( name );
544        if ( node )
545                return node->Value();
546        return 0;
547}
548
549
550#ifdef TIXML_USE_STL
551const std::string* TiXmlElement::Attribute( const std::string& name ) const
552{
553        const TiXmlAttribute* node = attributeSet.Find( name );
554        if ( node )
555                return &node->ValueStr();
556        return 0;
557}
558#endif
559
560
561const char* TiXmlElement::Attribute( const char* name, int* i ) const
562{
563        const char* s = Attribute( name );
564        if ( i )
565        {
566                if ( s ) {
567                        *i = atoi( s );
568                }
569                else {
570                        *i = 0;
571                }
572        }
573        return s;
574}
575
576
577#ifdef TIXML_USE_STL
578const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const
579{
580        const std::string* s = Attribute( name );
581        if ( i )
582        {
583                if ( s ) {
584                        *i = atoi( s->c_str() );
585                }
586                else {
587                        *i = 0;
588                }
589        }
590        return s;
591}
592#endif
593
594
595const char* TiXmlElement::Attribute( const char* name, double* d ) const
596{
597        const char* s = Attribute( name );
598        if ( d )
599        {
600                if ( s ) {
601                        *d = atof( s );
602                }
603                else {
604                        *d = 0;
605                }
606        }
607        return s;
608}
609
610
611#ifdef TIXML_USE_STL
612const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const
613{
614        const std::string* s = Attribute( name );
615        if ( d )
616        {
617                if ( s ) {
618                        *d = atof( s->c_str() );
619                }
620                else {
621                        *d = 0;
622                }
623        }
624        return s;
625}
626#endif
627
628
629int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
630{
631        const TiXmlAttribute* node = attributeSet.Find( name );
632        if ( !node )
633                return TIXML_NO_ATTRIBUTE;
634        return node->QueryIntValue( ival );
635}
636
637
638#ifdef TIXML_USE_STL
639int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const
640{
641        const TiXmlAttribute* node = attributeSet.Find( name );
642        if ( !node )
643                return TIXML_NO_ATTRIBUTE;
644        return node->QueryIntValue( ival );
645}
646#endif
647
648
649int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
650{
651        const TiXmlAttribute* node = attributeSet.Find( name );
652        if ( !node )
653                return TIXML_NO_ATTRIBUTE;
654        return node->QueryDoubleValue( dval );
655}
656
657
658#ifdef TIXML_USE_STL
659int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const
660{
661        const TiXmlAttribute* node = attributeSet.Find( name );
662        if ( !node )
663                return TIXML_NO_ATTRIBUTE;
664        return node->QueryDoubleValue( dval );
665}
666#endif
667
668
669void TiXmlElement::SetAttribute( const char * name, int val )
670{       
671        char buf[64];
672        #if defined(TIXML_SNPRINTF)             
673                TIXML_SNPRINTF( buf, sizeof(buf), "%d", val );
674        #else
675                sprintf( buf, "%d", val );
676        #endif
677        SetAttribute( name, buf );
678}
679
680
681#ifdef TIXML_USE_STL
682void TiXmlElement::SetAttribute( const std::string& name, int val )
683{       
684   std::ostringstream oss;
685   oss << val;
686   SetAttribute( name, oss.str() );
687}
688#endif
689
690
691void TiXmlElement::SetDoubleAttribute( const char * name, double val )
692{       
693        char buf[256];
694        #if defined(TIXML_SNPRINTF)             
695                TIXML_SNPRINTF( buf, sizeof(buf), "%f", val );
696        #else
697                sprintf( buf, "%f", val );
698        #endif
699        SetAttribute( name, buf );
700}
701
702
703void TiXmlElement::SetAttribute( const char * cname, const char * cvalue )
704{
705    #ifdef TIXML_USE_STL
706        TIXML_STRING _name( cname );
707        TIXML_STRING _value( cvalue );
708        #else
709        const char* _name = cname;
710        const char* _value = cvalue;
711        #endif
712
713        TiXmlAttribute* node = attributeSet.Find( _name );
714        if ( node )
715        {
716                node->SetValue( _value );
717                return;
718        }
719
720        TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue );
721        if ( attrib )
722        {
723                attributeSet.Add( attrib );
724        }
725        else
726        {
727                TiXmlDocument* document = GetDocument();
728                if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
729        }
730}
731
732
733#ifdef TIXML_USE_STL
734void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value )
735{
736        TiXmlAttribute* node = attributeSet.Find( name );
737        if ( node )
738        {
739                node->SetValue( _value );
740                return;
741        }
742
743        TiXmlAttribute* attrib = new TiXmlAttribute( name, _value );
744        if ( attrib )
745        {
746                attributeSet.Add( attrib );
747        }
748        else
749        {
750                TiXmlDocument* document = GetDocument();
751                if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
752        }
753}
754#endif
755
756
757void TiXmlElement::Print( FILE* cfile, int depth ) const
758{
759        int i;
760        assert( cfile );
761        for ( i=0; i<depth; i++ ) {
762                fprintf( cfile, "    " );
763        }
764
765        fprintf( cfile, "<%s", value.c_str() );
766
767        const TiXmlAttribute* attrib;
768        for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
769        {
770                fprintf( cfile, " " );
771                attrib->Print( cfile, depth );
772        }
773
774        // There are 3 different formatting approaches:
775        // 1) An element without children is printed as a <foo /> node
776        // 2) An element with only a text child is printed as <foo> text </foo>
777        // 3) An element with children is printed on multiple lines.
778        TiXmlNode* node;
779        if ( !firstChild )
780        {
781                fprintf( cfile, " />" );
782        }
783        else if ( firstChild == lastChild && firstChild->ToText() )
784        {
785                fprintf( cfile, ">" );
786                firstChild->Print( cfile, depth + 1 );
787                fprintf( cfile, "</%s>", value.c_str() );
788        }
789        else
790        {
791                fprintf( cfile, ">" );
792
793                for ( node = firstChild; node; node=node->NextSibling() )
794                {
795                        if ( !node->ToText() )
796                        {
797                                fprintf( cfile, "\n" );
798                        }
799                        node->Print( cfile, depth+1 );
800                }
801                fprintf( cfile, "\n" );
802                for( i=0; i<depth; ++i ) {
803                        fprintf( cfile, "    " );
804                }
805                fprintf( cfile, "</%s>", value.c_str() );
806        }
807}
808
809
810void TiXmlElement::CopyTo( TiXmlElement* target ) const
811{
812        // superclass:
813        TiXmlNode::CopyTo( target );
814
815        // Element class:
816        // Clone the attributes, then clone the children.
817        const TiXmlAttribute* attribute = 0;
818        for(    attribute = attributeSet.First();
819        attribute;
820        attribute = attribute->Next() )
821        {
822                target->SetAttribute( attribute->Name(), attribute->Value() );
823        }
824
825        TiXmlNode* node = 0;
826        for ( node = firstChild; node; node = node->NextSibling() )
827        {
828                target->LinkEndChild( node->Clone() );
829        }
830}
831
832bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const
833{
834        if ( visitor->VisitEnter( *this, attributeSet.First() ) ) 
835        {
836                for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
837                {
838                        if ( !node->Accept( visitor ) )
839                                break;
840                }
841        }
842        return visitor->VisitExit( *this );
843}
844
845
846TiXmlNode* TiXmlElement::Clone() const
847{
848        TiXmlElement* clone = new TiXmlElement( Value() );
849        if ( !clone )
850                return 0;
851
852        CopyTo( clone );
853        return clone;
854}
855
856
857const char* TiXmlElement::GetText() const
858{
859        const TiXmlNode* child = this->FirstChild();
860        if ( child ) {
861                const TiXmlText* childText = child->ToText();
862                if ( childText ) {
863                        return childText->Value();
864                }
865        }
866        return 0;
867}
868
869
870TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
871{
872        tabsize = 4;
873        useMicrosoftBOM = false;
874        ClearError();
875}
876
877TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
878{
879        tabsize = 4;
880        useMicrosoftBOM = false;
881        value = documentName;
882        ClearError();
883}
884
885
886#ifdef TIXML_USE_STL
887TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
888{
889        tabsize = 4;
890        useMicrosoftBOM = false;
891    value = documentName;
892        ClearError();
893}
894#endif
895
896
897TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT )
898{
899        copy.CopyTo( this );
900}
901
902
903void TiXmlDocument::operator=( const TiXmlDocument& copy )
904{
905        Clear();
906        copy.CopyTo( this );
907}
908
909
910bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
911{
912        // See STL_STRING_BUG below.
913        //StringToBuffer buf( value );
914
915        return LoadFile( Value(), encoding );
916}
917
918
919bool TiXmlDocument::SaveFile() const
920{
921        // See STL_STRING_BUG below.
922//      StringToBuffer buf( value );
923//
924//      if ( buf.buffer && SaveFile( buf.buffer ) )
925//              return true;
926//
927//      return false;
928        return SaveFile( Value() );
929}
930
931bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
932{
933        // There was a really terrifying little bug here. The code:
934        //              value = filename
935        // in the STL case, cause the assignment method of the std::string to
936        // be called. What is strange, is that the std::string had the same
937        // address as it's c_str() method, and so bad things happen. Looks
938        // like a bug in the Microsoft STL implementation.
939        // Add an extra string to avoid the crash.
940        TIXML_STRING filename( _filename );
941        value = filename;
942
943        // reading in binary mode so that tinyxml can normalize the EOL
944        FILE* file = fopen( value.c_str (), "rb" );     
945
946        if ( file )
947        {
948                bool result = LoadFile( file, encoding );
949                fclose( file );
950                return result;
951        }
952        else
953        {
954                SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
955                return false;
956        }
957}
958
959bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
960{
961        if ( !file ) 
962        {
963                SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
964                return false;
965        }
966
967        // Delete the existing data:
968        Clear();
969        location.Clear();
970
971        // Get the file size, so we can pre-allocate the string. HUGE speed impact.
972        long length = 0;
973        fseek( file, 0, SEEK_END );
974        length = ftell( file );
975        fseek( file, 0, SEEK_SET );
976
977        // Strange case, but good to handle up front.
978        if ( length == 0 )
979        {
980                SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
981                return false;
982        }
983
984        // If we have a file, assume it is all one big XML file, and read it in.
985        // The document parser may decide the document ends sooner than the entire file, however.
986        TIXML_STRING data;
987        data.reserve( length );
988
989        // Subtle bug here. TinyXml did use fgets. But from the XML spec:
990        // 2.11 End-of-Line Handling
991        // <snip>
992        // <quote>
993        // ...the XML processor MUST behave as if it normalized all line breaks in external
994        // parsed entities (including the document entity) on input, before parsing, by translating
995        // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
996        // a single #xA character.
997        // </quote>
998        //
999        // It is not clear fgets does that, and certainly isn't clear it works cross platform.
1000        // Generally, you expect fgets to translate from the convention of the OS to the c/unix
1001        // convention, and not work generally.
1002
1003        /*
1004        while( fgets( buf, sizeof(buf), file ) )
1005        {
1006                data += buf;
1007        }
1008        */
1009
1010        char* buf = new char[ length+1 ];
1011        buf[0] = 0;
1012
1013        if ( fread( buf, length, 1, file ) != 1 ) {
1014                delete [] buf;
1015                SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
1016                return false;
1017        }
1018
1019        const char* lastPos = buf;
1020        const char* p = buf;
1021
1022        buf[length] = 0;
1023        while( *p ) {
1024                assert( p < (buf+length) );
1025                if ( *p == 0xa ) {
1026                        // Newline character. No special rules for this. Append all the characters
1027                        // since the last string, and include the newline.
1028                        data.append( lastPos, (p-lastPos+1) );  // append, include the newline
1029                        ++p;                                                                    // move past the newline
1030                        lastPos = p;                                                    // and point to the new buffer (may be 0)
1031                        assert( p <= (buf+length) );
1032                }
1033                else if ( *p == 0xd ) {
1034                        // Carriage return. Append what we have so far, then
1035                        // handle moving forward in the buffer.
1036                        if ( (p-lastPos) > 0 ) {
1037                                data.append( lastPos, p-lastPos );      // do not add the CR
1038                        }
1039                        data += (char)0xa;                                              // a proper newline
1040
1041                        if ( *(p+1) == 0xa ) {
1042                                // Carriage return - new line sequence
1043                                p += 2;
1044                                lastPos = p;
1045                                assert( p <= (buf+length) );
1046                        }
1047                        else {
1048                                // it was followed by something else...that is presumably characters again.
1049                                ++p;
1050                                lastPos = p;
1051                                assert( p <= (buf+length) );
1052                        }
1053                }
1054                else {
1055                        ++p;
1056                }
1057        }
1058        // Handle any left over characters.
1059        if ( p-lastPos ) {
1060                data.append( lastPos, p-lastPos );
1061        }               
1062        delete [] buf;
1063        buf = 0;
1064
1065        Parse( data.c_str(), 0, encoding );
1066
1067        if (  Error() )
1068        return false;
1069    else
1070                return true;
1071}
1072
1073
1074bool TiXmlDocument::SaveFile( const char * filename ) const
1075{
1076        // The old c stuff lives on...
1077        FILE* fp = fopen( filename, "w" );
1078        if ( fp )
1079        {
1080                bool result = SaveFile( fp );
1081                fclose( fp );
1082                return result;
1083        }
1084        return false;
1085}
1086
1087
1088bool TiXmlDocument::SaveFile( FILE* fp ) const
1089{
1090        if ( useMicrosoftBOM ) 
1091        {
1092                const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
1093                const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
1094                const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
1095
1096                fputc( TIXML_UTF_LEAD_0, fp );
1097                fputc( TIXML_UTF_LEAD_1, fp );
1098                fputc( TIXML_UTF_LEAD_2, fp );
1099        }
1100        Print( fp, 0 );
1101        return (ferror(fp) == 0);
1102}
1103
1104
1105void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
1106{
1107        TiXmlNode::CopyTo( target );
1108
1109        target->error = error;
1110        target->errorDesc = errorDesc.c_str ();
1111
1112        TiXmlNode* node = 0;
1113        for ( node = firstChild; node; node = node->NextSibling() )
1114        {
1115                target->LinkEndChild( node->Clone() );
1116        }       
1117}
1118
1119
1120TiXmlNode* TiXmlDocument::Clone() const
1121{
1122        TiXmlDocument* clone = new TiXmlDocument();
1123        if ( !clone )
1124                return 0;
1125
1126        CopyTo( clone );
1127        return clone;
1128}
1129
1130
1131void TiXmlDocument::Print( FILE* cfile, int depth ) const
1132{
1133        assert( cfile );
1134        for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
1135        {
1136                node->Print( cfile, depth );
1137                fprintf( cfile, "\n" );
1138        }
1139}
1140
1141
1142bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const
1143{
1144        if ( visitor->VisitEnter( *this ) )
1145        {
1146                for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
1147                {
1148                        if ( !node->Accept( visitor ) )
1149                                break;
1150                }
1151        }
1152        return visitor->VisitExit( *this );
1153}
1154
1155
1156const TiXmlAttribute* TiXmlAttribute::Next() const
1157{
1158        // We are using knowledge of the sentinel. The sentinel
1159        // have a value or name.
1160        if ( next->value.empty() && next->name.empty() )
1161                return 0;
1162        return next;
1163}
1164
1165/*
1166TiXmlAttribute* TiXmlAttribute::Next()
1167{
1168        // We are using knowledge of the sentinel. The sentinel
1169        // have a value or name.
1170        if ( next->value.empty() && next->name.empty() )
1171                return 0;
1172        return next;
1173}
1174*/
1175
1176const TiXmlAttribute* TiXmlAttribute::Previous() const
1177{
1178        // We are using knowledge of the sentinel. The sentinel
1179        // have a value or name.
1180        if ( prev->value.empty() && prev->name.empty() )
1181                return 0;
1182        return prev;
1183}
1184
1185/*
1186TiXmlAttribute* TiXmlAttribute::Previous()
1187{
1188        // We are using knowledge of the sentinel. The sentinel
1189        // have a value or name.
1190        if ( prev->value.empty() && prev->name.empty() )
1191                return 0;
1192        return prev;
1193}
1194*/
1195
1196void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
1197{
1198        TIXML_STRING n, v;
1199
1200        PutString( name, &n );
1201        PutString( value, &v );
1202
1203        if (value.find ('\"') == TIXML_STRING::npos) {
1204                if ( cfile ) {
1205                fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
1206                }
1207                if ( str ) {
1208                        (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\"";
1209                }
1210        }
1211        else {
1212                if ( cfile ) {
1213                fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
1214                }
1215                if ( str ) {
1216                        (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'";
1217                }
1218        }
1219}
1220
1221
1222int TiXmlAttribute::QueryIntValue( int* ival ) const
1223{
1224        if ( sscanf( value.c_str(), "%d", ival ) == 1 )
1225                return TIXML_SUCCESS;
1226        return TIXML_WRONG_TYPE;
1227}
1228
1229int TiXmlAttribute::QueryDoubleValue( double* dval ) const
1230{
1231        if ( sscanf( value.c_str(), "%lf", dval ) == 1 )
1232                return TIXML_SUCCESS;
1233        return TIXML_WRONG_TYPE;
1234}
1235
1236void TiXmlAttribute::SetIntValue( int _value )
1237{
1238        char buf [64];
1239        #if defined(TIXML_SNPRINTF)             
1240                TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
1241        #else
1242                sprintf (buf, "%d", _value);
1243        #endif
1244        SetValue (buf);
1245}
1246
1247void TiXmlAttribute::SetDoubleValue( double _value )
1248{
1249        char buf [256];
1250        #if defined(TIXML_SNPRINTF)             
1251                TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value);
1252        #else
1253                sprintf (buf, "%lf", _value);
1254        #endif
1255        SetValue (buf);
1256}
1257
1258int TiXmlAttribute::IntValue() const
1259{
1260        return atoi (value.c_str ());
1261}
1262
1263double  TiXmlAttribute::DoubleValue() const
1264{
1265        return atof (value.c_str ());
1266}
1267
1268
1269TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT )
1270{
1271        copy.CopyTo( this );
1272}
1273
1274
1275void TiXmlComment::operator=( const TiXmlComment& base )
1276{
1277        Clear();
1278        base.CopyTo( this );
1279}
1280
1281
1282void TiXmlComment::Print( FILE* cfile, int depth ) const
1283{
1284        assert( cfile );
1285        for ( int i=0; i<depth; i++ )
1286        {
1287                fprintf( cfile,  "    " );
1288        }
1289        fprintf( cfile, "<!--%s-->", value.c_str() );
1290}
1291
1292
1293void TiXmlComment::CopyTo( TiXmlComment* target ) const
1294{
1295        TiXmlNode::CopyTo( target );
1296}
1297
1298
1299bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const
1300{
1301        return visitor->Visit( *this );
1302}
1303
1304
1305TiXmlNode* TiXmlComment::Clone() const
1306{
1307        TiXmlComment* clone = new TiXmlComment();
1308
1309        if ( !clone )
1310                return 0;
1311
1312        CopyTo( clone );
1313        return clone;
1314}
1315
1316
1317void TiXmlText::Print( FILE* cfile, int depth ) const
1318{
1319        assert( cfile );
1320        if ( cdata )
1321        {
1322                int i;
1323                fprintf( cfile, "\n" );
1324                for ( i=0; i<depth; i++ ) {
1325                        fprintf( cfile, "    " );
1326                }
1327                fprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() );    // unformatted output
1328        }
1329        else
1330        {
1331                TIXML_STRING buffer;
1332                PutString( value, &buffer );
1333                fprintf( cfile, "%s", buffer.c_str() );
1334        }
1335}
1336
1337
1338void TiXmlText::CopyTo( TiXmlText* target ) const
1339{
1340        TiXmlNode::CopyTo( target );
1341        target->cdata = cdata;
1342}
1343
1344
1345bool TiXmlText::Accept( TiXmlVisitor* visitor ) const
1346{
1347        return visitor->Visit( *this );
1348}
1349
1350
1351TiXmlNode* TiXmlText::Clone() const
1352{       
1353        TiXmlText* clone = 0;
1354        clone = new TiXmlText( "" );
1355
1356        if ( !clone )
1357                return 0;
1358
1359        CopyTo( clone );
1360        return clone;
1361}
1362
1363
1364TiXmlDeclaration::TiXmlDeclaration( const char * _version,
1365                                                                        const char * _encoding,
1366                                                                        const char * _standalone )
1367        : TiXmlNode( TiXmlNode::DECLARATION )
1368{
1369        version = _version;
1370        encoding = _encoding;
1371        standalone = _standalone;
1372}
1373
1374
1375#ifdef TIXML_USE_STL
1376TiXmlDeclaration::TiXmlDeclaration(     const std::string& _version,
1377                                                                        const std::string& _encoding,
1378                                                                        const std::string& _standalone )
1379        : TiXmlNode( TiXmlNode::DECLARATION )
1380{
1381        version = _version;
1382        encoding = _encoding;
1383        standalone = _standalone;
1384}
1385#endif
1386
1387
1388TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
1389        : TiXmlNode( TiXmlNode::DECLARATION )
1390{
1391        copy.CopyTo( this );   
1392}
1393
1394
1395void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
1396{
1397        Clear();
1398        copy.CopyTo( this );
1399}
1400
1401
1402void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
1403{
1404        if ( cfile ) fprintf( cfile, "<?xml " );
1405        if ( str )       (*str) += "<?xml ";
1406
1407        if ( !version.empty() ) {
1408                if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ());
1409                if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; }
1410        }
1411        if ( !encoding.empty() ) {
1412                if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
1413                if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; }
1414        }
1415        if ( !standalone.empty() ) {
1416                if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
1417                if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; }
1418        }
1419        if ( cfile ) fprintf( cfile, "?>" );
1420        if ( str )       (*str) += "?>";
1421}
1422
1423
1424void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
1425{
1426        TiXmlNode::CopyTo( target );
1427
1428        target->version = version;
1429        target->encoding = encoding;
1430        target->standalone = standalone;
1431}
1432
1433
1434bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const
1435{
1436        return visitor->Visit( *this );
1437}
1438
1439
1440TiXmlNode* TiXmlDeclaration::Clone() const
1441{       
1442        TiXmlDeclaration* clone = new TiXmlDeclaration();
1443
1444        if ( !clone )
1445                return 0;
1446
1447        CopyTo( clone );
1448        return clone;
1449}
1450
1451
1452void TiXmlUnknown::Print( FILE* cfile, int depth ) const
1453{
1454        for ( int i=0; i<depth; i++ )
1455                fprintf( cfile, "    " );
1456        fprintf( cfile, "<%s>", value.c_str() );
1457}
1458
1459
1460void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
1461{
1462        TiXmlNode::CopyTo( target );
1463}
1464
1465
1466bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const
1467{
1468        return visitor->Visit( *this );
1469}
1470
1471
1472TiXmlNode* TiXmlUnknown::Clone() const
1473{
1474        TiXmlUnknown* clone = new TiXmlUnknown();
1475
1476        if ( !clone )
1477                return 0;
1478
1479        CopyTo( clone );
1480        return clone;
1481}
1482
1483
1484TiXmlAttributeSet::TiXmlAttributeSet()
1485{
1486        sentinel.next = &sentinel;
1487        sentinel.prev = &sentinel;
1488}
1489
1490
1491TiXmlAttributeSet::~TiXmlAttributeSet()
1492{
1493        assert( sentinel.next == &sentinel );
1494        assert( sentinel.prev == &sentinel );
1495}
1496
1497
1498void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
1499{
1500    #ifdef TIXML_USE_STL
1501        assert( !Find( TIXML_STRING( addMe->Name() ) ) );       // Shouldn't be multiply adding to the set.
1502        #else
1503        assert( !Find( addMe->Name() ) );       // Shouldn't be multiply adding to the set.
1504        #endif
1505
1506        addMe->next = &sentinel;
1507        addMe->prev = sentinel.prev;
1508
1509        sentinel.prev->next = addMe;
1510        sentinel.prev      = addMe;
1511}
1512
1513void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
1514{
1515        TiXmlAttribute* node;
1516
1517        for( node = sentinel.next; node != &sentinel; node = node->next )
1518        {
1519                if ( node == removeMe )
1520                {
1521                        node->prev->next = node->next;
1522                        node->next->prev = node->prev;
1523                        node->next = 0;
1524                        node->prev = 0;
1525                        return;
1526                }
1527        }
1528        assert( 0 );            // we tried to remove a non-linked attribute.
1529}
1530
1531
1532#ifdef TIXML_USE_STL
1533const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
1534{
1535        for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1536        {
1537                if ( node->name == name )
1538                        return node;
1539        }
1540        return 0;
1541}
1542
1543/*
1544TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name )
1545{
1546        for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1547        {
1548                if ( node->name == name )
1549                        return node;
1550        }
1551        return 0;
1552}
1553*/
1554#endif
1555
1556
1557const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const
1558{
1559        for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1560        {
1561                if ( strcmp( node->name.c_str(), name ) == 0 )
1562                        return node;
1563        }
1564        return 0;
1565}
1566
1567/*
1568TiXmlAttribute* TiXmlAttributeSet::Find( const char* name )
1569{
1570        for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1571        {
1572                if ( strcmp( node->name.c_str(), name ) == 0 )
1573                        return node;
1574        }
1575        return 0;
1576}
1577*/
1578
1579#ifdef TIXML_USE_STL   
1580std::istream& operator>> (std::istream & in, TiXmlNode & base)
1581{
1582        TIXML_STRING tag;
1583        tag.reserve( 8 * 1000 );
1584        base.StreamIn( &in, &tag );
1585
1586        base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
1587        return in;
1588}
1589#endif
1590
1591
1592#ifdef TIXML_USE_STL   
1593std::ostream& operator<< (std::ostream & out, const TiXmlNode & base)
1594{
1595        TiXmlPrinter printer;
1596        printer.SetStreamPrinting();
1597        base.Accept( &printer );
1598        out << printer.Str();
1599
1600        return out;
1601}
1602
1603
1604std::string& operator<< (std::string& out, const TiXmlNode& base )
1605{
1606        TiXmlPrinter printer;
1607        printer.SetStreamPrinting();
1608        base.Accept( &printer );
1609        out.append( printer.Str() );
1610
1611        return out;
1612}
1613#endif
1614
1615
1616TiXmlHandle TiXmlHandle::FirstChild() const
1617{
1618        if ( node )
1619        {
1620                TiXmlNode* child = node->FirstChild();
1621                if ( child )
1622                        return TiXmlHandle( child );
1623        }
1624        return TiXmlHandle( 0 );
1625}
1626
1627
1628TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
1629{
1630        if ( node )
1631        {
1632                TiXmlNode* child = node->FirstChild( value );
1633                if ( child )
1634                        return TiXmlHandle( child );
1635        }
1636        return TiXmlHandle( 0 );
1637}
1638
1639
1640TiXmlHandle TiXmlHandle::FirstChildElement() const
1641{
1642        if ( node )
1643        {
1644                TiXmlElement* child = node->FirstChildElement();
1645                if ( child )
1646                        return TiXmlHandle( child );
1647        }
1648        return TiXmlHandle( 0 );
1649}
1650
1651
1652TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
1653{
1654        if ( node )
1655        {
1656                TiXmlElement* child = node->FirstChildElement( value );
1657                if ( child )
1658                        return TiXmlHandle( child );
1659        }
1660        return TiXmlHandle( 0 );
1661}
1662
1663
1664TiXmlHandle TiXmlHandle::Child( int count ) const
1665{
1666        if ( node )
1667        {
1668                int i;
1669                TiXmlNode* child = node->FirstChild();
1670                for (   i=0;
1671                                child && i<count;
1672                                child = child->NextSibling(), ++i )
1673                {
1674                        // nothing
1675                }
1676                if ( child )
1677                        return TiXmlHandle( child );
1678        }
1679        return TiXmlHandle( 0 );
1680}
1681
1682
1683TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
1684{
1685        if ( node )
1686        {
1687                int i;
1688                TiXmlNode* child = node->FirstChild( value );
1689                for (   i=0;
1690                                child && i<count;
1691                                child = child->NextSibling( value ), ++i )
1692                {
1693                        // nothing
1694                }
1695                if ( child )
1696                        return TiXmlHandle( child );
1697        }
1698        return TiXmlHandle( 0 );
1699}
1700
1701
1702TiXmlHandle TiXmlHandle::ChildElement( int count ) const
1703{
1704        if ( node )
1705        {
1706                int i;
1707                TiXmlElement* child = node->FirstChildElement();
1708                for (   i=0;
1709                                child && i<count;
1710                                child = child->NextSiblingElement(), ++i )
1711                {
1712                        // nothing
1713                }
1714                if ( child )
1715                        return TiXmlHandle( child );
1716        }
1717        return TiXmlHandle( 0 );
1718}
1719
1720
1721TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
1722{
1723        if ( node )
1724        {
1725                int i;
1726                TiXmlElement* child = node->FirstChildElement( value );
1727                for (   i=0;
1728                                child && i<count;
1729                                child = child->NextSiblingElement( value ), ++i )
1730                {
1731                        // nothing
1732                }
1733                if ( child )
1734                        return TiXmlHandle( child );
1735        }
1736        return TiXmlHandle( 0 );
1737}
1738
1739
1740bool TiXmlPrinter::VisitEnter( const TiXmlDocument& )
1741{
1742        return true;
1743}
1744
1745bool TiXmlPrinter::VisitExit( const TiXmlDocument& )
1746{
1747        return true;
1748}
1749
1750bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute )
1751{
1752        DoIndent();
1753        buffer += "<";
1754        buffer += element.Value();
1755
1756        for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() )
1757        {
1758                buffer += " ";
1759                attrib->Print( 0, 0, &buffer );
1760        }
1761
1762        if ( !element.FirstChild() ) 
1763        {
1764                buffer += " />";
1765                DoLineBreak();
1766        }
1767        else 
1768        {
1769                buffer += ">";
1770                if (    element.FirstChild()->ToText()
1771                          && element.LastChild() == element.FirstChild()
1772                          && element.FirstChild()->ToText()->CDATA() == false )
1773                {
1774                        simpleTextPrint = true;
1775                        // no DoLineBreak()!
1776                }
1777                else
1778                {
1779                        DoLineBreak();
1780                }
1781        }
1782        ++depth;       
1783        return true;
1784}
1785
1786
1787bool TiXmlPrinter::VisitExit( const TiXmlElement& element )
1788{
1789        --depth;
1790        if ( !element.FirstChild() ) 
1791        {
1792                // nothing.
1793        }
1794        else 
1795        {
1796                if ( simpleTextPrint )
1797                {
1798                        simpleTextPrint = false;
1799                }
1800                else
1801                {
1802                        DoIndent();
1803                }
1804                buffer += "</";
1805                buffer += element.Value();
1806                buffer += ">";
1807                DoLineBreak();
1808        }
1809        return true;
1810}
1811
1812
1813bool TiXmlPrinter::Visit( const TiXmlText& text )
1814{
1815        if ( text.CDATA() )
1816        {
1817                DoIndent();
1818                buffer += "<![CDATA[";
1819                buffer += text.Value();
1820                buffer += "]]>";
1821                DoLineBreak();
1822        }
1823        else if ( simpleTextPrint )
1824        {
1825                buffer += text.Value();
1826        }
1827        else
1828        {
1829                DoIndent();
1830                buffer += text.Value();
1831                DoLineBreak();
1832        }
1833        return true;
1834}
1835
1836
1837bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration )
1838{
1839        DoIndent();
1840        declaration.Print( 0, 0, &buffer );
1841        DoLineBreak();
1842        return true;
1843}
1844
1845
1846bool TiXmlPrinter::Visit( const TiXmlComment& comment )
1847{
1848        DoIndent();
1849        buffer += "<!--";
1850        buffer += comment.Value();
1851        buffer += "-->";
1852        DoLineBreak();
1853        return true;
1854}
1855
1856
1857bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown )
1858{
1859        DoIndent();
1860        buffer += "<";
1861        buffer += unknown.Value();
1862        buffer += ">";
1863        DoLineBreak();
1864        return true;
1865}
1866
Note: See TracBrowser for help on using the repository browser.