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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers spxmlstag.cpp Source File

spxmlstag.cpp

00001 /*
00002  * Copyright 2007 Stephen Liu
00003  * LGPL, see http://code.google.com/p/spxml/
00004  * For license terms, see the file COPYING along with this library.
00005  */
00006 
00007 #include <stdlib.h>
00008 #include <string.h>
00009 #include <ctype.h>
00010 #include <typeinfo>
00011 
00012 #include "mstring.h"
00013 
00014 #include "spxmlstag.hpp"
00015 #include "spxmlutils.hpp"
00016 #include "spxmlevent.hpp"
00017 #include "spxmlcodec.hpp"
00018 
00019 SP_XmlSTagParser :: SP_XmlSTagParser( const char * encoding )
00020 {
00021     mEvent = new SP_XmlStartTagEvent();
00022     mReader = new SP_XmlSTagNameReader();
00023     mStartTagName = new SP_XmlStringBuffer();
00024     mError = NULL;
00025 
00026     snprintf( mEncoding, sizeof( mEncoding ), "%s", encoding );
00027 }
00028 
00029 SP_XmlSTagParser :: ~SP_XmlSTagParser()
00030 {
00031     if( NULL != mEvent ) delete mEvent;
00032     mEvent = NULL;
00033 
00034     if( NULL != mReader ) delete mReader;
00035     mReader = NULL;
00036 
00037     if( NULL != mStartTagName ) delete mStartTagName;
00038     mStartTagName = NULL;
00039 
00040     if( NULL != mError ) free( mError );
00041     mError = NULL;
00042 }
00043 
00044 const char * SP_XmlSTagParser :: getEncoding()
00045 {
00046     return mEncoding;
00047 }
00048 
00049 SP_XmlStartTagEvent * SP_XmlSTagParser :: takeEvent()
00050 {
00051     SP_XmlStartTagEvent * event = mEvent;
00052 
00053     mEvent = NULL;
00054 
00055     return event;
00056 }
00057 
00058 const char * SP_XmlSTagParser :: getError()
00059 {
00060     return mError;
00061 }
00062 
00063 void SP_XmlSTagParser :: changeReader( SP_XmlSTagReader * reader )
00064 {
00065     delete mReader;
00066     mReader = reader;
00067 }
00068 
00069 void SP_XmlSTagParser :: setError( const char * error )
00070 {
00071     if( NULL != error ) {
00072         if( NULL != mError ) free( mError );
00073         mError = strdup( error );
00074     }
00075 }
00076 
00077 void SP_XmlSTagParser :: append( const char * source, int len )
00078 {
00079     for( int i = 0; i < len && NULL == mError; i++ ) {
00080         mReader->read( this, source[ i ] );
00081     }
00082 }
00083 
00084 //=========================================================
00085 
00086 SP_XmlSTagReader :: SP_XmlSTagReader()
00087 {
00088     mBuffer = new SP_XmlStringBuffer();
00089 }
00090 
00091 SP_XmlSTagReader :: ~SP_XmlSTagReader()
00092 {
00093     delete mBuffer;
00094     mBuffer = NULL;
00095 }
00096 
00097 void SP_XmlSTagReader :: changeReader( SP_XmlSTagParser * parser,
00098         SP_XmlSTagReader * reader )
00099 {
00100     //printf( "\nchange: %s\n", typeid( *reader ).name() );
00101     parser->changeReader( reader );
00102 }
00103 
00104 void SP_XmlSTagReader :: setError( SP_XmlSTagParser * parser, const char * error )
00105 {
00106     parser->setError( error );
00107 }
00108 
00109 void SP_XmlSTagReader :: setName( SP_XmlSTagParser * parser, const char * name )
00110 {
00111     parser->mEvent->setName( name );
00112 }
00113 
00114 void SP_XmlSTagReader :: addAttrName( SP_XmlSTagParser * parser, const char * name )
00115 {
00116     parser->mStartTagName->append( name );
00117 }
00118 
00119 void SP_XmlSTagReader :: addAttrValue( SP_XmlSTagParser * parser, const char * value )
00120 {
00121     SP_XmlStringBuffer decodeValue;
00122     SP_XmlStringCodec::decode( parser->getEncoding(), value, &decodeValue );
00123 
00124     parser->mEvent->addAttr( parser->mStartTagName->getBuffer(), decodeValue.getBuffer() );
00125     parser->mStartTagName->clean();
00126 }
00127 
00128 //=========================================================
00129 
00130 SP_XmlSTagNameReader :: SP_XmlSTagNameReader()
00131 {
00132 }
00133 
00134 SP_XmlSTagNameReader :: ~SP_XmlSTagNameReader()
00135 {
00136 }
00137 
00138 void SP_XmlSTagNameReader :: read( SP_XmlSTagParser * parser, char c )
00139 {
00140     if( isspace( c ) ) {
00141         if( 0 == mBuffer->getSize() ) {
00142             //leading space, skip
00143         } else {
00144             setName( parser, mBuffer->getBuffer() );
00145             changeReader( parser, new SP_XmlSTagAttrNameReader() );
00146         }
00147     } else {
00148         mBuffer->append( c );
00149     }
00150 }
00151 
00152 //=========================================================
00153 
00154 SP_XmlSTagAttrNameReader :: SP_XmlSTagAttrNameReader()
00155 {
00156     mWait4Quot = 0;
00157 }
00158 
00159 SP_XmlSTagAttrNameReader :: ~SP_XmlSTagAttrNameReader()
00160 {
00161 }
00162 
00163 void SP_XmlSTagAttrNameReader :: read( SP_XmlSTagParser * parser, char c )
00164 {
00165     if( 1 == mWait4Quot ) {
00166         if( '"' == c ) {
00167             addAttrName( parser, mBuffer->getBuffer() );
00168             changeReader( parser, new SP_XmlSTagEqualMarkReader() );
00169         } else {
00170             mBuffer->append( c );
00171         }
00172     } else {
00173         if( isspace( c ) ) {
00174             if( 0 == mBuffer->getSize() ) {
00175                 //leading space, skip
00176             } else {
00177                 addAttrName( parser, mBuffer->getBuffer() );
00178                 changeReader( parser, new SP_XmlSTagEqualMarkReader() );
00179             }
00180         } else {
00181             if( '"' == c && 0 == mBuffer->getSize() ) {
00182                 mWait4Quot = 1;
00183             } else if( '=' == c ) {
00184                 addAttrName( parser, mBuffer->getBuffer() );
00185                 SP_XmlSTagReader * reader = new SP_XmlSTagEqualMarkReader();
00186                 changeReader( parser, reader );
00187                 reader->read( parser, c );
00188             } else {
00189                 mBuffer->append( c );
00190             }
00191         }
00192     }
00193 }
00194 
00195 //=========================================================
00196 
00197 SP_XmlSTagEqualMarkReader :: SP_XmlSTagEqualMarkReader()
00198 {
00199 }
00200 
00201 SP_XmlSTagEqualMarkReader :: ~SP_XmlSTagEqualMarkReader()
00202 {
00203 }
00204 
00205 void SP_XmlSTagEqualMarkReader :: read( SP_XmlSTagParser * parser, char c )
00206 {
00207     if( isspace( c ) ) {
00208         //skip
00209     } else if( '=' == c ) {
00210         changeReader( parser, new SP_XmlSTagAttrValueReader() );
00211     } else {
00212         addAttrValue( parser, "" );
00213         SP_XmlSTagReader * reader = new SP_XmlSTagAttrNameReader();
00214         changeReader( parser, reader );
00215         reader->read( parser, c );
00216 
00217         //setError( parser, "miss '=' between name & value" );
00218     }
00219 }
00220 
00221 //=========================================================
00222 
00223 SP_XmlSTagAttrValueReader :: SP_XmlSTagAttrValueReader()
00224 {
00225     mHasReadQuot = 0;
00226 }
00227 
00228 SP_XmlSTagAttrValueReader :: ~SP_XmlSTagAttrValueReader()
00229 {
00230 }
00231 
00232 void SP_XmlSTagAttrValueReader :: read( SP_XmlSTagParser * parser, char c )
00233 {
00234     if( 0 == mHasReadQuot ) {
00235         if( isspace( c ) ) {
00236             //skip  
00237         } else if( '"' == c ) {
00238             mHasReadQuot = 1;
00239         } else if( '\'' == c ) {
00240             mHasReadQuot = 2;
00241         } else {
00242             setError( parser, "unknown attribute value start" );
00243         }
00244     } else {
00245         if( ( 1 == mHasReadQuot && '"' == c ) 
00246                 || ( 2 == mHasReadQuot && '\'' == c ) ) {
00247             addAttrValue( parser, mBuffer->getBuffer() );
00248             changeReader( parser, new SP_XmlSTagAttrNameReader() );
00249         } else {
00250             mBuffer->append( c );
00251         }
00252     }
00253 }
00254