source: tmcsimulator/branches/FEPSimulator/tinyxml/tinyxml.cpp @ 80

Revision 80, 36.7 KB checked in by jtorres, 9 years ago (diff)

Renamed project. Renamed LDS_LOOP to STATION.

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