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