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
spxmlstag.cpp
- Committer:
- hlipka
- Date:
- 2010-11-24
- Revision:
- 0:3fa97f2c0505
File content as of revision 0:3fa97f2c0505:
/* * Copyright 2007 Stephen Liu * LGPL, see http://code.google.com/p/spxml/ * For license terms, see the file COPYING along with this library. */ #include <stdlib.h> #include <string.h> #include <ctype.h> #include <typeinfo> #include "mstring.h" #include "spxmlstag.hpp" #include "spxmlutils.hpp" #include "spxmlevent.hpp" #include "spxmlcodec.hpp" SP_XmlSTagParser :: SP_XmlSTagParser( const char * encoding ) { mEvent = new SP_XmlStartTagEvent(); mReader = new SP_XmlSTagNameReader(); mStartTagName = new SP_XmlStringBuffer(); mError = NULL; snprintf( mEncoding, sizeof( mEncoding ), "%s", encoding ); } SP_XmlSTagParser :: ~SP_XmlSTagParser() { if( NULL != mEvent ) delete mEvent; mEvent = NULL; if( NULL != mReader ) delete mReader; mReader = NULL; if( NULL != mStartTagName ) delete mStartTagName; mStartTagName = NULL; if( NULL != mError ) free( mError ); mError = NULL; } const char * SP_XmlSTagParser :: getEncoding() { return mEncoding; } SP_XmlStartTagEvent * SP_XmlSTagParser :: takeEvent() { SP_XmlStartTagEvent * event = mEvent; mEvent = NULL; return event; } const char * SP_XmlSTagParser :: getError() { return mError; } void SP_XmlSTagParser :: changeReader( SP_XmlSTagReader * reader ) { delete mReader; mReader = reader; } void SP_XmlSTagParser :: setError( const char * error ) { if( NULL != error ) { if( NULL != mError ) free( mError ); mError = strdup( error ); } } void SP_XmlSTagParser :: append( const char * source, int len ) { for( int i = 0; i < len && NULL == mError; i++ ) { mReader->read( this, source[ i ] ); } } //========================================================= SP_XmlSTagReader :: SP_XmlSTagReader() { mBuffer = new SP_XmlStringBuffer(); } SP_XmlSTagReader :: ~SP_XmlSTagReader() { delete mBuffer; mBuffer = NULL; } void SP_XmlSTagReader :: changeReader( SP_XmlSTagParser * parser, SP_XmlSTagReader * reader ) { //printf( "\nchange: %s\n", typeid( *reader ).name() ); parser->changeReader( reader ); } void SP_XmlSTagReader :: setError( SP_XmlSTagParser * parser, const char * error ) { parser->setError( error ); } void SP_XmlSTagReader :: setName( SP_XmlSTagParser * parser, const char * name ) { parser->mEvent->setName( name ); } void SP_XmlSTagReader :: addAttrName( SP_XmlSTagParser * parser, const char * name ) { parser->mStartTagName->append( name ); } void SP_XmlSTagReader :: addAttrValue( SP_XmlSTagParser * parser, const char * value ) { SP_XmlStringBuffer decodeValue; SP_XmlStringCodec::decode( parser->getEncoding(), value, &decodeValue ); parser->mEvent->addAttr( parser->mStartTagName->getBuffer(), decodeValue.getBuffer() ); parser->mStartTagName->clean(); } //========================================================= SP_XmlSTagNameReader :: SP_XmlSTagNameReader() { } SP_XmlSTagNameReader :: ~SP_XmlSTagNameReader() { } void SP_XmlSTagNameReader :: read( SP_XmlSTagParser * parser, char c ) { if( isspace( c ) ) { if( 0 == mBuffer->getSize() ) { //leading space, skip } else { setName( parser, mBuffer->getBuffer() ); changeReader( parser, new SP_XmlSTagAttrNameReader() ); } } else { mBuffer->append( c ); } } //========================================================= SP_XmlSTagAttrNameReader :: SP_XmlSTagAttrNameReader() { mWait4Quot = 0; } SP_XmlSTagAttrNameReader :: ~SP_XmlSTagAttrNameReader() { } void SP_XmlSTagAttrNameReader :: read( SP_XmlSTagParser * parser, char c ) { if( 1 == mWait4Quot ) { if( '"' == c ) { addAttrName( parser, mBuffer->getBuffer() ); changeReader( parser, new SP_XmlSTagEqualMarkReader() ); } else { mBuffer->append( c ); } } else { if( isspace( c ) ) { if( 0 == mBuffer->getSize() ) { //leading space, skip } else { addAttrName( parser, mBuffer->getBuffer() ); changeReader( parser, new SP_XmlSTagEqualMarkReader() ); } } else { if( '"' == c && 0 == mBuffer->getSize() ) { mWait4Quot = 1; } else if( '=' == c ) { addAttrName( parser, mBuffer->getBuffer() ); SP_XmlSTagReader * reader = new SP_XmlSTagEqualMarkReader(); changeReader( parser, reader ); reader->read( parser, c ); } else { mBuffer->append( c ); } } } } //========================================================= SP_XmlSTagEqualMarkReader :: SP_XmlSTagEqualMarkReader() { } SP_XmlSTagEqualMarkReader :: ~SP_XmlSTagEqualMarkReader() { } void SP_XmlSTagEqualMarkReader :: read( SP_XmlSTagParser * parser, char c ) { if( isspace( c ) ) { //skip } else if( '=' == c ) { changeReader( parser, new SP_XmlSTagAttrValueReader() ); } else { addAttrValue( parser, "" ); SP_XmlSTagReader * reader = new SP_XmlSTagAttrNameReader(); changeReader( parser, reader ); reader->read( parser, c ); //setError( parser, "miss '=' between name & value" ); } } //========================================================= SP_XmlSTagAttrValueReader :: SP_XmlSTagAttrValueReader() { mHasReadQuot = 0; } SP_XmlSTagAttrValueReader :: ~SP_XmlSTagAttrValueReader() { } void SP_XmlSTagAttrValueReader :: read( SP_XmlSTagParser * parser, char c ) { if( 0 == mHasReadQuot ) { if( isspace( c ) ) { //skip } else if( '"' == c ) { mHasReadQuot = 1; } else if( '\'' == c ) { mHasReadQuot = 2; } else { setError( parser, "unknown attribute value start" ); } } else { if( ( 1 == mHasReadQuot && '"' == c ) || ( 2 == mHasReadQuot && '\'' == c ) ) { addAttrValue( parser, mBuffer->getBuffer() ); changeReader( parser, new SP_XmlSTagAttrNameReader() ); } else { mBuffer->append( c ); } } }