<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html><head><meta name="robots" content="noindex"> <meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"> <title>cpl_minixml.cpp Source File</title> <link href="doxygen.css" rel="stylesheet" type="text/css"> </head><body bgcolor="#ffffff"> <!-- Generated by Doxygen 1.2.3-20001105 on Thu Mar 28 09:47:27 2002 --> <center> <a class="qindex" href="index.html">Main Page</a> <a class="qindex" href="hierarchy.html">Class Hierarchy</a> <a class="qindex" href="annotated.html">Compound List</a> <a class="qindex" href="files.html">File List</a> <a class="qindex" href="functions.html">Compound Members</a> <a class="qindex" href="globals.html">File Members</a> <a class="qindex" href="pages.html">Related Pages</a> </center> <hr><h1>cpl_minixml.cpp</h1><div class="fragment"><pre>00001 <font class="comment">/**********************************************************************</font> 00002 <font class="comment"> * $Id: cpl_minixml_cpp-source.html,v 1.2 2002/04/16 13:11:47 warmerda Exp $</font> 00003 <font class="comment"> *</font> 00004 <font class="comment"> * Project: CPL - Common Portability Library</font> 00005 <font class="comment"> * Purpose: Implementation of MiniXML Parser and handling.</font> 00006 <font class="comment"> * Author: Frank Warmerdam, warmerdam@pobox.com</font> 00007 <font class="comment"> *</font> 00008 <font class="comment"> **********************************************************************</font> 00009 <font class="comment"> * Copyright (c) 2001, Frank Warmerdam</font> 00010 <font class="comment"> *</font> 00011 <font class="comment"> * Permission is hereby granted, free of charge, to any person obtaining a</font> 00012 <font class="comment"> * copy of this software and associated documentation files (the "Software"),</font> 00013 <font class="comment"> * to deal in the Software without restriction, including without limitation</font> 00014 <font class="comment"> * the rights to use, copy, modify, merge, publish, distribute, sublicense,</font> 00015 <font class="comment"> * and/or sell copies of the Software, and to permit persons to whom the</font> 00016 <font class="comment"> * Software is furnished to do so, subject to the following conditions:</font> 00017 <font class="comment"> * </font> 00018 <font class="comment"> * The above copyright notice and this permission notice shall be included</font> 00019 <font class="comment"> * in all copies or substantial portions of the Software.</font> 00020 <font class="comment"> * </font> 00021 <font class="comment"> * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR</font> 00022 <font class="comment"> * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,</font> 00023 <font class="comment"> * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL</font> 00024 <font class="comment"> * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER</font> 00025 <font class="comment"> * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING</font> 00026 <font class="comment"> * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER </font> 00027 <font class="comment"> * DEALINGS IN THE SOFTWARE.</font> 00028 <font class="comment"> **********************************************************************</font> 00029 <font class="comment"> *</font> 00030 <font class="comment"> * $Log: cpl_minixml_cpp-source.html,v $ 00030 <font class="comment"> * Revision 1.2 2002/04/16 13:11:47 warmerda 00030 <font class="comment"> * updated 00030 <font class="comment"> *</font> 00031 <font class="comment"> * Revision 1.9 2002/03/07 22:19:20 warmerda</font> 00032 <font class="comment"> * don't do operations within CPLAssert(), in UnreadChar()</font> 00033 <font class="comment"> *</font> 00034 <font class="comment"> * Revision 1.8 2002/03/05 14:26:57 warmerda</font> 00035 <font class="comment"> * expanded tabs</font> 00036 <font class="comment"> *</font> 00037 <font class="comment"> * Revision 1.7 2002/01/23 20:45:05 warmerda</font> 00038 <font class="comment"> * handle <?...?> and comment elements</font> 00039 <font class="comment"> *</font> 00040 <font class="comment"> * Revision 1.6 2002/01/22 18:54:48 warmerda</font> 00041 <font class="comment"> * ensure text is property initialized when serializing</font> 00042 <font class="comment"> *</font> 00043 <font class="comment"> * Revision 1.5 2002/01/16 03:58:51 warmerda</font> 00044 <font class="comment"> * support single quotes as well as double quotes</font> 00045 <font class="comment"> *</font> 00046 <font class="comment"> * Revision 1.4 2001/12/06 18:13:49 warmerda</font> 00047 <font class="comment"> * added CPLAddXMLChild and CPLCreateElmentAndValue</font> 00048 <font class="comment"> *</font> 00049 <font class="comment"> * Revision 1.3 2001/11/16 21:20:16 warmerda</font> 00050 <font class="comment"> * fixed typo</font> 00051 <font class="comment"> *</font> 00052 <font class="comment"> * Revision 1.2 2001/11/16 20:29:58 warmerda</font> 00053 <font class="comment"> * fixed lost char in normal CString tokens</font> 00054 <font class="comment"> *</font> 00055 <font class="comment"> * Revision 1.1 2001/11/16 15:39:48 warmerda</font> 00056 <font class="comment"> * New</font> 00057 <font class="comment"> */</font> 00058 00059 <font class="preprocessor">#include <ctype.h></font> 00060 <font class="preprocessor">#include "cpl_minixml.h"</font> 00061 <font class="preprocessor">#include "<a class="code" href="cpl_error_h.html">cpl_error.h</a>"</font> 00062 <font class="preprocessor">#include "<a class="code" href="cpl_conv_h.html">cpl_conv.h</a>"</font> 00063 <font class="preprocessor">#include "cpl_string.h"</font> 00064 00065 CPL_CVSID(<font class="stringliteral">"$Id: cpl_minixml_cpp-source.html,v 1.2 2002/04/16 13:11:47 warmerda Exp $"</font>); 00066 00067 <font class="keyword">typedef</font> <font class="keyword">enum</font> { 00068 TNone, 00069 TString, 00070 TOpen, 00071 TClose, 00072 TEqual, 00073 TToken, 00074 TSlashClose, 00075 TQuestionClose, 00076 TComment 00077 } TokenType; 00078 00079 <font class="keyword">typedef</font> <font class="keyword">struct </font>{ 00080 <font class="keyword">const</font> <font class="keywordtype">char</font> *pszInput; 00081 <font class="keywordtype">int</font> nInputOffset; 00082 <font class="keywordtype">int</font> nInputLine; 00083 00084 <font class="keywordtype">int</font> bInElement; 00085 TokenType eTokenType; 00086 <font class="keywordtype">char</font> *pszToken; 00087 <font class="keywordtype">int</font> nTokenMaxSize; 00088 <font class="keywordtype">int</font> nTokenSize; 00089 00090 <font class="keywordtype">int</font> nStackMaxSize; 00091 <font class="keywordtype">int</font> nStackSize; 00092 CPLXMLNode **papsStack; 00093 00094 CPLXMLNode *psFirstNode; 00095 } ParseContext; 00096 00097 <font class="comment">/************************************************************************/</font> 00098 <font class="comment">/* ReadChar() */</font> 00099 <font class="comment">/************************************************************************/</font> 00100 00101 <font class="keyword">static</font> <font class="keywordtype">char</font> ReadChar( ParseContext *psContext )<font class="keyword"></font> 00102 <font class="keyword"></font> 00103 <font class="keyword"></font>{ 00104 <font class="keywordtype">char</font> chReturn; 00105 00106 chReturn = psContext->pszInput[psContext->nInputOffset++]; 00107 00108 <font class="keywordflow">if</font>( chReturn == <font class="charliteral">'\0'</font> ) 00109 psContext->nInputOffset--; 00110 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( chReturn == 10 ) 00111 psContext->nInputLine++; 00112 00113 <font class="keywordflow">return</font> chReturn; 00114 } 00115 00116 <font class="comment">/************************************************************************/</font> 00117 <font class="comment">/* UnreadChar() */</font> 00118 <font class="comment">/************************************************************************/</font> 00119 00120 <font class="keyword">static</font> <font class="keywordtype">void</font> UnreadChar( ParseContext *psContext, <font class="keywordtype">char</font> chToUnread )<font class="keyword"></font> 00121 <font class="keyword"></font> 00122 <font class="keyword"></font>{ 00123 <font class="keywordflow">if</font>( chToUnread == <font class="charliteral">'\0'</font> ) 00124 { 00125 <font class="comment">/* do nothing */</font> 00126 } 00127 <font class="keywordflow">else</font> 00128 { 00129 CPLAssert( chToUnread 00130 == psContext->pszInput[psContext->nInputOffset-1] ); 00131 00132 psContext->nInputOffset--; 00133 00134 <font class="keywordflow">if</font>( chToUnread == 10 ) 00135 psContext->nInputLine--; 00136 } 00137 } 00138 00139 <font class="comment">/************************************************************************/</font> 00140 <font class="comment">/* AddToToken() */</font> 00141 <font class="comment">/************************************************************************/</font> 00142 00143 <font class="keyword">static</font> <font class="keywordtype">void</font> AddToToken( ParseContext *psContext, <font class="keywordtype">char</font> chNewChar )<font class="keyword"></font> 00144 <font class="keyword"></font> 00145 <font class="keyword"></font>{ 00146 <font class="keywordflow">if</font>( psContext->pszToken == NULL ) 00147 { 00148 psContext->nTokenMaxSize = 10; 00149 psContext->pszToken = (<font class="keywordtype">char</font> *) <a class="code" href="cpl_conv_h.html#a3">CPLMalloc</a>(psContext->nTokenMaxSize); 00150 } 00151 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( psContext->nTokenSize >= psContext->nTokenMaxSize - 2 ) 00152 { 00153 psContext->nTokenMaxSize *= 2; 00154 psContext->pszToken = (<font class="keywordtype">char</font> *) 00155 <a class="code" href="cpl_conv_h.html#a5">CPLRealloc</a>(psContext->pszToken,psContext->nTokenMaxSize); 00156 } 00157 00158 psContext->pszToken[psContext->nTokenSize++] = chNewChar; 00159 psContext->pszToken[psContext->nTokenSize] = <font class="charliteral">'\0'</font>; 00160 } 00161 00162 <font class="comment">/************************************************************************/</font> 00163 <font class="comment">/* ReadToken() */</font> 00164 <font class="comment">/************************************************************************/</font> 00165 00166 <font class="keyword">static</font> TokenType ReadToken( ParseContext *psContext )<font class="keyword"></font> 00167 <font class="keyword"></font> 00168 <font class="keyword"></font>{ 00169 <font class="keywordtype">char</font> chNext; 00170 00171 psContext->nTokenSize = 0; 00172 psContext->pszToken[0] = <font class="charliteral">'\0'</font>; 00173 00174 chNext = ReadChar( psContext ); 00175 <font class="keywordflow">while</font>( isspace(chNext) ) 00176 chNext = ReadChar( psContext ); 00177 00178 <font class="comment">/* -------------------------------------------------------------------- */</font> 00179 <font class="comment">/* Handle comments. */</font> 00180 <font class="comment">/* -------------------------------------------------------------------- */</font> 00181 <font class="keywordflow">if</font>( chNext == <font class="charliteral">'<'</font> 00182 && EQUALN(psContext->pszInput+psContext->nInputOffset,"!--",3) ) 00183 { 00184 psContext->eTokenType = TComment; 00185 00186 <font class="comment">// Skip "!--" characters</font> 00187 ReadChar(psContext); 00188 ReadChar(psContext); 00189 ReadChar(psContext); 00190 00191 <font class="keywordflow">while</font>( !EQUALN(psContext->pszInput+psContext->nInputOffset,"-->",3) 00192 && (chNext = ReadChar(psContext)) != <font class="charliteral">'\0'</font> ) 00193 AddToToken( psContext, chNext ); 00194 00195 <font class="comment">// Skip "-->" characters</font> 00196 ReadChar(psContext); 00197 ReadChar(psContext); 00198 ReadChar(psContext); 00199 } 00200 <font class="comment">/* -------------------------------------------------------------------- */</font> 00201 <font class="comment">/* Simple single tokens of interest. */</font> 00202 <font class="comment">/* -------------------------------------------------------------------- */</font> 00203 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( chNext == <font class="charliteral">'<'</font> && !psContext->bInElement ) 00204 { 00205 psContext->eTokenType = TOpen; 00206 psContext->bInElement = TRUE; 00207 } 00208 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( chNext == <font class="charliteral">'>'</font> && psContext->bInElement ) 00209 { 00210 psContext->eTokenType = TClose; 00211 psContext->bInElement = FALSE; 00212 } 00213 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( chNext == <font class="charliteral">'='</font> && psContext->bInElement ) 00214 { 00215 psContext->eTokenType = TEqual; 00216 } 00217 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( chNext == <font class="charliteral">'\0'</font> ) 00218 { 00219 psContext->eTokenType = TNone; 00220 } 00221 <font class="comment">/* -------------------------------------------------------------------- */</font> 00222 <font class="comment">/* Handle the /> token terminator. */</font> 00223 <font class="comment">/* -------------------------------------------------------------------- */</font> 00224 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( chNext == <font class="charliteral">'/'</font> && psContext->bInElement 00225 && psContext->pszInput[psContext->nInputOffset] == <font class="charliteral">'>'</font> ) 00226 { 00227 chNext = ReadChar( psContext ); 00228 <font class="keywordflow">if</font>( chNext != <font class="charliteral">'>'</font> ) 00229 { 00230 psContext->eTokenType = TNone; 00231 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 00232 <font class="stringliteral">"Parse error at '/' on line %d, expected '>'."</font>, 00233 psContext->nInputLine ); 00234 } 00235 <font class="keywordflow">else</font> 00236 { 00237 psContext->eTokenType = TSlashClose; 00238 psContext->bInElement = FALSE; 00239 } 00240 } 00241 <font class="comment">/* -------------------------------------------------------------------- */</font> 00242 <font class="comment">/* Handle the ?> token terminator. */</font> 00243 <font class="comment">/* -------------------------------------------------------------------- */</font> 00244 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( chNext == <font class="charliteral">'?'</font> && psContext->bInElement 00245 && psContext->pszInput[psContext->nInputOffset] == <font class="charliteral">'>'</font> ) 00246 { 00247 chNext = ReadChar( psContext ); 00248 <font class="keywordflow">if</font>( chNext != <font class="charliteral">'>'</font> ) 00249 { 00250 psContext->eTokenType = TNone; 00251 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 00252 <font class="stringliteral">"Parse error at '?' on line %d, expected '>'."</font>, 00253 psContext->nInputLine ); 00254 } 00255 <font class="keywordflow">else</font> 00256 { 00257 psContext->eTokenType = TQuestionClose; 00258 psContext->bInElement = FALSE; 00259 } 00260 } 00261 00262 <font class="comment">/* -------------------------------------------------------------------- */</font> 00263 <font class="comment">/* Collect a quoted string. */</font> 00264 <font class="comment">/* -------------------------------------------------------------------- */</font> 00265 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( psContext->bInElement && chNext == <font class="charliteral">'"'</font> ) 00266 { 00267 psContext->eTokenType = TString; 00268 00269 <font class="keywordflow">while</font>( (chNext = ReadChar(psContext)) != <font class="charliteral">'"'</font> 00270 && chNext != <font class="charliteral">'\0'</font> ) 00271 AddToToken( psContext, chNext ); 00272 00273 <font class="keywordflow">if</font>( chNext != <font class="charliteral">'"'</font> ) 00274 { 00275 psContext->eTokenType = TNone; 00276 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 00277 <font class="stringliteral">"Parse error on line %d, reached EOF before closing quote."</font>, 00278 psContext->nInputLine ); 00279 } 00280 } 00281 00282 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( psContext->bInElement && chNext == <font class="charliteral">'\''</font> ) 00283 { 00284 psContext->eTokenType = TString; 00285 00286 <font class="keywordflow">while</font>( (chNext = ReadChar(psContext)) != <font class="charliteral">'\''</font> 00287 && chNext != <font class="charliteral">'\0'</font> ) 00288 AddToToken( psContext, chNext ); 00289 00290 <font class="keywordflow">if</font>( chNext != <font class="charliteral">'\''</font> ) 00291 { 00292 psContext->eTokenType = TNone; 00293 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 00294 <font class="stringliteral">"Parse error on line %d, reached EOF before closing quote."</font>, 00295 psContext->nInputLine ); 00296 } 00297 } 00298 00299 <font class="comment">/* -------------------------------------------------------------------- */</font> 00300 <font class="comment">/* Collect an unquoted string, terminated by a open angle */</font> 00301 <font class="comment">/* bracket. */</font> 00302 <font class="comment">/* -------------------------------------------------------------------- */</font> 00303 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( !psContext->bInElement ) 00304 { 00305 psContext->eTokenType = TString; 00306 00307 AddToToken( psContext, chNext ); 00308 <font class="keywordflow">while</font>( (chNext = ReadChar(psContext)) != <font class="charliteral">'<'</font> 00309 && chNext != <font class="charliteral">'\0'</font> ) 00310 AddToToken( psContext, chNext ); 00311 UnreadChar( psContext, chNext ); 00312 } 00313 00314 <font class="comment">/* -------------------------------------------------------------------- */</font> 00315 <font class="comment">/* Collect a regular token terminated by white space, or */</font> 00316 <font class="comment">/* special character(s) like an equal sign. */</font> 00317 <font class="comment">/* -------------------------------------------------------------------- */</font> 00318 <font class="keywordflow">else</font> 00319 { 00320 psContext->eTokenType = TToken; 00321 00322 <font class="comment">/* add the first character to the token regardless of what it is */</font> 00323 AddToToken( psContext, chNext ); 00324 00325 <font class="keywordflow">for</font>( chNext = ReadChar(psContext); 00326 (chNext >= <font class="charliteral">'A'</font> && chNext <= <font class="charliteral">'Z'</font>) 00327 || (chNext >= <font class="charliteral">'a'</font> && chNext <= <font class="charliteral">'z'</font>) 00328 || chNext == <font class="charliteral">'_'</font> 00329 || chNext == <font class="charliteral">':'</font> 00330 || (chNext >= <font class="charliteral">'0'</font> && chNext <= <font class="charliteral">'9'</font>); 00331 chNext = ReadChar(psContext) ) 00332 { 00333 AddToToken( psContext, chNext ); 00334 } 00335 00336 UnreadChar(psContext, chNext); 00337 } 00338 00339 <font class="keywordflow">return</font> psContext->eTokenType; 00340 } 00341 00342 <font class="comment">/************************************************************************/</font> 00343 <font class="comment">/* PushNode() */</font> 00344 <font class="comment">/************************************************************************/</font> 00345 00346 <font class="keyword">static</font> <font class="keywordtype">void</font> PushNode( ParseContext *psContext, CPLXMLNode *psNode )<font class="keyword"></font> 00347 <font class="keyword"></font> 00348 <font class="keyword"></font>{ 00349 <font class="keywordflow">if</font>( psContext->nStackMaxSize <= psContext->nStackSize ) 00350 { 00351 psContext->nStackMaxSize += 10; 00352 psContext->papsStack = (CPLXMLNode **) 00353 <a class="code" href="cpl_conv_h.html#a5">CPLRealloc</a>(psContext->papsStack, 00354 <font class="keyword">sizeof</font>(CPLXMLNode*) * psContext->nStackMaxSize); 00355 } 00356 00357 psContext->papsStack[psContext->nStackSize++] = psNode; 00358 } 00359 00360 <font class="comment">/************************************************************************/</font> 00361 <font class="comment">/* AttachNode() */</font> 00362 <font class="comment">/* */</font> 00363 <font class="comment">/* Attach the passed node as a child of the current node. */</font> 00364 <font class="comment">/* Special handling exists for adding siblings to psFirst if */</font> 00365 <font class="comment">/* there is nothing on the stack. */</font> 00366 <font class="comment">/************************************************************************/</font> 00367 00368 <font class="keyword">static</font> <font class="keywordtype">void</font> AttachNode( ParseContext *psContext, CPLXMLNode *psNode )<font class="keyword"></font> 00369 <font class="keyword"></font> 00370 <font class="keyword"></font>{ 00371 <font class="keywordflow">if</font>( psContext->psFirstNode == NULL ) 00372 psContext->psFirstNode = psNode; 00373 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( psContext->nStackSize == 0 ) 00374 { 00375 CPLXMLNode *psSibling; 00376 00377 psSibling = psContext->psFirstNode; 00378 <font class="keywordflow">while</font>( psSibling->psNext != NULL ) 00379 psSibling = psSibling->psNext; 00380 psSibling->psNext = psNode; 00381 } 00382 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( psContext->papsStack[psContext->nStackSize-1]->psChild == NULL ) 00383 { 00384 psContext->papsStack[psContext->nStackSize-1]->psChild = psNode; 00385 } 00386 <font class="keywordflow">else</font> 00387 { 00388 CPLXMLNode *psSibling; 00389 00390 psSibling = psContext->papsStack[psContext->nStackSize-1]->psChild; 00391 <font class="keywordflow">while</font>( psSibling->psNext != NULL ) 00392 psSibling = psSibling->psNext; 00393 psSibling->psNext = psNode; 00394 } 00395 } 00396 00397 <font class="comment">/************************************************************************/</font> 00398 <font class="comment">/* CPLParseXMLString() */</font> 00399 <font class="comment">/************************************************************************/</font> 00400 00401 CPLXMLNode *CPLParseXMLString( <font class="keyword">const</font> <font class="keywordtype">char</font> *pszString )<font class="keyword"></font> 00402 <font class="keyword"></font> 00403 <font class="keyword"></font>{ 00404 ParseContext sContext; 00405 00406 <a class="code" href="cpl_error_h.html#a19">CPLErrorReset</a>(); 00407 00408 <font class="comment">/* -------------------------------------------------------------------- */</font> 00409 <font class="comment">/* Initialize parse context. */</font> 00410 <font class="comment">/* -------------------------------------------------------------------- */</font> 00411 sContext.pszInput = pszString; 00412 sContext.nInputOffset = 0; 00413 sContext.nInputLine = 0; 00414 sContext.bInElement = FALSE; 00415 sContext.pszToken = NULL; 00416 sContext.nTokenMaxSize = 0; 00417 sContext.nTokenSize = 0; 00418 sContext.eTokenType = TNone; 00419 sContext.nStackMaxSize = 0; 00420 sContext.nStackSize = 0; 00421 sContext.papsStack = NULL; 00422 sContext.psFirstNode = NULL; 00423 00424 <font class="comment">/* ensure token is initialized */</font> 00425 AddToToken( &sContext, <font class="charliteral">' '</font> ); 00426 00427 <font class="comment">/* ==================================================================== */</font> 00428 <font class="comment">/* Loop reading tokens. */</font> 00429 <font class="comment">/* ==================================================================== */</font> 00430 <font class="keywordflow">while</font>( ReadToken( &sContext ) != TNone ) 00431 { 00432 <font class="comment">/* -------------------------------------------------------------------- */</font> 00433 <font class="comment">/* Create a new element. */</font> 00434 <font class="comment">/* -------------------------------------------------------------------- */</font> 00435 <font class="keywordflow">if</font>( sContext.eTokenType == TOpen ) 00436 { 00437 CPLXMLNode *psElement; 00438 00439 <font class="keywordflow">if</font>( ReadToken(&sContext) != TToken ) 00440 { 00441 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 00442 <font class="stringliteral">"Line %d: Didn't find element token after open angle bracket."</font>, 00443 sContext.nInputLine ); 00444 <font class="keywordflow">break</font>; 00445 } 00446 00447 <font class="keywordflow">if</font>( sContext.pszToken[0] != <font class="charliteral">'/'</font> ) 00448 { 00449 psElement = CPLCreateXMLNode( NULL, CXT_Element, 00450 sContext.pszToken ); 00451 AttachNode( &sContext, psElement ); 00452 PushNode( &sContext, psElement ); 00453 } 00454 <font class="keywordflow">else</font> 00455 { 00456 <font class="keywordflow">if</font>( sContext.nStackSize == 0 00457 || !EQUAL(sContext.pszToken+1, 00458 sContext.papsStack[sContext.nStackSize-1]->pszValue) ) 00459 { 00460 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 00461 <font class="stringliteral">"Line %d: <%s> doesn't have matching <%s>."</font>, 00462 sContext.nInputLine, 00463 sContext.pszToken, sContext.pszToken+1 ); 00464 <font class="keywordflow">break</font>; 00465 } 00466 <font class="keywordflow">else</font> 00467 { 00468 <font class="keywordflow">if</font>( ReadToken(&sContext) != TClose ) 00469 { 00470 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 00471 <font class="stringliteral">"Line %d: Missing close angle bracket after <%s."</font>, 00472 sContext.nInputLine, 00473 sContext.pszToken ); 00474 <font class="keywordflow">break</font>; 00475 } 00476 00477 <font class="comment">/* pop element off stack */</font> 00478 sContext.nStackSize--; 00479 } 00480 } 00481 } 00482 00483 <font class="comment">/* -------------------------------------------------------------------- */</font> 00484 <font class="comment">/* Add an attribute to a token. */</font> 00485 <font class="comment">/* -------------------------------------------------------------------- */</font> 00486 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( sContext.eTokenType == TToken ) 00487 { 00488 CPLXMLNode *psAttr; 00489 00490 psAttr = CPLCreateXMLNode(NULL, CXT_Attribute, sContext.pszToken); 00491 AttachNode( &sContext, psAttr ); 00492 00493 <font class="keywordflow">if</font>( ReadToken(&sContext) != TEqual ) 00494 { 00495 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 00496 <font class="stringliteral">"Line %d: Didn't find expected '=' for attribute value."</font>, 00497 sContext.nInputLine ); 00498 <font class="keywordflow">break</font>; 00499 } 00500 00501 <font class="keywordflow">if</font>( ReadToken(&sContext) != TString 00502 && sContext.eTokenType != TToken ) 00503 { 00504 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 00505 <font class="stringliteral">"Line %d: Didn't find expected attribute value."</font>, 00506 sContext.nInputLine ); 00507 <font class="keywordflow">break</font>; 00508 } 00509 00510 CPLCreateXMLNode( psAttr, CXT_Text, sContext.pszToken ); 00511 } 00512 00513 <font class="comment">/* -------------------------------------------------------------------- */</font> 00514 <font class="comment">/* Close the start section of an element. */</font> 00515 <font class="comment">/* -------------------------------------------------------------------- */</font> 00516 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( sContext.eTokenType == TClose ) 00517 { 00518 <font class="keywordflow">if</font>( sContext.nStackSize == 0 ) 00519 { 00520 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 00521 <font class="stringliteral">"Line %d: Found unbalanced '>'."</font>, 00522 sContext.nInputLine ); 00523 <font class="keywordflow">break</font>; 00524 } 00525 } 00526 00527 <font class="comment">/* -------------------------------------------------------------------- */</font> 00528 <font class="comment">/* Close the start section of an element, and pop it */</font> 00529 <font class="comment">/* immediately. */</font> 00530 <font class="comment">/* -------------------------------------------------------------------- */</font> 00531 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( sContext.eTokenType == TSlashClose ) 00532 { 00533 <font class="keywordflow">if</font>( sContext.nStackSize == 0 ) 00534 { 00535 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 00536 <font class="stringliteral">"Line %d: Found unbalanced '/>'."</font>, 00537 sContext.nInputLine ); 00538 <font class="keywordflow">break</font>; 00539 } 00540 00541 sContext.nStackSize--; 00542 } 00543 00544 <font class="comment">/* -------------------------------------------------------------------- */</font> 00545 <font class="comment">/* Close the start section of a <?...?> element, and pop it */</font> 00546 <font class="comment">/* immediately. */</font> 00547 <font class="comment">/* -------------------------------------------------------------------- */</font> 00548 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( sContext.eTokenType == TQuestionClose ) 00549 { 00550 <font class="keywordflow">if</font>( sContext.nStackSize == 0 ) 00551 { 00552 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 00553 <font class="stringliteral">"Line %d: Found unbalanced '?>'."</font>, 00554 sContext.nInputLine ); 00555 <font class="keywordflow">break</font>; 00556 } 00557 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( sContext.papsStack[sContext.nStackSize-1]->pszValue[0] != <font class="charliteral">'?'</font> ) 00558 { 00559 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 00560 <font class="stringliteral">"Line %d: Found '?>' without matching '<?'."</font>, 00561 sContext.nInputLine ); 00562 <font class="keywordflow">break</font>; 00563 } 00564 00565 sContext.nStackSize--; 00566 } 00567 00568 <font class="comment">/* -------------------------------------------------------------------- */</font> 00569 <font class="comment">/* Handle comments. They are returned as a whole token with the */</font> 00570 <font class="comment">/* prefix and postfix omitted. No processing of white space */</font> 00571 <font class="comment">/* will be done. */</font> 00572 <font class="comment">/* -------------------------------------------------------------------- */</font> 00573 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( sContext.eTokenType == TComment ) 00574 { 00575 CPLXMLNode *psValue; 00576 00577 psValue = CPLCreateXMLNode(NULL, CXT_Comment, sContext.pszToken); 00578 AttachNode( &sContext, psValue ); 00579 } 00580 00581 <font class="comment">/* -------------------------------------------------------------------- */</font> 00582 <font class="comment">/* Add a text value node as a child of the current element. */</font> 00583 <font class="comment">/* -------------------------------------------------------------------- */</font> 00584 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( sContext.eTokenType == TString && !sContext.bInElement ) 00585 { 00586 CPLXMLNode *psValue; 00587 00588 psValue = CPLCreateXMLNode(NULL, CXT_Text, sContext.pszToken); 00589 AttachNode( &sContext, psValue ); 00590 } 00591 <font class="comment">/* -------------------------------------------------------------------- */</font> 00592 <font class="comment">/* Anything else is an error. */</font> 00593 <font class="comment">/* -------------------------------------------------------------------- */</font> 00594 <font class="keywordflow">else</font> 00595 { 00596 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 00597 <font class="stringliteral">"Parse error at line %d, unexpected token:%s\n"</font>, 00598 sContext.nInputLine, sContext.pszToken ); 00599 <font class="keywordflow">break</font>; 00600 } 00601 } 00602 00603 <font class="comment">/* -------------------------------------------------------------------- */</font> 00604 <font class="comment">/* Did we pop all the way out of our stack? */</font> 00605 <font class="comment">/* -------------------------------------------------------------------- */</font> 00606 <font class="keywordflow">if</font>( <a class="code" href="cpl_error_h.html#a21">CPLGetLastErrorType</a>() == CE_None && sContext.nStackSize != 0 ) 00607 { 00608 <a class="code" href="cpl_error_h.html#a17">CPLError</a>( CE_Failure, CPLE_AppDefined, 00609 <font class="stringliteral">"Parse error at EOF, not all elements have been closed,\n"</font> 00610 <font class="stringliteral">"starting with %s\n"</font>, 00611 sContext.papsStack[sContext.nStackSize-1]->pszValue ); 00612 } 00613 00614 <font class="comment">/* -------------------------------------------------------------------- */</font> 00615 <font class="comment">/* Cleanup */</font> 00616 <font class="comment">/* -------------------------------------------------------------------- */</font> 00617 CPLFree( sContext.pszToken ); 00618 <font class="keywordflow">if</font>( sContext.papsStack != NULL ) 00619 CPLFree( sContext.papsStack ); 00620 00621 <font class="keywordflow">if</font>( <a class="code" href="cpl_error_h.html#a21">CPLGetLastErrorType</a>() != CE_None ) 00622 { 00623 CPLDestroyXMLNode( sContext.psFirstNode ); 00624 sContext.psFirstNode = NULL; 00625 } 00626 00627 <font class="keywordflow">return</font> sContext.psFirstNode; 00628 } 00629 00630 <font class="comment">/************************************************************************/</font> 00631 <font class="comment">/* _GrowBuffer() */</font> 00632 <font class="comment">/************************************************************************/</font> 00633 00634 <font class="keyword">static</font> <font class="keywordtype">void</font> _GrowBuffer( <font class="keywordtype">unsigned</font> <font class="keywordtype">int</font> nNeeded, 00635 <font class="keywordtype">char</font> **ppszText, <font class="keywordtype">unsigned</font> <font class="keywordtype">int</font> *pnMaxLength )<font class="keyword"></font> 00636 <font class="keyword"></font> 00637 <font class="keyword"></font>{ 00638 <font class="keywordflow">if</font>( nNeeded+1 >= *pnMaxLength ) 00639 { 00640 *pnMaxLength = MAX(*pnMaxLength * 2,nNeeded+1); 00641 *ppszText = (<font class="keywordtype">char</font> *) <a class="code" href="cpl_conv_h.html#a5">CPLRealloc</a>(*ppszText, *pnMaxLength); 00642 } 00643 } 00644 00645 <font class="comment">/************************************************************************/</font> 00646 <font class="comment">/* CPLSerializeXMLNode() */</font> 00647 <font class="comment">/************************************************************************/</font> 00648 00649 <font class="keyword">static</font> <font class="keywordtype">void</font> 00650 CPLSerializeXMLNode( CPLXMLNode *psNode, <font class="keywordtype">int</font> nIndent, 00651 <font class="keywordtype">char</font> **ppszText, <font class="keywordtype">unsigned</font> <font class="keywordtype">int</font> *pnLength, 00652 <font class="keywordtype">unsigned</font> <font class="keywordtype">int</font> *pnMaxLength )<font class="keyword"></font> 00653 <font class="keyword"></font> 00654 <font class="keyword"></font>{ 00655 <font class="keywordflow">if</font>( psNode == NULL ) 00656 <font class="keywordflow">return</font>; 00657 00658 <font class="comment">/* -------------------------------------------------------------------- */</font> 00659 <font class="comment">/* Ensure the buffer is plenty large to hold this additional */</font> 00660 <font class="comment">/* string. */</font> 00661 <font class="comment">/* -------------------------------------------------------------------- */</font> 00662 *pnLength += strlen(*ppszText + *pnLength); 00663 <font class="keywordflow">if</font>(strlen(psNode->pszValue) + *pnLength + 40 + nIndent > *pnMaxLength) 00664 _GrowBuffer( strlen(psNode->pszValue) + *pnLength + 40 + nIndent, 00665 ppszText, pnMaxLength ); 00666 00667 <font class="comment">/* -------------------------------------------------------------------- */</font> 00668 <font class="comment">/* Text is just directly emitted. */</font> 00669 <font class="comment">/* -------------------------------------------------------------------- */</font> 00670 <font class="keywordflow">if</font>( psNode->eType == CXT_Text ) 00671 { 00672 CPLAssert( psNode->psChild == NULL ); 00673 00674 strcat( *ppszText + *pnLength, psNode->pszValue ); 00675 } 00676 00677 <font class="comment">/* -------------------------------------------------------------------- */</font> 00678 <font class="comment">/* Attributes require a little formatting. */</font> 00679 <font class="comment">/* -------------------------------------------------------------------- */</font> 00680 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( psNode->eType == CXT_Attribute ) 00681 { 00682 CPLAssert( psNode->psChild != NULL 00683 && psNode->psChild->eType == CXT_Text ); 00684 00685 sprintf( *ppszText + *pnLength, <font class="stringliteral">" %s=\""</font>, psNode->pszValue ); 00686 CPLSerializeXMLNode( psNode->psChild, 0, ppszText, 00687 pnLength, pnMaxLength ); 00688 strcat( *ppszText + *pnLength, <font class="stringliteral">"\""</font> ); 00689 } 00690 00691 <font class="comment">/* -------------------------------------------------------------------- */</font> 00692 <font class="comment">/* Attributes require a little formatting. */</font> 00693 <font class="comment">/* -------------------------------------------------------------------- */</font> 00694 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( psNode->eType == CXT_Comment ) 00695 { 00696 <font class="keywordtype">int</font> i; 00697 00698 CPLAssert( psNode->psChild == NULL ); 00699 00700 <font class="keywordflow">for</font>( i = 0; i < nIndent; i++ ) 00701 (*ppszText)[(*pnLength)++] = <font class="charliteral">' '</font>; 00702 00703 sprintf( *ppszText + *pnLength, <font class="stringliteral">"<!--%s-->\n"</font>, 00704 psNode->pszValue ); 00705 } 00706 00707 <font class="comment">/* -------------------------------------------------------------------- */</font> 00708 <font class="comment">/* Elements actually have to deal with general children, and */</font> 00709 <font class="comment">/* various formatting issues. */</font> 00710 <font class="comment">/* -------------------------------------------------------------------- */</font> 00711 <font class="keywordflow">else</font> <font class="keywordflow">if</font>( psNode->eType == CXT_Element ) 00712 { 00713 CPLXMLNode *psChild = psNode->psChild; 00714 <font class="keywordtype">char</font> *pszIndent; 00715 00716 pszIndent = (<font class="keywordtype">char</font> *) <a class="code" href="cpl_conv_h.html#a4">CPLCalloc</a>(nIndent + 1,1); 00717 memset(pszIndent, <font class="charliteral">' '</font>, nIndent ); 00718 00719 strcat( *ppszText + *pnLength, pszIndent ); 00720 *pnLength += nIndent; 00721 sprintf( *ppszText + *pnLength, <font class="stringliteral">"<%s"</font>, psNode->pszValue ); 00722 00723 <font class="keywordflow">while</font>( psChild != NULL && psChild->eType == CXT_Attribute ) 00724 { 00725 CPLSerializeXMLNode( psChild, 0, ppszText, pnLength, 00726 pnMaxLength ); 00727 psChild = psChild->psNext; 00728 } 00729 00730 <font class="keywordflow">if</font>( psChild == NULL ) 00731 { 00732 <font class="keywordflow">if</font>( psNode->pszValue[0] == <font class="charliteral">'?'</font> ) 00733 strcat( *ppszText + *pnLength, <font class="stringliteral">"?>\n"</font> ); 00734 <font class="keywordflow">else</font> 00735 strcat( *ppszText + *pnLength, <font class="stringliteral">"/>\n"</font> ); 00736 } 00737 <font class="keywordflow">else</font> 00738 { 00739 <font class="keywordtype">int</font> bJustText = TRUE; 00740 00741 strcat( *ppszText + *pnLength, <font class="stringliteral">">"</font> ); 00742 00743 <font class="keywordflow">while</font>( psChild != NULL ) 00744 { 00745 <font class="keywordflow">if</font>( psChild->eType != CXT_Text && bJustText ) 00746 { 00747 bJustText = FALSE; 00748 strcat( *ppszText + *pnLength, <font class="stringliteral">"\n"</font> ); 00749 } 00750 00751 CPLSerializeXMLNode( psChild, nIndent + 2, ppszText, pnLength, 00752 pnMaxLength ); 00753 psChild = psChild->psNext; 00754 } 00755 00756 <font class="keywordflow">if</font>( strlen(psNode->pszValue)+*pnLength+40+nIndent > *pnMaxLength) 00757 _GrowBuffer( strlen(psNode->pszValue)+*pnLength+40+nIndent, 00758 ppszText, pnMaxLength ); 00759 00760 <font class="keywordflow">if</font>( !bJustText ) 00761 strcat( *ppszText + *pnLength, pszIndent ); 00762 00763 *pnLength += strlen(*ppszText + *pnLength); 00764 sprintf( *ppszText + *pnLength, <font class="stringliteral">"</%s>\n"</font>, psNode->pszValue ); 00765 } 00766 00767 CPLFree( pszIndent ); 00768 } 00769 } 00770 00771 <font class="comment">/************************************************************************/</font> 00772 <font class="comment">/* CPLSerializeXMLTree() */</font> 00773 <font class="comment">/************************************************************************/</font> 00774 00775 <font class="keywordtype">char</font> *CPLSerializeXMLTree( CPLXMLNode *psNode )<font class="keyword"></font> 00776 <font class="keyword"></font> 00777 <font class="keyword"></font>{ 00778 <font class="keywordtype">unsigned</font> <font class="keywordtype">int</font> nMaxLength = 10000, nLength = 0; 00779 <font class="keywordtype">char</font> *pszText = NULL; 00780 CPLXMLNode *psThis; 00781 00782 pszText = (<font class="keywordtype">char</font> *) <a class="code" href="cpl_conv_h.html#a3">CPLMalloc</a>(nMaxLength); 00783 pszText[0] = <font class="charliteral">'\0'</font>; 00784 00785 <font class="keywordflow">for</font>( psThis = psNode; psThis != NULL; psThis = psThis->psNext ) 00786 CPLSerializeXMLNode( psThis, 0, &pszText, &nLength, &nMaxLength ); 00787 00788 <font class="keywordflow">return</font> pszText; 00789 } 00790 00791 <font class="comment">/************************************************************************/</font> 00792 <font class="comment">/* CPLCreateXMLNode() */</font> 00793 <font class="comment">/************************************************************************/</font> 00794 00795 CPLXMLNode *CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType, 00796 <font class="keyword">const</font> <font class="keywordtype">char</font> *pszText )<font class="keyword"></font> 00797 <font class="keyword"></font> 00798 <font class="keyword"></font>{ 00799 CPLXMLNode *psNode; 00800 00801 <font class="comment">/* -------------------------------------------------------------------- */</font> 00802 <font class="comment">/* Create new node. */</font> 00803 <font class="comment">/* -------------------------------------------------------------------- */</font> 00804 psNode = (CPLXMLNode *) <a class="code" href="cpl_conv_h.html#a4">CPLCalloc</a>(<font class="keyword">sizeof</font>(CPLXMLNode),1); 00805 00806 psNode->eType = eType; 00807 psNode->pszValue = <a class="code" href="cpl_conv_h.html#a6">CPLStrdup</a>( pszText ); 00808 00809 <font class="comment">/* -------------------------------------------------------------------- */</font> 00810 <font class="comment">/* Attach to parent, if provided. */</font> 00811 <font class="comment">/* -------------------------------------------------------------------- */</font> 00812 <font class="keywordflow">if</font>( poParent != NULL ) 00813 { 00814 <font class="keywordflow">if</font>( poParent->psChild == NULL ) 00815 poParent->psChild = psNode; 00816 <font class="keywordflow">else</font> 00817 { 00818 CPLXMLNode *psLink = poParent->psChild; 00819 00820 <font class="keywordflow">while</font>( psLink->psNext != NULL ) 00821 psLink = psLink->psNext; 00822 00823 psLink->psNext = psNode; 00824 } 00825 } 00826 00827 <font class="keywordflow">return</font> psNode; 00828 } 00829 00830 <font class="comment">/************************************************************************/</font> 00831 <font class="comment">/* CPLDestroyXMLNode() */</font> 00832 <font class="comment">/************************************************************************/</font> 00833 00834 <font class="keywordtype">void</font> CPLDestroyXMLNode( CPLXMLNode *psNode )<font class="keyword"></font> 00835 <font class="keyword"></font> 00836 <font class="keyword"></font>{ 00837 <font class="keywordflow">if</font>( psNode->psChild != NULL ) 00838 CPLDestroyXMLNode( psNode->psChild ); 00839 00840 <font class="keywordflow">if</font>( psNode->psNext != NULL ) 00841 CPLDestroyXMLNode( psNode->psNext ); 00842 00843 CPLFree( psNode->pszValue ); 00844 CPLFree( psNode ); 00845 } 00846 00847 <font class="comment">/************************************************************************/</font> 00848 <font class="comment">/* CPLGetXMLNode() */</font> 00849 <font class="comment">/************************************************************************/</font> 00850 00851 CPLXMLNode *CPLGetXMLNode( CPLXMLNode *poRoot, <font class="keyword">const</font> <font class="keywordtype">char</font> *pszPath )<font class="keyword"></font> 00852 <font class="keyword"></font> 00853 <font class="keyword"></font>{ 00854 <font class="keywordtype">char</font> **papszTokens; 00855 <font class="keywordtype">int</font> iToken = 0; 00856 00857 papszTokens = CSLTokenizeStringComplex( pszPath, <font class="stringliteral">"."</font>, FALSE, FALSE ); 00858 00859 <font class="keywordflow">while</font>( papszTokens[iToken] != NULL && poRoot != NULL ) 00860 { 00861 CPLXMLNode *psChild; 00862 00863 <font class="keywordflow">for</font>( psChild = poRoot->psChild; psChild != NULL; 00864 psChild = psChild->psNext ) 00865 { 00866 <font class="keywordflow">if</font>( psChild->eType != CXT_Text 00867 && EQUAL(papszTokens[iToken],psChild->pszValue) ) 00868 <font class="keywordflow">break</font>; 00869 } 00870 00871 <font class="keywordflow">if</font>( psChild == NULL ) 00872 { 00873 poRoot = NULL; 00874 <font class="keywordflow">break</font>; 00875 } 00876 00877 poRoot = psChild; 00878 iToken++; 00879 } 00880 00881 CSLDestroy( papszTokens ); 00882 <font class="keywordflow">return</font> poRoot; 00883 } 00884 00885 <font class="comment">/************************************************************************/</font> 00886 <font class="comment">/* CPLGetXMLValue() */</font> 00887 <font class="comment">/************************************************************************/</font> 00888 00889 <font class="keyword">const</font> <font class="keywordtype">char</font> *CPLGetXMLValue( CPLXMLNode *poRoot, <font class="keyword">const</font> <font class="keywordtype">char</font> *pszPath, 00890 <font class="keyword">const</font> <font class="keywordtype">char</font> *pszDefault )<font class="keyword"></font> 00891 <font class="keyword"></font> 00892 <font class="keyword"></font>{ 00893 CPLXMLNode *psTarget; 00894 00895 psTarget = CPLGetXMLNode( poRoot, pszPath ); 00896 <font class="keywordflow">if</font>( psTarget == NULL ) 00897 <font class="keywordflow">return</font> pszDefault; 00898 00899 <font class="keywordflow">if</font>( psTarget->eType == CXT_Attribute ) 00900 { 00901 CPLAssert( psTarget->psChild != NULL 00902 && psTarget->psChild->eType == CXT_Text ); 00903 00904 <font class="keywordflow">return</font> psTarget->psChild->pszValue; 00905 } 00906 00907 <font class="keywordflow">if</font>( psTarget->eType == CXT_Element 00908 && psTarget->psChild != NULL 00909 && psTarget->psChild->eType == CXT_Text 00910 && psTarget->psChild->psNext == NULL ) 00911 { 00912 <font class="keywordflow">return</font> psTarget->psChild->pszValue; 00913 } 00914 00915 <font class="keywordflow">return</font> pszDefault; 00916 } 00917 00918 <font class="comment">/************************************************************************/</font> 00919 <font class="comment">/* CPLAddXMLChild() */</font> 00920 <font class="comment">/* */</font> 00921 <font class="comment">/* Add a node as a child of another. */</font> 00922 <font class="comment">/************************************************************************/</font> 00923 00924 <font class="keywordtype">void</font> CPLAddXMLChild( CPLXMLNode *psParent, CPLXMLNode *psChild )<font class="keyword"></font> 00925 <font class="keyword"></font> 00926 <font class="keyword"></font>{ 00927 CPLXMLNode *psSib; 00928 00929 CPLAssert( psChild->psNext == NULL ); 00930 psChild->psNext = NULL; 00931 00932 <font class="keywordflow">if</font>( psParent->psChild == NULL ) 00933 { 00934 psParent->psChild = psChild; 00935 <font class="keywordflow">return</font>; 00936 } 00937 00938 <font class="keywordflow">for</font>( psSib = psParent->psChild; 00939 psSib->psNext != NULL; 00940 psSib = psSib->psNext ) {} 00941 00942 psSib->psNext = psChild; 00943 } 00944 00945 <font class="comment">/************************************************************************/</font> 00946 <font class="comment">/* CPLCreateXMLElementAndValue() */</font> 00947 <font class="comment">/************************************************************************/</font> 00948 00949 CPLXMLNode *CPLCreateXMLElementAndValue( CPLXMLNode *psParent, 00950 <font class="keyword">const</font> <font class="keywordtype">char</font> *pszName, 00951 <font class="keyword">const</font> <font class="keywordtype">char</font> *pszValue )<font class="keyword"></font> 00952 <font class="keyword"></font> 00953 <font class="keyword"></font>{ 00954 <font class="keywordflow">return</font> CPLCreateXMLNode( 00955 CPLCreateXMLNode( psParent, CXT_Element, pszName ), 00956 CXT_Text, pszValue ); 00957 } 00958 </div></pre><hr><address><small>Generated at Thu Mar 28 09:47:28 2002 for GDAL by <a href="http://www.stack.nl/~dimitri/doxygen/index.html"> <img src="doxygen.gif" alt="doxygen" align="middle" border=0 width=110 height=53></a>1.2.3-20001105 written by <a href="mailto:dimitri@stack.nl">Dimitri van Heesch</a>, © 1997-2000</small></address> </body> </html>