Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/mac_osx/src/external/tinyxml/tinyxml.cpp @ 8749

Last change on this file since 8749 was 6620, checked in by rgrieder, 15 years ago

Updated TinyXML++ to the latest trunk revision.
Only adds a function and corrects a parenthesis bug.

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