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