Mbed port of the Simple Plain Xml parser. See http://code.google.com/p/spxml/ for more details. This library uses less memory and is much better suited to streaming data than TinyXML (doesn\'t use as much C++ features, and especially works without streams). See http://mbed.org/users/hlipka/notebook/xml-parsing/ for usage examples.

Dependents:   spxmltest_weather VFD_fontx2_weather weather_LCD_display News_LCD_display ... more

Committer:
hlipka
Date:
Wed Nov 24 20:52:14 2010 +0000
Revision:
0:3fa97f2c0505
initial revision

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hlipka 0:3fa97f2c0505 1 /*
hlipka 0:3fa97f2c0505 2 * Copyright 2007 Stephen Liu
hlipka 0:3fa97f2c0505 3 * LGPL, see http://code.google.com/p/spxml/
hlipka 0:3fa97f2c0505 4 * For license terms, see the file COPYING along with this library.
hlipka 0:3fa97f2c0505 5 */
hlipka 0:3fa97f2c0505 6
hlipka 0:3fa97f2c0505 7 #include <stdlib.h>
hlipka 0:3fa97f2c0505 8 #include <string.h>
hlipka 0:3fa97f2c0505 9 #include <assert.h>
hlipka 0:3fa97f2c0505 10 #include <typeinfo>
hlipka 0:3fa97f2c0505 11
hlipka 0:3fa97f2c0505 12 #include "mstring.h"
hlipka 0:3fa97f2c0505 13
hlipka 0:3fa97f2c0505 14 #include "spxmlparser.hpp"
hlipka 0:3fa97f2c0505 15 #include "spxmlreader.hpp"
hlipka 0:3fa97f2c0505 16 #include "spxmlutils.hpp"
hlipka 0:3fa97f2c0505 17 #include "spxmlevent.hpp"
hlipka 0:3fa97f2c0505 18 #include "spxmlcodec.hpp"
hlipka 0:3fa97f2c0505 19
hlipka 0:3fa97f2c0505 20 SP_XmlPullParser :: SP_XmlPullParser()
hlipka 0:3fa97f2c0505 21 {
hlipka 0:3fa97f2c0505 22 mReaderPool = new SP_XmlReaderPool();
hlipka 0:3fa97f2c0505 23 mReader = getReader( SP_XmlReader::eLBracket );
hlipka 0:3fa97f2c0505 24 mEventQueue = new SP_XmlPullEventQueue();
hlipka 0:3fa97f2c0505 25 mEventQueue->enqueue( new SP_XmlStartDocEvent() );
hlipka 0:3fa97f2c0505 26
hlipka 0:3fa97f2c0505 27 mRootTagState = eRootNone;
hlipka 0:3fa97f2c0505 28 mTagNameStack = new SP_XmlArrayList();
hlipka 0:3fa97f2c0505 29 mLevel = 0;
hlipka 0:3fa97f2c0505 30
hlipka 0:3fa97f2c0505 31 mIgnoreWhitespace = 1;
hlipka 0:3fa97f2c0505 32
hlipka 0:3fa97f2c0505 33 mError = NULL;
hlipka 0:3fa97f2c0505 34
hlipka 0:3fa97f2c0505 35 memset( mErrorSegment, 0, sizeof( mErrorSegment ) );
hlipka 0:3fa97f2c0505 36 mErrorIndex = 0;
hlipka 0:3fa97f2c0505 37 mRowIndex = mColIndex = 0;
hlipka 0:3fa97f2c0505 38
hlipka 0:3fa97f2c0505 39 memset( mEncoding, 0, sizeof( mEncoding ) );
hlipka 0:3fa97f2c0505 40 }
hlipka 0:3fa97f2c0505 41
hlipka 0:3fa97f2c0505 42 SP_XmlPullParser :: ~SP_XmlPullParser()
hlipka 0:3fa97f2c0505 43 {
hlipka 0:3fa97f2c0505 44 mReaderPool->save( mReader );
hlipka 0:3fa97f2c0505 45
hlipka 0:3fa97f2c0505 46 for( int i = 0; i < mTagNameStack->getCount(); i++ ) {
hlipka 0:3fa97f2c0505 47 free( (char*)mTagNameStack->getItem( i ) );
hlipka 0:3fa97f2c0505 48 }
hlipka 0:3fa97f2c0505 49 delete mTagNameStack;
hlipka 0:3fa97f2c0505 50
hlipka 0:3fa97f2c0505 51 delete mEventQueue;
hlipka 0:3fa97f2c0505 52
hlipka 0:3fa97f2c0505 53 delete mReaderPool;
hlipka 0:3fa97f2c0505 54
hlipka 0:3fa97f2c0505 55 if( NULL != mError ) free( mError );
hlipka 0:3fa97f2c0505 56 }
hlipka 0:3fa97f2c0505 57
hlipka 0:3fa97f2c0505 58 const char * SP_XmlPullParser :: getEncoding()
hlipka 0:3fa97f2c0505 59 {
hlipka 0:3fa97f2c0505 60 if( '\0' == mEncoding[0] ) {
hlipka 0:3fa97f2c0505 61 return SP_XmlStringCodec::DEFAULT_ENCODING;
hlipka 0:3fa97f2c0505 62 }
hlipka 0:3fa97f2c0505 63
hlipka 0:3fa97f2c0505 64 return mEncoding;
hlipka 0:3fa97f2c0505 65 }
hlipka 0:3fa97f2c0505 66
hlipka 0:3fa97f2c0505 67 int SP_XmlPullParser :: append( const char * source, int len )
hlipka 0:3fa97f2c0505 68 {
hlipka 0:3fa97f2c0505 69 if( NULL != mError ) return 0;
hlipka 0:3fa97f2c0505 70
hlipka 0:3fa97f2c0505 71 int consumed = 0;
hlipka 0:3fa97f2c0505 72
hlipka 0:3fa97f2c0505 73 for( int i = 0; i < len && NULL == mError; i++ ) {
hlipka 0:3fa97f2c0505 74
hlipka 0:3fa97f2c0505 75 consumed++;
hlipka 0:3fa97f2c0505 76
hlipka 0:3fa97f2c0505 77 char c = source[ i ];
hlipka 0:3fa97f2c0505 78
hlipka 0:3fa97f2c0505 79 mErrorSegment[ mErrorIndex++ % sizeof( mErrorSegment ) ] = c;
hlipka 0:3fa97f2c0505 80 mReader->read( this, c );
hlipka 0:3fa97f2c0505 81 if( '\n' == c ) {
hlipka 0:3fa97f2c0505 82 mRowIndex++;
hlipka 0:3fa97f2c0505 83 mColIndex = 0;
hlipka 0:3fa97f2c0505 84 } else {
hlipka 0:3fa97f2c0505 85 mColIndex++;
hlipka 0:3fa97f2c0505 86 }
hlipka 0:3fa97f2c0505 87 }
hlipka 0:3fa97f2c0505 88
hlipka 0:3fa97f2c0505 89 return consumed;
hlipka 0:3fa97f2c0505 90 }
hlipka 0:3fa97f2c0505 91
hlipka 0:3fa97f2c0505 92 SP_XmlPullEvent * SP_XmlPullParser :: getNext()
hlipka 0:3fa97f2c0505 93 {
hlipka 0:3fa97f2c0505 94 SP_XmlPullEvent * event = mEventQueue->dequeue();
hlipka 0:3fa97f2c0505 95
hlipka 0:3fa97f2c0505 96 if( NULL != event ) {
hlipka 0:3fa97f2c0505 97 if( SP_XmlPullEvent::eStartTag == event->getEventType() ) mLevel++;
hlipka 0:3fa97f2c0505 98 if( SP_XmlPullEvent::eEndTag == event->getEventType() ) mLevel--;
hlipka 0:3fa97f2c0505 99 }
hlipka 0:3fa97f2c0505 100
hlipka 0:3fa97f2c0505 101 return event;
hlipka 0:3fa97f2c0505 102 }
hlipka 0:3fa97f2c0505 103
hlipka 0:3fa97f2c0505 104 int SP_XmlPullParser :: getLevel()
hlipka 0:3fa97f2c0505 105 {
hlipka 0:3fa97f2c0505 106 return mLevel;
hlipka 0:3fa97f2c0505 107 }
hlipka 0:3fa97f2c0505 108
hlipka 0:3fa97f2c0505 109 void SP_XmlPullParser :: setIgnoreWhitespace( int ignoreWhitespace )
hlipka 0:3fa97f2c0505 110 {
hlipka 0:3fa97f2c0505 111 mIgnoreWhitespace = ignoreWhitespace;
hlipka 0:3fa97f2c0505 112 }
hlipka 0:3fa97f2c0505 113
hlipka 0:3fa97f2c0505 114 int SP_XmlPullParser :: getIgnoreWhitespace()
hlipka 0:3fa97f2c0505 115 {
hlipka 0:3fa97f2c0505 116 return mIgnoreWhitespace;
hlipka 0:3fa97f2c0505 117 }
hlipka 0:3fa97f2c0505 118
hlipka 0:3fa97f2c0505 119 const char * SP_XmlPullParser :: getError()
hlipka 0:3fa97f2c0505 120 {
hlipka 0:3fa97f2c0505 121 return mError;
hlipka 0:3fa97f2c0505 122 }
hlipka 0:3fa97f2c0505 123
hlipka 0:3fa97f2c0505 124 void SP_XmlPullParser :: changeReader( SP_XmlReader * reader )
hlipka 0:3fa97f2c0505 125 {
hlipka 0:3fa97f2c0505 126 SP_XmlPullEvent * event = mReader->getEvent( this );
hlipka 0:3fa97f2c0505 127 if( NULL != event ) {
hlipka 0:3fa97f2c0505 128 if( SP_XmlPullEvent::eStartTag == event->getEventType() ) {
hlipka 0:3fa97f2c0505 129 if( eRootNone == mRootTagState ) mRootTagState = eRootStart;
hlipka 0:3fa97f2c0505 130 const char * name = ((SP_XmlStartTagEvent*)event)->getName();
hlipka 0:3fa97f2c0505 131 mTagNameStack->append( strdup( name ) );
hlipka 0:3fa97f2c0505 132 }
hlipka 0:3fa97f2c0505 133 if( SP_XmlPullEvent::eEndTag == event->getEventType() ) {
hlipka 0:3fa97f2c0505 134 char error[ 256 ] = { 0 };
hlipka 0:3fa97f2c0505 135
hlipka 0:3fa97f2c0505 136 const char * etag = ((SP_XmlEndTagEvent*)event)->getText();
hlipka 0:3fa97f2c0505 137 char * stag = (char*)mTagNameStack->takeItem( SP_XmlArrayList::LAST_INDEX );
hlipka 0:3fa97f2c0505 138 if( NULL != stag ) {
hlipka 0:3fa97f2c0505 139 if( 0 != strcmp( stag, etag ) ) {
hlipka 0:3fa97f2c0505 140 snprintf( error, sizeof( error ),
hlipka 0:3fa97f2c0505 141 "mismatched tag, start-tag <%s>, end-tag <%s>", stag, etag );
hlipka 0:3fa97f2c0505 142 }
hlipka 0:3fa97f2c0505 143 free( stag );
hlipka 0:3fa97f2c0505 144 } else {
hlipka 0:3fa97f2c0505 145 snprintf( error, sizeof( error ),
hlipka 0:3fa97f2c0505 146 "mismatched tag, start-tag <NULL>, end-tag <%s>", etag );
hlipka 0:3fa97f2c0505 147 }
hlipka 0:3fa97f2c0505 148
hlipka 0:3fa97f2c0505 149 if( '\0' != *error ) {
hlipka 0:3fa97f2c0505 150 setError( error );
hlipka 0:3fa97f2c0505 151 delete event;
hlipka 0:3fa97f2c0505 152 event = NULL;
hlipka 0:3fa97f2c0505 153 }
hlipka 0:3fa97f2c0505 154 }
hlipka 0:3fa97f2c0505 155
hlipka 0:3fa97f2c0505 156 if( NULL != event ) {
hlipka 0:3fa97f2c0505 157 if( SP_XmlPullEvent::eDocDecl == event->getEventType() ) {
hlipka 0:3fa97f2c0505 158 snprintf( mEncoding, sizeof( mEncoding ), "%s",
hlipka 0:3fa97f2c0505 159 ((SP_XmlDocDeclEvent*)event)->getEncoding() );
hlipka 0:3fa97f2c0505 160 }
hlipka 0:3fa97f2c0505 161 mEventQueue->enqueue( event );
hlipka 0:3fa97f2c0505 162 if( mTagNameStack->getCount() <= 0 && eRootStart == mRootTagState ) {
hlipka 0:3fa97f2c0505 163 mRootTagState = eRootEnd;
hlipka 0:3fa97f2c0505 164 mEventQueue->enqueue( new SP_XmlEndDocEvent() );
hlipka 0:3fa97f2c0505 165 }
hlipka 0:3fa97f2c0505 166 }
hlipka 0:3fa97f2c0505 167 }
hlipka 0:3fa97f2c0505 168
hlipka 0:3fa97f2c0505 169 //printf( "\nchange: %s -> %s\n", typeid( *mReader ).name(), typeid( *reader ).name() );
hlipka 0:3fa97f2c0505 170
hlipka 0:3fa97f2c0505 171 mReaderPool->save( mReader );
hlipka 0:3fa97f2c0505 172 mReader = reader;
hlipka 0:3fa97f2c0505 173 }
hlipka 0:3fa97f2c0505 174
hlipka 0:3fa97f2c0505 175 SP_XmlReader * SP_XmlPullParser :: getReader( int type )
hlipka 0:3fa97f2c0505 176 {
hlipka 0:3fa97f2c0505 177 return mReaderPool->borrow( type );
hlipka 0:3fa97f2c0505 178 }
hlipka 0:3fa97f2c0505 179
hlipka 0:3fa97f2c0505 180 void SP_XmlPullParser :: setError( const char * error )
hlipka 0:3fa97f2c0505 181 {
hlipka 0:3fa97f2c0505 182 if( NULL != error ) {
hlipka 0:3fa97f2c0505 183 if( NULL != mError ) free( mError );
hlipka 0:3fa97f2c0505 184
hlipka 0:3fa97f2c0505 185 char segment[ 2 * sizeof( mErrorSegment ) + 1 ];
hlipka 0:3fa97f2c0505 186 {
hlipka 0:3fa97f2c0505 187 memset( segment, 0, sizeof( segment ) );
hlipka 0:3fa97f2c0505 188
hlipka 0:3fa97f2c0505 189 char temp[ sizeof( mErrorSegment ) + 1 ];
hlipka 0:3fa97f2c0505 190 memset( temp, 0, sizeof( temp ) );
hlipka 0:3fa97f2c0505 191 if( mErrorIndex < (int)sizeof( mErrorSegment ) ) {
hlipka 0:3fa97f2c0505 192 strncpy( temp, mErrorSegment, mErrorIndex );
hlipka 0:3fa97f2c0505 193 } else {
hlipka 0:3fa97f2c0505 194 int offset = mErrorIndex % sizeof( mErrorSegment );
hlipka 0:3fa97f2c0505 195 strncpy( temp, mErrorSegment + offset, sizeof( mErrorSegment ) - offset );
hlipka 0:3fa97f2c0505 196 strncpy( temp + sizeof( mErrorSegment ) - offset, mErrorSegment, offset );
hlipka 0:3fa97f2c0505 197 }
hlipka 0:3fa97f2c0505 198
hlipka 0:3fa97f2c0505 199 for( char * pos = temp, * dest = segment; '\0' != *pos; pos++ ) {
hlipka 0:3fa97f2c0505 200 if( '\r' == *pos ) {
hlipka 0:3fa97f2c0505 201 *dest++ = '\\';
hlipka 0:3fa97f2c0505 202 *dest++ = 'r';
hlipka 0:3fa97f2c0505 203 } else if( '\n' == *pos ) {
hlipka 0:3fa97f2c0505 204 *dest++ = '\\';
hlipka 0:3fa97f2c0505 205 *dest++ = 'n';
hlipka 0:3fa97f2c0505 206 } else if( '\t' == *pos ) {
hlipka 0:3fa97f2c0505 207 *dest++ = '\\';
hlipka 0:3fa97f2c0505 208 *dest++ = 't';
hlipka 0:3fa97f2c0505 209 } else {
hlipka 0:3fa97f2c0505 210 *dest++ = *pos;
hlipka 0:3fa97f2c0505 211 }
hlipka 0:3fa97f2c0505 212 }
hlipka 0:3fa97f2c0505 213 }
hlipka 0:3fa97f2c0505 214
hlipka 0:3fa97f2c0505 215 char msg[ 512 ];
hlipka 0:3fa97f2c0505 216 snprintf( msg, sizeof( msg), "%s ( occured at row(%d), col(%d) : %s )",
hlipka 0:3fa97f2c0505 217 error, mRowIndex + 1, mColIndex + 1, segment );
hlipka 0:3fa97f2c0505 218
hlipka 0:3fa97f2c0505 219 mError = strdup( msg );
hlipka 0:3fa97f2c0505 220 }
hlipka 0:3fa97f2c0505 221 }
hlipka 0:3fa97f2c0505 222