Orocos Real-Time Toolkit  2.9.0
tinyxmlparser.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: Peter Soetens do nov 2 13:06:01 CET 2006 tinyxmlparser.cpp
3 
4  tinyxmlparser.cpp - description
5  -------------------
6  begin : do november 02 2006
7  copyright : (C) 2006 Peter Soetens
8  email : peter.soetens@gmail.com
9 
10  ***************************************************************************
11  * This library is free software; you can redistribute it and/or *
12  * modify it under the terms of the GNU General Public *
13  * License as published by the Free Software Foundation; *
14  * version 2 of the License. *
15  * *
16  * As a special exception, you may use this file as part of a free *
17  * software library without restriction. Specifically, if other files *
18  * instantiate templates or use macros or inline functions from this *
19  * file, or you compile this file and link it with other files to *
20  * produce an executable, this file does not by itself cause the *
21  * resulting executable to be covered by the GNU General Public *
22  * License. This exception does not however invalidate any other *
23  * reasons why the executable file might be covered by the GNU General *
24  * Public License. *
25  * *
26  * This library is distributed in the hope that it will be useful, *
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
29  * Lesser General Public License for more details. *
30  * *
31  * You should have received a copy of the GNU General Public *
32  * License along with this library; if not, write to the Free Software *
33  * Foundation, Inc., 59 Temple Place, *
34  * Suite 330, Boston, MA 02111-1307 USA *
35  * *
36  ***************************************************************************/
37 
38 
39 /*
40 www.sourceforge.net/projects/tinyxml
41 Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
42 
43 This software is provided 'as-is', without any express or implied
44 warranty. In no event will the authors be held liable for any
45 damages arising from the use of this software.
46 
47 Permission is granted to anyone to use this software for any
48 purpose, including commercial applications, and to alter it and
49 redistribute it freely, subject to the following restrictions:
50 
51 1. The origin of this software must not be misrepresented; you must
52 not claim that you wrote the original software. If you use this
53 software in a product, an acknowledgment in the product documentation
54 would be appreciated but is not required.
55 
56 2. Altered source versions must be plainly marked as such, and
57 must not be misrepresented as being the original software.
58 
59 3. This notice may not be removed or altered from any source
60 distribution.
61 */
62 
63 #include "tinyxml.h"
64 #include <ctype.h>
65 #include <stddef.h>
66 
67 //#define DEBUG_PARSER
68 #if defined( DEBUG_PARSER )
69 # if defined( DEBUG ) && defined( _MSC_VER )
70 # include <windows.h>
71 # define TIXML_LOG OutputDebugString
72 # else
73 # define TIXML_LOG printf
74 # endif
75 #endif
76 
77 namespace RTT { namespace marsh {
78 
79 // Note tha "PutString" hardcodes the same list. This
80 // is less flexible than it appears. Changing the entries
81 // or order will break putstring.
82 TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] =
83 {
84  { "&amp;", 5, '&' },
85  { "&lt;", 4, '<' },
86  { "&gt;", 4, '>' },
87  { "&quot;", 6, '\"' },
88  { "&apos;", 6, '\'' }
89 };
90 
91 // Bunch of unicode info at:
92 // http://www.unicode.org/faq/utf_bom.html
93 // Including the basic of this table, which determines the #bytes in the
94 // sequence from the lead byte. 1 placed for invalid sequences --
95 // although the result will be junk, pass it through as much as possible.
96 // Beware of the non-characters in UTF-8:
97 // ef bb bf (Microsoft "lead bytes")
98 // ef bf be
99 // ef bf bf
100 
101 const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
102 const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
103 const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
104 
105 const int TiXmlBase::utf8ByteTable[256] =
106 {
107  // 0 1 2 3 4 5 6 7 8 9 a b c d e f
108  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00
109  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10
110  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20
111  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30
112  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40
113  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50
114  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60
115  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range
116  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid
117  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90
118  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0
119  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0
120  1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte
121  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0
122  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte
123  4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid
124 };
125 
126 
127 void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length )
128 {
129  const unsigned long BYTE_MASK = 0xBF;
130  const unsigned long BYTE_MARK = 0x80;
131  const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
132 
133  if (input < 0x80)
134  *length = 1;
135  else if ( input < 0x800 )
136  *length = 2;
137  else if ( input < 0x10000 )
138  *length = 3;
139  else if ( input < 0x200000 )
140  *length = 4;
141  else
142  { *length = 0; return; } // This code won't covert this correctly anyway.
143 
144  output += *length;
145 
146  // Scary scary fall throughs.
147  switch (*length)
148  {
149  case 4:
150  --output;
151  *output = (char)((input | BYTE_MARK) & BYTE_MASK);
152  input >>= 6;
153  case 3:
154  --output;
155  *output = (char)((input | BYTE_MARK) & BYTE_MASK);
156  input >>= 6;
157  case 2:
158  --output;
159  *output = (char)((input | BYTE_MARK) & BYTE_MASK);
160  input >>= 6;
161  case 1:
162  --output;
163  *output = (char)(input | FIRST_BYTE_MARK[*length]);
164  }
165 }
166 
167 
168 /*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ )
169 {
170  // This will only work for low-ascii, everything else is assumed to be a valid
171  // letter. I'm not sure this is the best approach, but it is quite tricky trying
172  // to figure out alhabetical vs. not across encoding. So take a very
173  // conservative approach.
174 
175 // if ( encoding == TIXML_ENCODING_UTF8 )
176 // {
177  if ( anyByte < 127 )
178  return isalpha( anyByte );
179  else
180  return 1; // What else to do? The unicode set is huge...get the english ones right.
181 // }
182 // else
183 // {
184 // return isalpha( anyByte );
185 // }
186 }
187 
188 
189 /*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ )
190 {
191  // This will only work for low-ascii, everything else is assumed to be a valid
192  // letter. I'm not sure this is the best approach, but it is quite tricky trying
193  // to figure out alhabetical vs. not across encoding. So take a very
194  // conservative approach.
195 
196 // if ( encoding == TIXML_ENCODING_UTF8 )
197 // {
198  if ( anyByte < 127 )
199  return isalnum( anyByte );
200  else
201  return 1; // What else to do? The unicode set is huge...get the english ones right.
202 // }
203 // else
204 // {
205 // return isalnum( anyByte );
206 // }
207 }
208 
209 
211 {
212  friend class TiXmlDocument;
213  public:
214  void Stamp( const char* now, TiXmlEncoding encoding );
215 
216  const TiXmlCursor& Cursor() { return cursor; }
217 
218  private:
219  // Only used by the document!
220  TiXmlParsingData( const char* start, int _tabsize, int row, int col )
221  {
222  assert( start );
223  stamp = start;
224  tabsize = _tabsize;
225  cursor.row = row;
226  cursor.col = col;
227  }
228 
229  TiXmlCursor cursor;
230  const char* stamp;
231  int tabsize;
232 };
233 
234 
235 void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding )
236 {
237  assert( now );
238 
239  // Do nothing if the tabsize is 0.
240  if ( tabsize < 1 )
241  {
242  return;
243  }
244 
245  // Get the current row, column.
246  int row = cursor.row;
247  int col = cursor.col;
248  const char* p = stamp;
249  assert( p );
250 
251  while ( p < now )
252  {
253  // Treat p as unsigned, so we have a happy compiler.
254  const unsigned char* pU = (const unsigned char*)p;
255 
256  // Code contributed by Fletcher Dunn: (modified by lee)
257  switch (*pU) {
258  case 0:
259  // We *should* never get here, but in case we do, don't
260  // advance past the terminating null character, ever
261  return;
262 
263  case '\r':
264  // bump down to the next line
265  ++row;
266  col = 0;
267  // Eat the character
268  ++p;
269 
270  // Check for \r\n sequence, and treat this as a single character
271  if (*p == '\n') {
272  ++p;
273  }
274  break;
275 
276  case '\n':
277  // bump down to the next line
278  ++row;
279  col = 0;
280 
281  // Eat the character
282  ++p;
283 
284  // Check for \n\r sequence, and treat this as a single
285  // character. (Yes, this bizarre thing does occur still
286  // on some arcane platforms...)
287  if (*p == '\r') {
288  ++p;
289  }
290  break;
291 
292  case '\t':
293  // Eat the character
294  ++p;
295 
296  // Skip to next tab stop
297  col = (col / tabsize + 1) * tabsize;
298  break;
299 
300  case TIXML_UTF_LEAD_0:
301  if ( encoding == TIXML_ENCODING_UTF8 )
302  {
303  if ( *(p+1) && *(p+2) )
304  {
305  // In these cases, don't advance the column. These are
306  // 0-width spaces.
307  if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 )
308  p += 3;
309  else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU )
310  p += 3;
311  else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU )
312  p += 3;
313  else
314  { p +=3; ++col; } // A normal character.
315  }
316  }
317  else
318  {
319  ++p;
320  ++col;
321  }
322  break;
323 
324  default:
325  if ( encoding == TIXML_ENCODING_UTF8 )
326  {
327  // Eat the 1 to 4 byte utf8 character.
328  int step = TiXmlBase::utf8ByteTable[*((unsigned char*)p)];
329  if ( step == 0 )
330  step = 1; // Error case from bad encoding, but handle gracefully.
331  p += step;
332 
333  // Just advance one column, of course.
334  ++col;
335  }
336  else
337  {
338  ++p;
339  ++col;
340  }
341  break;
342  }
343  }
344  cursor.row = row;
345  cursor.col = col;
346  assert( cursor.row >= -1 );
347  assert( cursor.col >= -1 );
348  stamp = p;
349  assert( stamp );
350 }
351 
352 
353 const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding )
354 {
355  if ( !p || !*p )
356  {
357  return 0;
358  }
359  if ( encoding == TIXML_ENCODING_UTF8 )
360  {
361  while ( *p )
362  {
363  const unsigned char* pU = (const unsigned char*)p;
364 
365  // Skip the stupid Microsoft UTF-8 Byte order marks
366  if ( *(pU+0)==TIXML_UTF_LEAD_0
367  && *(pU+1)==TIXML_UTF_LEAD_1
368  && *(pU+2)==TIXML_UTF_LEAD_2 )
369  {
370  p += 3;
371  continue;
372  }
373  else if(*(pU+0)==TIXML_UTF_LEAD_0
374  && *(pU+1)==0xbfU
375  && *(pU+2)==0xbeU )
376  {
377  p += 3;
378  continue;
379  }
380  else if(*(pU+0)==TIXML_UTF_LEAD_0
381  && *(pU+1)==0xbfU
382  && *(pU+2)==0xbfU )
383  {
384  p += 3;
385  continue;
386  }
387 
388  if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) // Still using old rules for white space.
389  ++p;
390  else
391  break;
392  }
393  }
394  else
395  {
396  while ( *p && (IsWhiteSpace( *p ) || *p == '\n' || *p =='\r') )
397  ++p;
398  }
399 
400  return p;
401 }
402 
403 #ifdef TIXML_USE_STL
404 /*static*/ bool TiXmlBase::StreamWhiteSpace( TIXML_ISTREAM * in, TIXML_STRING * tag )
405 {
406  for( ;; )
407  {
408  if ( !in->good() ) return false;
409 
410  int c = in->peek();
411  // At this scope, we can't get to a document. So fail silently.
412  if ( !IsWhiteSpace( c ) || c <= 0 )
413  return true;
414 
415  *tag += (char) in->get();
416  }
417 }
418 
419 /*static*/ bool TiXmlBase::StreamTo( TIXML_ISTREAM * in, int character, TIXML_STRING * tag )
420 {
421  //assert( character > 0 && character < 128 ); // else it won't work in utf-8
422  while ( in->good() )
423  {
424  int c = in->peek();
425  if ( c == character )
426  return true;
427  if ( c <= 0 ) // Silent failure: can't get document at this scope
428  return false;
429 
430  in->get();
431  *tag += (char) c;
432  }
433  return false;
434 }
435 #endif
436 
437 const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding )
438 {
439  *name = "";
440  assert( p );
441 
442  // Names start with letters or underscores.
443  // Of course, in unicode, tinyxml has no idea what a letter *is*. The
444  // algorithm is generous.
445  //
446  // After that, they can be letters, underscores, numbers,
447  // hyphens, or colons. (Colons are valid ony for namespaces,
448  // but tinyxml can't tell namespaces from names.)
449  if ( p && *p
450  && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) )
451  {
452  while( p && *p
453  && ( IsAlphaNum( (unsigned char ) *p, encoding )
454  || *p == '_'
455  || *p == '-'
456  || *p == '.'
457  || *p == ':' ) )
458  {
459  (*name) += *p;
460  ++p;
461  }
462  return p;
463  }
464  return 0;
465 }
466 
467 const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding )
468 {
469  // Presume an entity, and pull it out.
470  TIXML_STRING ent;
471  int i;
472  *length = 0;
473 
474  if ( *(p+1) && *(p+1) == '#' && *(p+2) )
475  {
476  unsigned long ucs = 0;
477  ptrdiff_t delta = 0;
478  unsigned mult = 1;
479 
480  if ( *(p+2) == 'x' )
481  {
482  // Hexadecimal.
483  if ( !*(p+3) ) return 0;
484 
485  const char* q = p+3;
486  q = strchr( q, ';' );
487 
488  if ( !q || !*q ) return 0;
489 
490  delta = q-p;
491  --q;
492 
493  while ( *q != 'x' )
494  {
495  if ( *q >= '0' && *q <= '9' )
496  ucs += mult * (*q - '0');
497  else if ( *q >= 'a' && *q <= 'f' )
498  ucs += mult * (*q - 'a' + 10);
499  else if ( *q >= 'A' && *q <= 'F' )
500  ucs += mult * (*q - 'A' + 10 );
501  else
502  return 0;
503  mult *= 16;
504  --q;
505  }
506  }
507  else
508  {
509  // Decimal.
510  if ( !*(p+2) ) return 0;
511 
512  const char* q = p+2;
513  q = strchr( q, ';' );
514 
515  if ( !q || !*q ) return 0;
516 
517  delta = q-p;
518  --q;
519 
520  while ( *q != '#' )
521  {
522  if ( *q >= '0' && *q <= '9' )
523  ucs += mult * (*q - '0');
524  else
525  return 0;
526  mult *= 10;
527  --q;
528  }
529  }
530  if ( encoding == TIXML_ENCODING_UTF8 )
531  {
532  // convert the UCS to UTF-8
533  ConvertUTF32ToUTF8( ucs, value, length );
534  }
535  else
536  {
537  *value = (char)ucs;
538  *length = 1;
539  }
540  return p + delta + 1;
541  }
542 
543  // Now try to match it.
544  for( i=0; i<NUM_ENTITY; ++i )
545  {
546  if ( strncmp( entity[i].str, p, entity[i].strLength ) == 0 )
547  {
548  assert( strlen( entity[i].str ) == entity[i].strLength );
549  *value = entity[i].chr;
550  *length = 1;
551  return ( p + entity[i].strLength );
552  }
553  }
554 
555  // So it wasn't an entity, its unrecognized, or something like that.
556  *value = *p; // Don't put back the last one, since we return it!
557  return p+1;
558 }
559 
560 
561 bool TiXmlBase::StringEqual( const char* p,
562  const char* tag,
563  bool ignoreCase,
564  TiXmlEncoding encoding )
565 {
566  assert( p );
567  assert( tag );
568  if ( !p || !*p )
569  {
570  assert( 0 );
571  return false;
572  }
573 
574  const char* q = p;
575 
576  if ( ignoreCase )
577  {
578  while ( *q && *tag && ToLower( *q, encoding ) == ToLower( *tag, encoding ) )
579  {
580  ++q;
581  ++tag;
582  }
583 
584  if ( *tag == 0 )
585  return true;
586  }
587  else
588  {
589  while ( *q && *tag && *q == *tag )
590  {
591  ++q;
592  ++tag;
593  }
594 
595  if ( *tag == 0 ) // Have we found the end of the tag, and everything equal?
596  return true;
597  }
598  return false;
599 }
600 
601 const char* TiXmlBase::ReadText( const char* p,
602  TIXML_STRING * text,
603  bool trimWhiteSpace,
604  const char* endTag,
605  bool caseInsensitive,
606  TiXmlEncoding encoding )
607 {
608  *text = "";
609  if ( !trimWhiteSpace // certain tags always keep whitespace
610  || !condenseWhiteSpace ) // if true, whitespace is always kept
611  {
612  // Keep all the white space.
613  while ( p && *p
614  && !StringEqual( p, endTag, caseInsensitive, encoding )
615  )
616  {
617  int len;
618  char cArr[4] = { 0, 0, 0, 0 };
619  p = GetChar( p, cArr, &len, encoding );
620  text->append( cArr, len );
621  }
622  }
623  else
624  {
625  bool whitespace = false;
626 
627  // Remove leading white space:
628  p = SkipWhiteSpace( p, encoding );
629  while ( p && *p
630  && !StringEqual( p, endTag, caseInsensitive, encoding ) )
631  {
632  if ( *p == '\r' || *p == '\n' )
633  {
634  whitespace = true;
635  ++p;
636  }
637  else if ( IsWhiteSpace( *p ) )
638  {
639  whitespace = true;
640  ++p;
641  }
642  else
643  {
644  // If we've found whitespace, add it before the
645  // new character. Any whitespace just becomes a space.
646  if ( whitespace )
647  {
648  (*text) += ' ';
649  whitespace = false;
650  }
651  int len;
652  char cArr[4] = { 0, 0, 0, 0 };
653  p = GetChar( p, cArr, &len, encoding );
654  if ( len == 1 )
655  (*text) += cArr[0]; // more efficient
656  else
657  text->append( cArr, len );
658  }
659  }
660  }
661  return p + strlen( endTag );
662 }
663 
664 #ifdef TIXML_USE_STL
665 
666 void TiXmlDocument::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
667 {
668  // The basic issue with a document is that we don't know what we're
669  // streaming. Read something presumed to be a tag (and hope), then
670  // identify it, and call the appropriate stream method on the tag.
671  //
672  // This "pre-streaming" will never read the closing ">" so the
673  // sub-tag can orient itself.
674 
675  if ( !StreamTo( in, '<', tag ) )
676  {
678  return;
679  }
680 
681  while ( in->good() )
682  {
683  int tagIndex = (int) tag->length();
684  while ( in->good() && in->peek() != '>' )
685  {
686  int c = in->get();
687  if ( c <= 0 )
688  {
690  break;
691  }
692  (*tag) += (char) c;
693  }
694 
695  if ( in->good() )
696  {
697  // We now have something we presume to be a node of
698  // some sort. Identify it, and call the node to
699  // continue streaming.
700  TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING );
701 
702  if ( node )
703  {
704  node->StreamIn( in, tag );
705  bool isElement = node->ToElement() != 0;
706  delete node;
707  node = 0;
708 
709  // If this is the root element, we're done. Parsing will be
710  // done by the >> operator.
711  if ( isElement )
712  {
713  return;
714  }
715  }
716  else
717  {
718  SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN );
719  return;
720  }
721  }
722  }
723  // We should have returned sooner.
724  SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN );
725 }
726 
727 #endif
728 
729 const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding )
730 {
731  ClearError();
732 
733  // Parse away, at the document level. Since a document
734  // contains nothing but other tags, most of what happens
735  // here is skipping white space.
736  if ( !p || !*p )
737  {
739  return 0;
740  }
741 
742  // Note that, for a document, this needs to come
743  // before the while space skip, so that parsing
744  // starts from the pointer we are given.
745  location.Clear();
746  if ( prevData )
747  {
748  location.row = prevData->cursor.row;
749  location.col = prevData->cursor.col;
750  }
751  else
752  {
753  location.row = 0;
754  location.col = 0;
755  }
756  TiXmlParsingData data( p, TabSize(), location.row, location.col );
757  location = data.Cursor();
758 
759  if ( encoding == TIXML_ENCODING_UNKNOWN )
760  {
761  // Check for the Microsoft UTF-8 lead bytes.
762  const unsigned char* pU = (const unsigned char*)p;
763  if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0
764  && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1
765  && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 )
766  {
767  encoding = TIXML_ENCODING_UTF8;
768  useMicrosoftBOM = true;
769  }
770  }
771 
772  p = SkipWhiteSpace( p, encoding );
773  if ( !p )
774  {
776  return 0;
777  }
778 
779  while ( p && *p )
780  {
781  TiXmlNode* node = Identify( p, encoding );
782  if ( node )
783  {
784  p = node->Parse( p, &data, encoding );
785  LinkEndChild( node );
786  }
787  else
788  {
789  break;
790  }
791 
792  // Did we get encoding info?
793  if ( encoding == TIXML_ENCODING_UNKNOWN
794  && node->ToDeclaration() )
795  {
796  TiXmlDeclaration* dec = node->ToDeclaration();
797  const char* enc = dec->Encoding();
798  assert( enc );
799 
800  if ( *enc == 0 )
801  encoding = TIXML_ENCODING_UTF8;
802  else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) )
803  encoding = TIXML_ENCODING_UTF8;
804  else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) )
805  encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice
806  else
807  encoding = TIXML_ENCODING_LEGACY;
808  }
809 
810  p = SkipWhiteSpace( p, encoding );
811  }
812 
813  // Was this empty?
814  if ( !firstChild ) {
815  SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding );
816  return 0;
817  }
818 
819  // All is well.
820  return p;
821 }
822 
823 void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding )
824 {
825  // The first error in a chain is more accurate - don't set again!
826  if ( error )
827  return;
828 
829  assert( err > 0 && err < TIXML_ERROR_STRING_COUNT );
830  error = true;
831  errorId = err;
832  errorDesc = errorString[ errorId ];
833 
834  errorLocation.Clear();
835  if ( pError && data )
836  {
837  data->Stamp( pError, encoding );
838  errorLocation = data->Cursor();
839  }
840 }
841 
842 
843 TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding )
844 {
845  TiXmlNode* returnNode = 0;
846 
847  p = SkipWhiteSpace( p, encoding );
848  if( !p || !*p || *p != '<' )
849  {
850  return 0;
851  }
852 
853  TiXmlDocument* doc = GetDocument();
854  p = SkipWhiteSpace( p, encoding );
855 
856  if ( !p || !*p )
857  {
858  return 0;
859  }
860 
861  // What is this thing?
862  // - Elements start with a letter or underscore, but xml is reserved.
863  // - Comments: <!--
864  // - Decleration: <?xml
865  // - Everthing else is unknown to tinyxml.
866  //
867 
868  const char* xmlHeader = { "<?xml" };
869  const char* commentHeader = { "<!--" };
870  const char* dtdHeader = { "<!" };
871  const char* cdataHeader = { "<![CDATA[" };
872 
873  if ( StringEqual( p, xmlHeader, true, encoding ) )
874  {
875  #ifdef DEBUG_PARSER
876  TIXML_LOG( "XML parsing Declaration\n" );
877  #endif
878  returnNode = new TiXmlDeclaration();
879  }
880  else if ( StringEqual( p, commentHeader, false, encoding ) )
881  {
882  #ifdef DEBUG_PARSER
883  TIXML_LOG( "XML parsing Comment\n" );
884  #endif
885  returnNode = new TiXmlComment();
886  }
887  else if ( StringEqual( p, cdataHeader, false, encoding ) )
888  {
889  #ifdef DEBUG_PARSER
890  TIXML_LOG( "XML parsing CDATA\n" );
891  #endif
892  TiXmlText* text = new TiXmlText( "" );
893  text->SetCDATA( true );
894  returnNode = text;
895  }
896  else if ( StringEqual( p, dtdHeader, false, encoding ) )
897  {
898  #ifdef DEBUG_PARSER
899  TIXML_LOG( "XML parsing Unknown(1)\n" );
900  #endif
901  returnNode = new TiXmlUnknown();
902  }
903  else if ( IsAlpha( *(p+1), encoding )
904  || *(p+1) == '_' )
905  {
906  #ifdef DEBUG_PARSER
907  TIXML_LOG( "XML parsing Element\n" );
908  #endif
909  returnNode = new TiXmlElement( "" );
910  }
911  else
912  {
913  #ifdef DEBUG_PARSER
914  TIXML_LOG( "XML parsing Unknown(2)\n" );
915  #endif
916  returnNode = new TiXmlUnknown();
917  }
918 
919  if ( returnNode )
920  {
921  // Set the parent, so it can report errors
922  returnNode->parent = this;
923  }
924  else
925  {
926  if ( doc )
928  }
929  return returnNode;
930 }
931 
932 #ifdef TIXML_USE_STL
933 
934 void TiXmlElement::StreamIn (TIXML_ISTREAM * in, TIXML_STRING * tag)
935 {
936  // We're called with some amount of pre-parsing. That is, some of "this"
937  // element is in "tag". Go ahead and stream to the closing ">"
938  while( in->good() )
939  {
940  int c = in->get();
941  if ( c <= 0 )
942  {
943  TiXmlDocument* document = GetDocument();
944  if ( document )
946  return;
947  }
948  (*tag) += (char) c ;
949 
950  if ( c == '>' )
951  break;
952  }
953 
954  if ( tag->length() < 3 ) return;
955 
956  // Okay...if we are a "/>" tag, then we're done. We've read a complete tag.
957  // If not, identify and stream.
958 
959  if ( tag->at( tag->length() - 1 ) == '>'
960  && tag->at( tag->length() - 2 ) == '/' )
961  {
962  // All good!
963  return;
964  }
965  else if ( tag->at( tag->length() - 1 ) == '>' )
966  {
967  // There is more. Could be:
968  // text
969  // closing tag
970  // another node.
971  for ( ;; )
972  {
973  StreamWhiteSpace( in, tag );
974 
975  // Do we have text?
976  if ( in->good() && in->peek() != '<' )
977  {
978  // Yep, text.
979  TiXmlText text( "" );
980  text.StreamIn( in, tag );
981 
982  // What follows text is a closing tag or another node.
983  // Go around again and figure it out.
984  continue;
985  }
986 
987  // We now have either a closing tag...or another node.
988  // We should be at a "<", regardless.
989  if ( !in->good() ) return;
990  assert( in->peek() == '<' );
991  int tagIndex = (int) tag->length();
992 
993  bool closingTag = false;
994  bool firstCharFound = false;
995 
996  for( ;; )
997  {
998  if ( !in->good() )
999  return;
1000 
1001  int c = in->peek();
1002  if ( c <= 0 )
1003  {
1004  TiXmlDocument* document = GetDocument();
1005  if ( document )
1007  return;
1008  }
1009 
1010  if ( c == '>' )
1011  break;
1012 
1013  *tag += (char) c;
1014  in->get();
1015 
1016  if ( !firstCharFound && c != '<' && !IsWhiteSpace( c ) )
1017  {
1018  firstCharFound = true;
1019  if ( c == '/' )
1020  closingTag = true;
1021  }
1022  }
1023  // If it was a closing tag, then read in the closing '>' to clean up the input stream.
1024  // If it was not, the streaming will be done by the tag.
1025  if ( closingTag )
1026  {
1027  if ( !in->good() )
1028  return;
1029 
1030  int c = in->get();
1031  if ( c <= 0 )
1032  {
1033  TiXmlDocument* document = GetDocument();
1034  if ( document )
1036  return;
1037  }
1038  assert( c == '>' );
1039  *tag += (char) c;
1040 
1041  // We are done, once we've found our closing tag.
1042  return;
1043  }
1044  else
1045  {
1046  // If not a closing tag, id it, and stream.
1047  const char* tagloc = tag->c_str() + tagIndex;
1048  TiXmlNode* node = Identify( tagloc, TIXML_DEFAULT_ENCODING );
1049  if ( !node )
1050  return;
1051  node->StreamIn( in, tag );
1052  delete node;
1053  node = 0;
1054 
1055  // No return: go around from the beginning: text, closing tag, or node.
1056  }
1057  }
1058  }
1059 }
1060 #endif
1061 
1062 const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
1063 {
1064  p = SkipWhiteSpace( p, encoding );
1065  TiXmlDocument* document = GetDocument();
1066 
1067  if ( !p || !*p )
1068  {
1069  if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, 0, 0, encoding );
1070  return 0;
1071  }
1072 
1073  if ( data )
1074  {
1075  data->Stamp( p, encoding );
1076  location = data->Cursor();
1077  }
1078 
1079  if ( *p != '<' )
1080  {
1081  if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, p, data, encoding );
1082  return 0;
1083  }
1084 
1085  p = SkipWhiteSpace( p+1, encoding );
1086 
1087  // Read the name.
1088  const char* pErr = p;
1089 
1090  p = ReadName( p, &value, encoding );
1091  if ( !p || !*p )
1092  {
1093  if ( document ) document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, pErr, data, encoding );
1094  return 0;
1095  }
1096 
1097  TIXML_STRING endTag ("</");
1098  endTag += value;
1099  endTag += ">";
1100 
1101  // Check for and read attributes. Also look for an empty
1102  // tag or an end tag.
1103  while ( p && *p )
1104  {
1105  pErr = p;
1106  p = SkipWhiteSpace( p, encoding );
1107  if ( !p || !*p )
1108  {
1109  if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
1110  return 0;
1111  }
1112  if ( *p == '/' )
1113  {
1114  ++p;
1115  // Empty tag.
1116  if ( *p != '>' )
1117  {
1118  if ( document ) document->SetError( TIXML_ERROR_PARSING_EMPTY, p, data, encoding );
1119  return 0;
1120  }
1121  return (p+1);
1122  }
1123  else if ( *p == '>' )
1124  {
1125  // Done with attributes (if there were any.)
1126  // Read the value -- which can include other
1127  // elements -- read the end tag, and return.
1128  ++p;
1129  p = ReadValue( p, data, encoding ); // Note this is an Element method, and will set the error if one happens.
1130  if ( !p || !*p )
1131  return 0;
1132 
1133  // We should find the end tag now
1134  if ( StringEqual( p, endTag.c_str(), false, encoding ) )
1135  {
1136  p += endTag.length();
1137  return p;
1138  }
1139  else
1140  {
1141  if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
1142  return 0;
1143  }
1144  }
1145  else
1146  {
1147  // Try to read an attribute:
1148  TiXmlAttribute* attrib = new TiXmlAttribute();
1149  if ( !attrib )
1150  {
1151  if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, pErr, data, encoding );
1152  return 0;
1153  }
1154 
1155  attrib->SetDocument( document );
1156  const char* pErr = p;
1157  p = attrib->Parse( p, data, encoding );
1158 
1159  if ( !p || !*p )
1160  {
1161  if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding );
1162  delete attrib;
1163  return 0;
1164  }
1165 
1166  // Handle the strange case of double attributes:
1167  TiXmlAttribute* node = attributeSet.Find( attrib->NameTStr() );
1168  if ( node )
1169  {
1170  node->SetValue( attrib->Value() );
1171  delete attrib;
1172  return 0;
1173  }
1174 
1175  attributeSet.Add( attrib );
1176  }
1177  }
1178  return p;
1179 }
1180 
1181 
1182 const char* TiXmlElement::ReadValue( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
1183 {
1184  TiXmlDocument* document = GetDocument();
1185 
1186  // Read in text and elements in any order.
1187  const char* pWithWhiteSpace = p;
1188  p = SkipWhiteSpace( p, encoding );
1189 
1190  while ( p && *p )
1191  {
1192  if ( *p != '<' )
1193  {
1194  // Take what we have, make a text element.
1195  TiXmlText* textNode = new TiXmlText( "" );
1196 
1197  if ( !textNode )
1198  {
1199  if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, encoding );
1200  return 0;
1201  }
1202 
1204  {
1205  p = textNode->Parse( p, data, encoding );
1206  }
1207  else
1208  {
1209  // Special case: we want to keep the white space
1210  // so that leading spaces aren't removed.
1211  p = textNode->Parse( pWithWhiteSpace, data, encoding );
1212  }
1213 
1214  if ( !textNode->Blank() )
1215  LinkEndChild( textNode );
1216  else
1217  delete textNode;
1218  }
1219  else
1220  {
1221  // We hit a '<'
1222  // Have we hit a new element or an end tag? This could also be
1223  // a TiXmlText in the "CDATA" style.
1224  if ( StringEqual( p, "</", false, encoding ) )
1225  {
1226  return p;
1227  }
1228  else
1229  {
1230  TiXmlNode* node = Identify( p, encoding );
1231  if ( node )
1232  {
1233  p = node->Parse( p, data, encoding );
1234  LinkEndChild( node );
1235  }
1236  else
1237  {
1238  return 0;
1239  }
1240  }
1241  }
1242  pWithWhiteSpace = p;
1243  p = SkipWhiteSpace( p, encoding );
1244  }
1245 
1246  if ( !p )
1247  {
1248  if ( document ) document->SetError( TIXML_ERROR_READING_ELEMENT_VALUE, 0, 0, encoding );
1249  }
1250  return p;
1251 }
1252 
1253 
1254 #ifdef TIXML_USE_STL
1255 void TiXmlUnknown::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
1256 {
1257  while ( in->good() )
1258  {
1259  int c = in->get();
1260  if ( c <= 0 )
1261  {
1262  TiXmlDocument* document = GetDocument();
1263  if ( document )
1265  return;
1266  }
1267  (*tag) += (char) c;
1268 
1269  if ( c == '>' )
1270  {
1271  // All is well.
1272  return;
1273  }
1274  }
1275 }
1276 #endif
1277 
1278 
1279 const char* TiXmlUnknown::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
1280 {
1281  TiXmlDocument* document = GetDocument();
1282  p = SkipWhiteSpace( p, encoding );
1283 
1284  if ( data )
1285  {
1286  data->Stamp( p, encoding );
1287  location = data->Cursor();
1288  }
1289  if ( !p || !*p || *p != '<' )
1290  {
1291  if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, p, data, encoding );
1292  return 0;
1293  }
1294  ++p;
1295  value = "";
1296 
1297  while ( p && *p && *p != '>' )
1298  {
1299  value += *p;
1300  ++p;
1301  }
1302 
1303  if ( !p )
1304  {
1305  if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding );
1306  }
1307  if ( *p == '>' )
1308  return p+1;
1309  return p;
1310 }
1311 
1312 #ifdef TIXML_USE_STL
1313 void TiXmlComment::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
1314 {
1315  while ( in->good() )
1316  {
1317  int c = in->get();
1318  if ( c <= 0 )
1319  {
1320  TiXmlDocument* document = GetDocument();
1321  if ( document )
1323  return;
1324  }
1325 
1326  (*tag) += (char) c;
1327 
1328  if ( c == '>'
1329  && tag->at( tag->length() - 2 ) == '-'
1330  && tag->at( tag->length() - 3 ) == '-' )
1331  {
1332  // All is well.
1333  return;
1334  }
1335  }
1336 }
1337 #endif
1338 
1339 
1340 const char* TiXmlComment::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
1341 {
1342  TiXmlDocument* document = GetDocument();
1343  value = "";
1344 
1345  p = SkipWhiteSpace( p, encoding );
1346 
1347  if ( data )
1348  {
1349  data->Stamp( p, encoding );
1350  location = data->Cursor();
1351  }
1352  const char* startTag = "<!--";
1353  const char* endTag = "-->";
1354 
1355  if ( !StringEqual( p, startTag, false, encoding ) )
1356  {
1357  document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding );
1358  return 0;
1359  }
1360  p += strlen( startTag );
1361  p = ReadText( p, &value, false, endTag, false, encoding );
1362  return p;
1363 }
1364 
1365 
1366 const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
1367 {
1368  p = SkipWhiteSpace( p, encoding );
1369  if ( !p || !*p ) return 0;
1370 
1371  int tabsize = 4;
1372  if ( document )
1373  tabsize = document->TabSize();
1374 
1375  if ( data )
1376  {
1377  data->Stamp( p, encoding );
1378  location = data->Cursor();
1379  }
1380  // Read the name, the '=' and the value.
1381  const char* pErr = p;
1382  p = ReadName( p, &name, encoding );
1383  if ( !p || !*p )
1384  {
1385  if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
1386  return 0;
1387  }
1388  p = SkipWhiteSpace( p, encoding );
1389  if ( !p || !*p || *p != '=' )
1390  {
1391  if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
1392  return 0;
1393  }
1394 
1395  ++p; // skip '='
1396  p = SkipWhiteSpace( p, encoding );
1397  if ( !p || !*p )
1398  {
1399  if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
1400  return 0;
1401  }
1402 
1403  const char* end;
1404 
1405  if ( *p == '\'' )
1406  {
1407  ++p;
1408  end = "\'";
1409  p = ReadText( p, &value, false, end, false, encoding );
1410  }
1411  else if ( *p == '"' )
1412  {
1413  ++p;
1414  end = "\"";
1415  p = ReadText( p, &value, false, end, false, encoding );
1416  }
1417  else
1418  {
1419  // All attribute values should be in single or double quotes.
1420  // But this is such a common error that the parser will try
1421  // its best, even without them.
1422  value = "";
1423  while ( p && *p // existence
1424  && !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r' // whitespace
1425  && *p != '/' && *p != '>' ) // tag end
1426  {
1427  value += *p;
1428  ++p;
1429  }
1430  }
1431  return p;
1432 }
1433 
1434 #ifdef TIXML_USE_STL
1435 void TiXmlText::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
1436 {
1437  if ( cdata )
1438  {
1439  int c = in->get();
1440  if ( c <= 0 )
1441  {
1442  TiXmlDocument* document = GetDocument();
1443  if ( document )
1445  return;
1446  }
1447 
1448  (*tag) += (char) c;
1449 
1450  if ( c == '>'
1451  && tag->at( tag->length() - 2 ) == ']'
1452  && tag->at( tag->length() - 3 ) == ']' )
1453  {
1454  // All is well.
1455  return;
1456  }
1457  }
1458  else
1459  {
1460  while ( in->good() )
1461  {
1462  int c = in->peek();
1463  if ( c == '<' )
1464  return;
1465  if ( c <= 0 )
1466  {
1467  TiXmlDocument* document = GetDocument();
1468  if ( document )
1470  return;
1471  }
1472 
1473  (*tag) += (char) c;
1474  in->get();
1475  }
1476  }
1477 }
1478 #endif
1479 
1480 const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
1481 {
1482  value = "";
1483  TiXmlDocument* document = GetDocument();
1484 
1485  if ( data )
1486  {
1487  data->Stamp( p, encoding );
1488  location = data->Cursor();
1489  }
1490 
1491  const char* const startTag = "<![CDATA[";
1492  const char* const endTag = "]]>";
1493 
1494  if ( cdata || StringEqual( p, startTag, false, encoding ) )
1495  {
1496  cdata = true;
1497 
1498  if ( !StringEqual( p, startTag, false, encoding ) )
1499  {
1500  document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding );
1501  return 0;
1502  }
1503  p += strlen( startTag );
1504 
1505  // Keep all the white space, ignore the encoding, etc.
1506  while ( p && *p
1507  && !StringEqual( p, endTag, false, encoding )
1508  )
1509  {
1510  value += *p;
1511  ++p;
1512  }
1513 
1514  TIXML_STRING dummy;
1515  p = ReadText( p, &dummy, false, endTag, false, encoding );
1516  return p;
1517  }
1518  else
1519  {
1520  bool ignoreWhite = true;
1521 
1522  const char* end = "<";
1523  p = ReadText( p, &value, ignoreWhite, end, false, encoding );
1524  if ( p )
1525  return p-1; // don't truncate the '<'
1526  return 0;
1527  }
1528 }
1529 
1530 #ifdef TIXML_USE_STL
1531 void TiXmlDeclaration::StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag )
1532 {
1533  while ( in->good() )
1534  {
1535  int c = in->get();
1536  if ( c <= 0 )
1537  {
1538  TiXmlDocument* document = GetDocument();
1539  if ( document )
1541  return;
1542  }
1543  (*tag) += (char) c;
1544 
1545  if ( c == '>' )
1546  {
1547  // All is well.
1548  return;
1549  }
1550  }
1551 }
1552 #endif
1553 
1554 const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding )
1555 {
1556  p = SkipWhiteSpace( p, _encoding );
1557  // Find the beginning, find the end, and look for
1558  // the stuff in-between.
1559  TiXmlDocument* document = GetDocument();
1560  if ( !p || !*p || !StringEqual( p, "<?xml", true, _encoding ) )
1561  {
1562  if ( document ) document->SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding );
1563  return 0;
1564  }
1565  if ( data )
1566  {
1567  data->Stamp( p, _encoding );
1568  location = data->Cursor();
1569  }
1570  p += 5;
1571 
1572  version = "";
1573  encoding = "";
1574  standalone = "";
1575 
1576  while ( p && *p )
1577  {
1578  if ( *p == '>' )
1579  {
1580  ++p;
1581  return p;
1582  }
1583 
1584  p = SkipWhiteSpace( p, _encoding );
1585  if ( StringEqual( p, "version", true, _encoding ) )
1586  {
1587  TiXmlAttribute attrib;
1588  p = attrib.Parse( p, data, _encoding );
1589  version = attrib.Value();
1590  }
1591  else if ( StringEqual( p, "encoding", true, _encoding ) )
1592  {
1593  TiXmlAttribute attrib;
1594  p = attrib.Parse( p, data, _encoding );
1595  encoding = attrib.Value();
1596  }
1597  else if ( StringEqual( p, "standalone", true, _encoding ) )
1598  {
1599  TiXmlAttribute attrib;
1600  p = attrib.Parse( p, data, _encoding );
1601  standalone = attrib.Value();
1602  }
1603  else
1604  {
1605  // Read over whatever it is.
1606  while( p && *p && *p != '>' && !IsWhiteSpace( *p ) )
1607  ++p;
1608  }
1609  }
1610  return 0;
1611 }
1612 
1613 bool TiXmlText::Blank() const
1614 {
1615  for ( unsigned i=0; i<value.length(); i++ )
1616  if ( !IsWhiteSpace( value[i] ) )
1617  return false;
1618  return true;
1619 }
1620 
1621 }}
const char * Encoding() const
Encoding. Will return an empty string if none was found.
Definition: tinyxml.h:1186
void Stamp(const char *now, TiXmlEncoding encoding)
static int ToLower(int v, TiXmlEncoding encoding)
Definition: tinyxml.h:384
const char * Value() const
Return the value of this attribute.
Definition: tinyxml.h:766
virtual const char * Parse(const char *p, TiXmlParsingData *data, TiXmlEncoding encoding)
TiXmlNode * Identify(const char *start, TiXmlEncoding encoding)
static bool IsWhiteSpace(char c)
Definition: tinyxml.h:284
static const int utf8ByteTable[256]
Definition: tinyxml.h:243
static const char * SkipWhiteSpace(const char *, TiXmlEncoding encoding)
const TIXML_STRING & NameTStr() const
Definition: tinyxml.h:771
static const char * ReadText(const char *in, TIXML_STRING *text, bool ignoreWhiteSpace, const char *endTag, bool ignoreCase, TiXmlEncoding encoding)
An attribute is a name-value pair.
Definition: tinyxml.h:733
Always the top level node.
Definition: tinyxml.h:1259
TiXmlNode * parent
Definition: tinyxml.h:709
const char * ReadValue(const char *in, TiXmlParsingData *prevData, TiXmlEncoding encoding)
An XML comment.
Definition: tinyxml.h:1048
static int IsAlphaNum(unsigned char anyByte, TiXmlEncoding encoding)
static bool StringEqual(const char *p, const char *endTag, bool ignoreCase, TiXmlEncoding encoding)
virtual const char * Parse(const char *p, TiXmlParsingData *data, TiXmlEncoding encoding)
virtual const char * Parse(const char *p, TiXmlParsingData *data=0, TiXmlEncoding encoding=TIXML_DEFAULT_ENCODING)
Parse the given null terminated block of xml data.
void SetCDATA(bool _cdata)
Turns on or off a CDATA representation of text.
Definition: tinyxml.h:1123
The parent class for everything in the Document Object Model.
Definition: tinyxml.h:425
virtual const char * Parse(const char *p, TiXmlParsingData *data, TiXmlEncoding encoding)
static void ConvertUTF32ToUTF8(unsigned long input, char *output, int *length)
TiXmlCursor location
Definition: tinyxml.h:375
static const char * GetEntity(const char *in, char *value, int *length, TiXmlEncoding encoding)
virtual const TiXmlDeclaration * ToDeclaration() const
Cast to a more defined type. Will return null if not of the requested type.
Definition: tinyxml.h:680
virtual const char * Parse(const char *p, TiXmlParsingData *data, TiXmlEncoding encoding)
friend class TiXmlElement
Definition: tinyxml.h:192
void SetError(int err, const char *errorLocation, TiXmlParsingData *prevData, TiXmlEncoding encoding)
void SetDocument(TiXmlDocument *doc)
Definition: tinyxml.h:821
const TiXmlEncoding TIXML_DEFAULT_ENCODING
Definition: tinyxml.h:165
virtual const char * Parse(const char *p, TiXmlParsingData *data, TiXmlEncoding encoding)=0
const unsigned char TIXML_UTF_LEAD_0
const unsigned char TIXML_UTF_LEAD_1
static int IsAlpha(unsigned char anyByte, TiXmlEncoding encoding)
const unsigned char TIXML_UTF_LEAD_2
const TiXmlCursor & Cursor()
void SetValue(const char *_value)
Set the value.
Definition: tinyxml.h:787
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:52
virtual const TiXmlElement * ToElement() const
Cast to a more defined type. Will return null if not of the requested type.
Definition: tinyxml.h:676
In correct XML the declaration is the first entry in the file.
Definition: tinyxml.h:1160
Any tag that tinyXml doesn&#39;t recognize is saved as an unknown.
Definition: tinyxml.h:1223
static const char * ReadName(const char *p, TIXML_STRING *name, TiXmlEncoding encoding)
static const char * GetChar(const char *p, char *_value, int *length, TiXmlEncoding encoding)
Definition: tinyxml.h:323
static const char * errorString[TIXML_ERROR_STRING_COUNT]
Definition: tinyxml.h:373
static bool IsWhiteSpaceCondensed()
Return the current white space setting.
Definition: tinyxml.h:215
virtual const char * Parse(const char *p, TiXmlParsingData *data, TiXmlEncoding encoding)
#define TIXML_STRING
Definition: tinyxml.h:92
virtual const char * Parse(const char *p, TiXmlParsingData *data, TiXmlEncoding encoding)