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
spdomparser.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 <assert.h> 00008 00009 #include "spdomparser.hpp" 00010 #include "spxmlparser.hpp" 00011 #include "spxmlevent.hpp" 00012 #include "spxmlutils.hpp" 00013 #include "spxmlnode.hpp" 00014 #include "spxmlcodec.hpp" 00015 00016 //========================================================= 00017 00018 SP_XmlDomParser :: SP_XmlDomParser() 00019 { 00020 mParser = new SP_XmlPullParser(); 00021 mDocument = new SP_XmlDocument(); 00022 mCurrent = NULL; 00023 } 00024 00025 SP_XmlDomParser :: ~SP_XmlDomParser() 00026 { 00027 if( NULL != mDocument ) delete mDocument; 00028 mDocument = NULL; 00029 00030 if( NULL != mParser ) delete mParser; 00031 mParser = NULL; 00032 } 00033 00034 void SP_XmlDomParser :: setIgnoreWhitespace( int ignoreWhitespace ) 00035 { 00036 mParser->setIgnoreWhitespace( ignoreWhitespace ); 00037 } 00038 00039 int SP_XmlDomParser :: getIgnoreWhitespace() 00040 { 00041 return mParser->getIgnoreWhitespace(); 00042 } 00043 00044 const char * SP_XmlDomParser :: getEncoding() 00045 { 00046 return mParser->getEncoding(); 00047 } 00048 00049 int SP_XmlDomParser :: append( const char * source, int len ) 00050 { 00051 int ret = 0; 00052 00053 for( int pos = 0; pos < len; pos += 64 ) { 00054 int realLen = ( len - pos ) > 64 ? 64 : ( len - pos ); 00055 ret += mParser->append( source + pos, realLen ); 00056 buildTree(); 00057 } 00058 00059 return ret; 00060 } 00061 00062 void SP_XmlDomParser :: buildTree() 00063 { 00064 for( SP_XmlPullEvent * event = mParser->getNext(); 00065 NULL != event; event = mParser->getNext() ) { 00066 00067 switch( event->getEventType() ) { 00068 case SP_XmlPullEvent::eStartDocument: 00069 // ignore 00070 delete event; 00071 break; 00072 case SP_XmlPullEvent::eEndDocument: 00073 // ignore 00074 delete event; 00075 break; 00076 case SP_XmlPullEvent::eDocDecl: 00077 { 00078 mDocument->setDocDecl( 00079 new SP_XmlDocDeclNode( (SP_XmlDocDeclEvent*)event ) ); 00080 break; 00081 } 00082 case SP_XmlPullEvent::eDocType: 00083 { 00084 mDocument->setDocType( 00085 new SP_XmlDocTypeNode( (SP_XmlDocTypeEvent*)event ) ); 00086 break; 00087 } 00088 case SP_XmlPullEvent::eStartTag: 00089 { 00090 SP_XmlElementNode * element = 00091 new SP_XmlElementNode( (SP_XmlStartTagEvent*)event ); 00092 if( NULL == mCurrent ) { 00093 mCurrent = element; 00094 mDocument->setRootElement( element ); 00095 } else { 00096 mCurrent->addChild( element ); 00097 mCurrent = element; 00098 } 00099 break; 00100 } 00101 case SP_XmlPullEvent::eEndTag: 00102 { 00103 SP_XmlNode * parent = (SP_XmlNode*)mCurrent->getParent(); 00104 if( NULL != parent && SP_XmlNode::eELEMENT == parent->getType() ) { 00105 mCurrent = static_cast<SP_XmlElementNode*>((SP_XmlNode*)parent); 00106 } else { 00107 mCurrent = NULL; 00108 } 00109 00110 delete event; 00111 break; 00112 } 00113 case SP_XmlPullEvent::eCData: 00114 { 00115 if( NULL != mCurrent ) { 00116 mCurrent->addChild( new SP_XmlCDataNode( (SP_XmlCDataEvent*)event ) ); 00117 } else { 00118 delete event; 00119 } 00120 break; 00121 } 00122 case SP_XmlPullEvent::eComment: 00123 { 00124 if( NULL != mCurrent ) { 00125 mCurrent->addChild( new SP_XmlCommentNode( (SP_XmlCommentEvent*)event ) ); 00126 } else { 00127 delete event; 00128 } 00129 break; 00130 } 00131 case SP_XmlPIEvent::ePI: 00132 { 00133 if( NULL != mCurrent ) { 00134 mCurrent->addChild( new SP_XmlPINode( (SP_XmlPIEvent*)event ) ); 00135 } else { 00136 mDocument->getChildren()->append( 00137 new SP_XmlPINode( (SP_XmlPIEvent*)event ) ); 00138 } 00139 break; 00140 } 00141 default: 00142 { 00143 assert( 0 ); 00144 break; 00145 } 00146 } 00147 } 00148 } 00149 00150 const char * SP_XmlDomParser :: getError () 00151 { 00152 return mParser->getError(); 00153 } 00154 00155 const SP_XmlDocument * SP_XmlDomParser :: getDocument() const 00156 { 00157 return mDocument; 00158 } 00159 00160 //========================================================= 00161 00162 SP_XmlDomBuffer :: SP_XmlDomBuffer( const SP_XmlNode * node, int indent ) 00163 { 00164 mBuffer = new SP_XmlStringBuffer(); 00165 dump( SP_XmlStringCodec::DEFAULT_ENCODING, node, mBuffer, indent ? 0 : -1 ); 00166 } 00167 00168 SP_XmlDomBuffer :: SP_XmlDomBuffer( const char * encoding, const SP_XmlNode * node, int indent ) 00169 { 00170 mBuffer = new SP_XmlStringBuffer(); 00171 dump( encoding, node, mBuffer, indent ? 0 : -1 ); 00172 } 00173 00174 SP_XmlDomBuffer :: ~SP_XmlDomBuffer() 00175 { 00176 if( NULL != mBuffer ) delete mBuffer; 00177 mBuffer = NULL; 00178 } 00179 00180 const char * SP_XmlDomBuffer :: getBuffer() const 00181 { 00182 return mBuffer->getBuffer(); 00183 } 00184 00185 int SP_XmlDomBuffer :: getSize() const 00186 { 00187 return mBuffer->getSize(); 00188 } 00189 00190 void SP_XmlDomBuffer :: dump( const char * encoding, 00191 const SP_XmlNode * node, SP_XmlStringBuffer * buffer, int level ) 00192 { 00193 if( SP_XmlNode::eXMLDOC == node->getType() ) { 00194 SP_XmlDocument * document = static_cast<SP_XmlDocument*>((SP_XmlNode*)node); 00195 dumpDocDecl( encoding, document->getDocDecl(), buffer, level ); 00196 dumpDocType( encoding, document->getDocType(), buffer, level ); 00197 00198 const SP_XmlNodeList * children = document->getChildren(); 00199 for( int j = 0; j < children->getLength(); j++ ) { 00200 dump( encoding, children->get( j ), buffer, level ); 00201 } 00202 } else if( SP_XmlNode::eCDATA == node->getType() ) { 00203 SP_XmlCDataNode * cdata = static_cast<SP_XmlCDataNode*>((SP_XmlNode*)node); 00204 SP_XmlStringCodec::encode( encoding, cdata->getText(), buffer ); 00205 } else if( SP_XmlNode::eCOMMENT == node->getType() ) { 00206 SP_XmlCommentNode * comment = static_cast<SP_XmlCommentNode*>((SP_XmlNode*)node); 00207 00208 if( level >= 0 ) { 00209 buffer->append( '\n' ); 00210 for( int i = 0; i < level; i++ ) buffer->append( '\t' ); 00211 buffer->append( "<!--" ); 00212 buffer->append( comment->getText() ); 00213 buffer->append( "-->\n" ); 00214 } else { 00215 buffer->append( "<!--" ); 00216 buffer->append( comment->getText() ); 00217 buffer->append( "-->" ); 00218 } 00219 } else if( SP_XmlNode::eELEMENT == node->getType() ) { 00220 dumpElement( encoding, node, buffer, level ); 00221 } else if( SP_XmlNode::eDOCDECL == node->getType() ) { 00222 dumpDocDecl( encoding, (SP_XmlDocDeclNode*)node, buffer, level ); 00223 } else if( SP_XmlNode::eDOCTYPE == node->getType() ) { 00224 dumpDocType( encoding, (SP_XmlDocTypeNode*)node, buffer, level ); 00225 } else if( SP_XmlNode::ePI == node->getType() ) { 00226 SP_XmlPINode * piNode = static_cast<SP_XmlPINode*>((SP_XmlNode*)node); 00227 00228 if( level >= 0 ) { 00229 for( int i = 0; i < level; i++ ) buffer->append( '\t' ); 00230 buffer->append( "<?" ); 00231 buffer->append( piNode->getTarget() ); 00232 buffer->append( ' ' ); 00233 buffer->append( piNode->getData() ); 00234 buffer->append( "?>\n" ); 00235 } else { 00236 buffer->append( "<?" ); 00237 buffer->append( piNode->getTarget() ); 00238 if( '\0' != *( piNode->getTarget() ) ) buffer->append( ' ' ); 00239 buffer->append( piNode->getData() ); 00240 buffer->append( "?>" ); 00241 } 00242 } else { 00243 // ignore 00244 } 00245 } 00246 00247 void SP_XmlDomBuffer :: dumpDocDecl( const char * encoding, 00248 const SP_XmlDocDeclNode * docDecl, 00249 SP_XmlStringBuffer * buffer, int level ) 00250 { 00251 if( NULL == docDecl ) return; 00252 00253 buffer->append( "<?xml version=\"" ); 00254 if( '\0' != * ( docDecl->getVersion() ) ) { 00255 buffer->append( docDecl->getVersion() ); 00256 } else { 00257 buffer->append( "1.0" ); 00258 } 00259 buffer->append( "\" " ); 00260 00261 if( '\0' != * ( docDecl->getEncoding() ) ) { 00262 buffer->append( "encoding=\"" ); 00263 buffer->append( docDecl->getEncoding() ); 00264 buffer->append( "\" " ); 00265 } 00266 00267 if( -1 != docDecl->getStandalone() ) { 00268 char standalone[ 32 ]; 00269 snprintf( standalone, sizeof( standalone ), "standalone=\"%s\" ", 00270 0 == docDecl->getStandalone() ? "no" : "yes" ); 00271 buffer->append( standalone ); 00272 } 00273 00274 buffer->append( level >= 0 ? "?>\n" : "?>" ); 00275 } 00276 00277 void SP_XmlDomBuffer :: dumpDocType( const char * encoding, 00278 const SP_XmlDocTypeNode * docType, 00279 SP_XmlStringBuffer * buffer, int level ) 00280 { 00281 if( NULL == docType ) return; 00282 00283 buffer->append( "<!DOCTYPE " ); 00284 buffer->append( docType->getName() ); 00285 00286 if( '\0' != * ( docType->getPublicID() ) ) { 00287 buffer->append( " PUBLIC " ); 00288 buffer->append( '"' ); 00289 buffer->append( docType->getPublicID() ); 00290 buffer->append( '"' ); 00291 } 00292 00293 if( '\0' != * ( docType->getSystemID() ) ) { 00294 buffer->append( " SYSTEM " ); 00295 buffer->append( '"' ); 00296 buffer->append( docType->getSystemID() ); 00297 buffer->append( '"' ); 00298 } 00299 00300 if( '\0' != * ( docType->getDTD() ) ) { 00301 buffer->append( " \"" ); 00302 buffer->append( docType->getDTD() ); 00303 buffer->append( '"' ); 00304 } 00305 00306 buffer->append( level >= 0 ? ">\n" : ">" ); 00307 } 00308 00309 void SP_XmlDomBuffer :: dumpElement( const char * encoding, 00310 const SP_XmlNode * node, SP_XmlStringBuffer * buffer, int level ) 00311 { 00312 if( NULL == node ) return; 00313 00314 if( SP_XmlNode::eELEMENT == node->getType() ) { 00315 int i = 0; 00316 00317 for( i = 0; i < level; i++ ) buffer->append( '\t' ); 00318 00319 SP_XmlElementNode * element = static_cast<SP_XmlElementNode*>((SP_XmlNode*)node); 00320 buffer->append( "<" ); 00321 buffer->append( element->getName() ); 00322 00323 const char * name = NULL, * value = NULL; 00324 for( i = 0; i < element->getAttrCount(); i++ ) { 00325 name = element->getAttr( i, &value ); 00326 if( NULL != name && NULL != value ) { 00327 buffer->append( ' ' ); 00328 buffer->append( name ); 00329 buffer->append( "=\"" ); 00330 SP_XmlStringCodec::encode( encoding, value, buffer ); 00331 buffer->append( "\"" ); 00332 } 00333 } 00334 00335 const SP_XmlNodeList * children = element->getChildren(); 00336 00337 if( children->getLength() > 0 ) { 00338 if( SP_XmlNode::eCDATA != children->get( 0 )->getType() ) { 00339 buffer->append( level >= 0 ? ">\n" : ">" ); 00340 } else { 00341 buffer->append( ">" ); 00342 } 00343 00344 for( int j = 0; j < children->getLength(); j++ ) { 00345 dump( encoding, children->get( j ), buffer, level >= 0 ? level + 1 : -1 ); 00346 } 00347 00348 if( SP_XmlNode::eCDATA != children->get( 0 )->getType() ) { 00349 for( int i = 0; i < level; i++ ) buffer->append( '\t' ); 00350 } 00351 buffer->append( "</" ); 00352 buffer->append( element->getName() ); 00353 buffer->append( level >= 0 ? ">\n" : ">" ); 00354 } else { 00355 buffer->append( level >= 0 ? "/>\n" : ">" ); 00356 } 00357 } else { 00358 dump( encoding, node, buffer, level ); 00359 } 00360 } 00361
Generated on Sun Jul 17 2022 09:10:11 by 1.7.2