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