omads/omadsextensions/dsutils/emailxmlutils/src/nsmlxmlparser.cpp
changeset 1 95fdac6ccb5c
parent 0 dab8a81a92de
child 2 19dc812fb587
equal deleted inserted replaced
0:dab8a81a92de 1:95fdac6ccb5c
     1 /*
       
     2 * Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Sources
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // 1.2 Changes: nsmlxmlparser module added
       
    20 
       
    21 // ------------------------------------------------------------------------------------------------
       
    22 // Includes
       
    23 // ------------------------------------------------------------------------------------------------
       
    24 #include <s32buf.h>
       
    25 #include <s32file.h>
       
    26 #include "nsmlxmlparser.h"
       
    27 
       
    28 
       
    29 // ------------------------------------------------------------------------------------------------
       
    30 // 
       
    31 // CNSmlXmlParser methods
       
    32 // 
       
    33 // ------------------------------------------------------------------------------------------------
       
    34 
       
    35 // ------------------------------------------------------------------------------------------------
       
    36 // Constructor
       
    37 // ------------------------------------------------------------------------------------------------
       
    38 EXPORT_C CNSmlXmlParser::CNSmlXmlParser()
       
    39 	{
       
    40 	}
       
    41 
       
    42 
       
    43 // ------------------------------------------------------------------------------------------------
       
    44 // Destructor.
       
    45 // ------------------------------------------------------------------------------------------------
       
    46 EXPORT_C CNSmlXmlParser::~CNSmlXmlParser()
       
    47 	{
       
    48 	if( iBuffer ) delete iBuffer;
       
    49 	if ( iCompleteBuffer ) delete iCompleteBuffer;
       
    50 	}
       
    51 
       
    52 
       
    53 // ------------------------------------------------------------------------------------------------
       
    54 // Parses the given string for cdata areas and entitys. If a cdata area is 
       
    55 // found, the data in it is skipped over. The entities outside cdata are converted 
       
    56 // into characters they represent (but only if cdata is found).
       
    57 // Note: This method is intended for processing the CDATA used right after <Data>. 
       
    58 // I.e. this method removes the cdata-elements used for wrapping the whole xml data 
       
    59 // and processes the string so that the inner cdatas used in the xml become valid.
       
    60 // THIS METHOD SHOULD BE CALLED RIGHT IN THE BEGINNING OF PARSING IF <Data>-BLOCK 
       
    61 // IS WRAPPED WITHIN CDATA.
       
    62 // ------------------------------------------------------------------------------------------------
       
    63 void CNSmlXmlParser::PreProcessL( HBufC8* aXml ) const
       
    64 	{
       
    65 	// take a modifiable pointer
       
    66 	TPtr8 xml = aXml->Des();
       
    67 
       
    68 	// the string used for searching and moving in the string
       
    69 	TPtrC8 searchString(*aXml);
       
    70 
       
    71 	// the current position in the original string
       
    72 	TInt searchStartPos = 0;
       
    73 
       
    74 	// find the first cdata start
       
    75 	TInt cdataStartPos = searchString.Find(KCDataStart);
       
    76 	
       
    77 	// If CDATA is not found from beginning then data is not inside CDATA and then
       
    78 	// preprocessing is not needed
       
    79 	if ( cdataStartPos != 0 )
       
    80 	    {
       
    81 	    return;
       
    82 	    }
       
    83 
       
    84 	TInt cdataEndPos = KErrNotFound;
       
    85 
       
    86 	// while cdata is found
       
    87 	while ( cdataStartPos != KErrNotFound )
       
    88 		{
       
    89 		cdataStartPos += searchStartPos;
       
    90 
       
    91 		// find an end of cdata before entities are converted
       
    92 		cdataEndPos = searchString.Find(KCDataEnd);
       
    93 
       
    94 		// convert entities between search start and cdata start
       
    95 		TInt entityChange = EntitiesToCharactersL(aXml, searchStartPos, cdataStartPos);
       
    96 		xml.Set(aXml->Des());
       
    97 		cdataStartPos += entityChange;
       
    98 
       
    99 		if ( cdataEndPos != KErrNotFound )
       
   100 			{
       
   101 			cdataEndPos += entityChange;
       
   102 			cdataEndPos += searchStartPos;
       
   103 
       
   104 			// if the end is before start -> error
       
   105 			if (cdataEndPos < cdataStartPos)
       
   106 				User::Leave( EInvalidCDataStructure );
       
   107 				
       
   108 			// remove cdata end
       
   109 			xml.Delete(cdataEndPos, KCDataEnd().Length());
       
   110 			// remove cdata start
       
   111 			xml.Delete(cdataStartPos, KCDataStart().Length());
       
   112 
       
   113 			searchStartPos = cdataEndPos - KCDataStart().Length();
       
   114 			searchString.Set( xml.Right(xml.Length() - searchStartPos) );
       
   115 			}
       
   116 		else 
       
   117 			{
       
   118 			// the end of cdata was not found or cdata end was before start -> error
       
   119 			User::Leave( EInvalidCDataStructure );
       
   120 			}
       
   121 
       
   122 		// find a new cdata start that is after the found end
       
   123 		cdataStartPos = searchString.Find(KCDataStart);
       
   124 
       
   125 		}
       
   126 
       
   127 	}
       
   128 
       
   129 
       
   130 // ------------------------------------------------------------------------------------------------
       
   131 // Return the TNSmlBoolean-value's string-representation.
       
   132 // ------------------------------------------------------------------------------------------------
       
   133 TPtrC8 CNSmlXmlParser::BooleanToString( const TNSmlBoolean aValue ) const
       
   134 	{
       
   135 	TPtrC8 str;
       
   136 	switch(aValue)
       
   137 		{
       
   138 		case EBooleanTrue:
       
   139 			{
       
   140 			str.Set(KStringTrue);
       
   141 			break;
       
   142 			}
       
   143 		case EBooleanFalse:
       
   144 			{
       
   145 			str.Set(KStringFalse);
       
   146 			break;
       
   147 			}
       
   148 		default:
       
   149 			{
       
   150 			str.Set(KStringEmpty);
       
   151 			}
       
   152 		}
       
   153 
       
   154 	return str;
       
   155 	}
       
   156 
       
   157 
       
   158 // ------------------------------------------------------------------------------------------------
       
   159 // Returns the TTime-value's string-representation.
       
   160 // ------------------------------------------------------------------------------------------------
       
   161 TBuf8<KDateTimeLength> CNSmlXmlParser::DateTimeToStringL( const TTime& aValue ) const
       
   162 	{
       
   163 	TBuf<KDateTimeLength> str;
       
   164 	
       
   165 	// aValue is not changed but Z character is added to the end of string.
       
   166 	// Messaging uses UTC times and that is reason why time is not changed.
       
   167 	aValue.FormatL( str, _L("%F%Y%M%DT%H%T%SZ") );
       
   168 
       
   169 	// from 16-bit to 8-bit
       
   170 	TBuf8<KDateTimeLength> dt;
       
   171 	dt.Copy(str);
       
   172 
       
   173 	return dt;
       
   174 	}
       
   175 
       
   176 
       
   177 // ------------------------------------------------------------------------------------------------
       
   178 // Returns the integer value's string-representation.
       
   179 // ------------------------------------------------------------------------------------------------
       
   180 TBuf8<KIntegerMaxLength> CNSmlXmlParser::IntegerToString( const TInt aValue ) const
       
   181 	{
       
   182 	TBuf8<KIntegerMaxLength> str;
       
   183 	str.AppendNum(aValue);
       
   184 	return str;
       
   185 	}
       
   186 
       
   187 
       
   188 // ------------------------------------------------------------------------------------------------
       
   189 // Returns the boolean representation of the string or leaves if error (EInvalidBooleanValue).
       
   190 // ------------------------------------------------------------------------------------------------
       
   191 TNSmlBoolean CNSmlXmlParser::StringToBooleanL( const TPtrC8& aValue ) const
       
   192 	{
       
   193 	if( aValue == KStringTrue )
       
   194 		return EBooleanTrue;
       
   195 	else if( aValue == KStringFalse || aValue == KStringEmpty )
       
   196 		return EBooleanFalse;
       
   197 	else
       
   198 		User::Leave(EInvalidBooleanValue);
       
   199 
       
   200 	return EBooleanMissing;
       
   201 	}
       
   202 
       
   203 	
       
   204 // ------------------------------------------------------------------------------------------------
       
   205 // Returns the integer representation of the string or leaves if error (EInvalidIntegerValue).
       
   206 // ------------------------------------------------------------------------------------------------
       
   207 TInt CNSmlXmlParser::StringToIntegerL( const TPtrC8& aValue ) const
       
   208 	{
       
   209 	if (aValue.Length() <= 0)
       
   210 		return 0;
       
   211 
       
   212 	// convert the data to an integer
       
   213 	TLex8 lex(aValue);
       
   214 	TUint uValue = 0;
       
   215 	TBool isNegative = EFalse;
       
   216 
       
   217 	TChar c = lex.Peek();
       
   218 
       
   219 	// check for a minus or plus sign
       
   220 	if ( c == '-' )
       
   221 		{
       
   222 		isNegative = ETrue;
       
   223 		lex.Inc();
       
   224 		}
       
   225 	else if ( c == '+' )
       
   226 		{
       
   227 		lex.Inc();
       
   228 		}
       
   229 
       
   230 	TRadix radix = EDecimal;
       
   231 	c = lex.Peek();
       
   232 
       
   233 	if (c == '0') // octal or hex
       
   234 		{
       
   235 		lex.Get();
       
   236 		c = lex.Get();
       
   237 		if ( c == 'x' || c == 'X' )
       
   238 			{
       
   239 			radix = EHex;
       
   240 			}
       
   241 		else
       
   242 			{
       
   243 			radix = EOctal;
       
   244 			lex.UnGet(); // back up
       
   245 			}
       
   246 		}
       
   247 
       
   248 	TInt err = lex.Val(uValue, radix);
       
   249 	if ( err != KErrNone )
       
   250 		User::Leave(EInvalidIntegerValue);
       
   251 
       
   252 	TInt value = uValue;
       
   253 
       
   254 	return isNegative ? value*(-1) : value;
       
   255 	}
       
   256 
       
   257 
       
   258 // ------------------------------------------------------------------------------------------------
       
   259 // Returns the TTime representation of the string or leaves if error (EInvalidDatetimeValue).
       
   260 // UTC times are not supported, i.e. datetimes that have Z-ending are treated as 
       
   261 // local times.
       
   262 // ------------------------------------------------------------------------------------------------
       
   263 TTime CNSmlXmlParser::StringToTTimeL( TPtrC8& aValue ) const
       
   264 	{
       
   265 	// check that there is data
       
   266 	if (aValue.Length() <= 0)
       
   267 		User::Leave( EInvalidDatetimeValue );
       
   268 
       
   269 	// format the data into a TTime
       
   270 
       
   271 	if (aValue[aValue.Length()-1] == 'Z')
       
   272 		{
       
   273 		// The datetime is in UTC, which is not supported
       
   274 		// no correction done, treat as local time
       
   275 		aValue.Set( aValue.Left( aValue.Length()-1 ) );
       
   276 		}
       
   277 
       
   278 	TDateTime datetime(0,(TMonth)0,0,0,0,0,0);
       
   279 
       
   280 	// read datetime and check errors
       
   281 
       
   282 	TInt error = KErrNone;
       
   283 
       
   284 	// read year
       
   285 	TPtrC8 str = aValue.Left(4);
       
   286 	TLex8 lex(str);
       
   287 	TInt value;
       
   288 	error = lex.Val(value);
       
   289 	CheckDatetimeErrorL( error );
       
   290 	error  = datetime.SetYear(value);
       
   291 	CheckDatetimeErrorL( error );
       
   292 
       
   293 	// read month
       
   294 	str.Set(aValue.Mid(4, 2));
       
   295 	lex.Assign(str);
       
   296 	error = lex.Val(value);
       
   297 	CheckDatetimeErrorL( error );
       
   298 	--value;
       
   299 	error = datetime.SetMonth((TMonth)value);
       
   300 	CheckDatetimeErrorL( error );
       
   301 
       
   302 	// read day
       
   303 	str.Set(aValue.Mid(6, 2));
       
   304 	lex.Assign(str);
       
   305 	error = lex.Val(value);
       
   306 	CheckDatetimeErrorL( error );
       
   307 	--value;
       
   308 	error = datetime.SetDay(value);
       
   309 	CheckDatetimeErrorL( error );
       
   310 
       
   311 	// Skip character 'T' and read hour
       
   312 	str.Set(aValue.Mid(9, 2));
       
   313 	lex.Assign(str);
       
   314 	error = lex.Val(value);
       
   315 	CheckDatetimeErrorL( error );
       
   316 	error = datetime.SetHour(value);
       
   317 	CheckDatetimeErrorL( error );
       
   318 
       
   319 	// minutes
       
   320 	str.Set(aValue.Mid(11, 2));
       
   321 	lex.Assign(str);
       
   322 	error = lex.Val(value);
       
   323 	CheckDatetimeErrorL( error );
       
   324 	error = datetime.SetMinute(value);
       
   325 	CheckDatetimeErrorL( error );
       
   326 
       
   327 	// seconds
       
   328 	str.Set(aValue.Mid(13, 2));
       
   329 	lex.Assign(str);
       
   330 	error = lex.Val(value);
       
   331 	CheckDatetimeErrorL( error );
       
   332 	error = datetime.SetSecond(value);
       
   333 	CheckDatetimeErrorL( error );
       
   334 
       
   335 	return TTime(datetime);
       
   336 	}
       
   337 
       
   338 
       
   339 // ------------------------------------------------------------------------------------------------
       
   340 // Adds start element, the value and end element to aPtr.
       
   341 // ------------------------------------------------------------------------------------------------
       
   342 void CNSmlXmlParser::AppendElement( TPtr8& aPtr, const TDesC8& aElementName, const TDesC8& aValue ) const
       
   343 	{
       
   344 	// start element
       
   345 	aPtr.Append(KElementStart);
       
   346 	aPtr.Append(aElementName);
       
   347 	aPtr.Append(KElementEnd);
       
   348 
       
   349 	// value
       
   350 	aPtr.Append(aValue);
       
   351 
       
   352 	// end element
       
   353 	aPtr.Append(KElementStart);
       
   354 	aPtr.Append(KCharacterSlash);
       
   355 	aPtr.Append(aElementName);
       
   356 	aPtr.Append(KElementEnd);
       
   357 	}
       
   358 
       
   359 
       
   360 // ------------------------------------------------------------------------------------------------
       
   361 // Forms an element using the given element name and appends it to the given string.
       
   362 // ------------------------------------------------------------------------------------------------
       
   363 void CNSmlXmlParser::AppendElement( TPtr8& aPtr, const TDesC8& aElementName ) const
       
   364 	{
       
   365 	aPtr.Append(KElementStart);
       
   366 	aPtr.Append(aElementName);
       
   367 	aPtr.Append(KElementEnd);
       
   368 	}
       
   369 
       
   370 
       
   371 // ------------------------------------------------------------------------------------------------
       
   372 // Forms an end element using the given element name and appends it to the given string.
       
   373 // ------------------------------------------------------------------------------------------------
       
   374 void CNSmlXmlParser::AppendEndElement( TPtr8& aPtr, const TDesC8& aElementName ) const
       
   375 	{
       
   376 	aPtr.Append(KElementStart);
       
   377 	aPtr.Append(KCharacterSlash);
       
   378 	aPtr.Append(aElementName);
       
   379 	aPtr.Append(KElementEnd);
       
   380 	}
       
   381 
       
   382 
       
   383 // ------------------------------------------------------------------------------------------------
       
   384 // Returns the total length of start and end tag.
       
   385 // ------------------------------------------------------------------------------------------------
       
   386 TInt CNSmlXmlParser::SizeOfElements( const TDesC8& aElementName ) const
       
   387 	{
       
   388 	TInt size = 0;
       
   389 
       
   390 	// start element plus end element ( 1 = length of '/' char )
       
   391 	size += 2*aElementName.Length() + 1;
       
   392 	size += 2*KElementStartEndWidth; // '<' and '>'
       
   393 
       
   394 	return size;
       
   395 	}
       
   396 
       
   397 
       
   398 // ------------------------------------------------------------------------------------------------
       
   399 // Returns the length of the given boolean element and it's data if it was a string.
       
   400 // ------------------------------------------------------------------------------------------------
       
   401 TInt CNSmlXmlParser::SizeOfBoolean( const TNSmlBoolean aValue, const TDesC8& aElementName ) const
       
   402 	{
       
   403 	TInt size = 0;
       
   404 	size += SizeOfElements( aElementName );
       
   405 	switch ( aValue )
       
   406 		{
       
   407 		case EBooleanTrue:
       
   408 			return size+4; // "true"
       
   409 		case EBooleanFalse:
       
   410 			return size+5; // "false"
       
   411 		default:
       
   412 			return 0;
       
   413 		}
       
   414 	}
       
   415 
       
   416 
       
   417 // ------------------------------------------------------------------------------------------------
       
   418 // Returns the length of the given datetime element and it's data if it was a string.
       
   419 // ------------------------------------------------------------------------------------------------
       
   420 TInt CNSmlXmlParser::SizeOfDatetime( const TDesC8& aElementName ) const
       
   421 	{
       
   422 	TInt size = SizeOfElements( aElementName ) + KDateTimeLength;
       
   423 	return size;
       
   424 	}
       
   425 
       
   426 
       
   427 // ------------------------------------------------------------------------------------------------
       
   428 // Returns the maximum length of the given integer element and it's data if it was a string.
       
   429 // ------------------------------------------------------------------------------------------------
       
   430 TInt CNSmlXmlParser::SizeOfInteger( const TDesC8& aElementName ) const
       
   431 	{
       
   432 	TInt size = SizeOfElements( aElementName ) + KIntegerMaxLength;
       
   433 	return size;
       
   434 	}
       
   435 
       
   436 
       
   437 // ------------------------------------------------------------------------------------------------
       
   438 // Returns the length of the given string element and it's data if it was a string.
       
   439 // ------------------------------------------------------------------------------------------------
       
   440 TInt CNSmlXmlParser::SizeOfString( const HBufC8* aValue, const TDesC8& aElementName ) const
       
   441 	{
       
   442 	TInt size = SizeOfElements( aElementName ) + aValue->Length();
       
   443 	return size;
       
   444 	}
       
   445 
       
   446 
       
   447 // ------------------------------------------------------------------------------------------------
       
   448 // Finds entities and replaces them with the characters they represent. Returns 
       
   449 // an integer indicating the size change in aXml.
       
   450 // ------------------------------------------------------------------------------------------------
       
   451 TInt CNSmlXmlParser::EntitiesToCharactersL( HBufC8*& aXml, TInt aStartPos, TInt aEndPos ) const
       
   452 	{
       
   453 	TInt change = 0;
       
   454 	TInt changeSum = 0;
       
   455 
       
   456 	change = ReplaceL(aXml, KEntityLT, KLessThan, aStartPos, aEndPos);
       
   457 	changeSum += change;
       
   458 	aEndPos += change;
       
   459 
       
   460 	change = ReplaceL(aXml, KEntityGT, KGreaterThan, aStartPos, aEndPos);
       
   461 	changeSum += change;
       
   462 	aEndPos += change;
       
   463 
       
   464 	change = ReplaceL(aXml, KEntityAMP, KAmpersand, aStartPos, aEndPos);
       
   465 	changeSum += change;
       
   466 	aEndPos += change;
       
   467 
       
   468 	change = ReplaceL(aXml, KEntityAPOS, KApostrophe, aStartPos, aEndPos);
       
   469 	changeSum += change;
       
   470 	aEndPos += change;
       
   471 
       
   472 	change = ReplaceL(aXml, KEntityQUOT, KQuotation, aStartPos, aEndPos);
       
   473 	changeSum += change;
       
   474 
       
   475 	return changeSum;
       
   476 	}
       
   477 
       
   478 
       
   479 // ------------------------------------------------------------------------------------------------
       
   480 // Finds special characters and replaces them with corresponding entities. Returns 
       
   481 // an integer indicating the size change in aXml.
       
   482 // ------------------------------------------------------------------------------------------------
       
   483 TInt CNSmlXmlParser::CharactersToEntitiesL( HBufC8*& aXml, TInt aStartPos, TInt aEndPos ) const
       
   484 	{
       
   485 	TInt change = 0;
       
   486 	TInt changeSum = 0;
       
   487 
       
   488 	// Note: this replace has to be the first one, since it changes 
       
   489 	// &-characters to &amp;s and all the other replaces generate 
       
   490 	// &-characters as they are entities.
       
   491 	change = ReplaceL(aXml, KAmpersand, KEntityAMP, aStartPos, aEndPos);
       
   492 	changeSum += change;
       
   493 	aEndPos += change;
       
   494 
       
   495 	change = ReplaceL(aXml, KLessThan, KEntityLT, aStartPos, aEndPos);
       
   496 	changeSum += change;
       
   497 	aEndPos += change;
       
   498 
       
   499 	change = ReplaceL(aXml, KGreaterThan, KEntityGT, aStartPos, aEndPos);
       
   500 	changeSum += change;
       
   501 	aEndPos += change;
       
   502 
       
   503 	change = ReplaceL(aXml, KApostrophe, KEntityAPOS, aStartPos, aEndPos);
       
   504 	changeSum += change;
       
   505 	aEndPos += change;
       
   506 
       
   507 	change = ReplaceL(aXml, KQuotation, KEntityQUOT, aStartPos, aEndPos);
       
   508 	changeSum += change;
       
   509 
       
   510 	return changeSum;
       
   511 	}
       
   512 
       
   513 
       
   514 // ------------------------------------------------------------------------------------------------
       
   515 // Returns ETrue if all the characters in the given text are whitespace 
       
   516 // characters, else EFalse.
       
   517 // ------------------------------------------------------------------------------------------------
       
   518 TBool CNSmlXmlParser::IsWhitespace( const TDesC8& aText ) const
       
   519 	{
       
   520 	// loop the string character by character
       
   521 	TText c;
       
   522 	for ( TInt i=0; i < aText.Length(); ++i )
       
   523 		{
       
   524 		c = aText[i];
       
   525 		switch( c )
       
   526 			{
       
   527 			case KWhitespaceEmpty:
       
   528 				break;
       
   529 			case KWhitespaceLineFeed:
       
   530 				break;
       
   531 			case KWhitespaceNewLine:
       
   532 				break;
       
   533 			case KWhitespaceTabular:
       
   534 				break;
       
   535 			case KWhitespaceLineFeedNewLine:
       
   536 				break;
       
   537 			default:
       
   538 				return EFalse;
       
   539 			}
       
   540 		}
       
   541 
       
   542 	return ETrue;
       
   543 	}
       
   544 
       
   545 
       
   546 // ------------------------------------------------------------------------------------------------
       
   547 // Leaves with EInvalidXmlError if the given string is not whitespace.
       
   548 // ------------------------------------------------------------------------------------------------
       
   549 void CNSmlXmlParser::LeaveIfNotWhiteSpaceL( const TDesC8& aText ) const
       
   550 	{
       
   551 	if ( !IsWhitespace( aText ) )
       
   552 		{
       
   553 		User::Leave( EInvalidXmlError );
       
   554 		}
       
   555 	}
       
   556 
       
   557 
       
   558 // ------------------------------------------------------------------------------------------------
       
   559 // Maps the given value to TNSmlParserGeneratorError.
       
   560 // ------------------------------------------------------------------------------------------------
       
   561 TNSmlParserGeneratorError CNSmlXmlParser::CheckError( const TInt error ) const
       
   562 	{
       
   563 	if ( error == KErrNoMemory )
       
   564 		{
       
   565 		return EOutOfMemory;
       
   566 		}
       
   567 	else if ( error < KErrNone )
       
   568 		{
       
   569 		// some system wide error, should not occur
       
   570 		return EUnknownError;
       
   571 		}
       
   572 	else if ( error != EErrorNone )
       
   573 		{
       
   574 		return (TNSmlParserGeneratorError)error;
       
   575 		}
       
   576 
       
   577 	return EErrorNone;
       
   578 	}
       
   579 
       
   580 
       
   581 // ------------------------------------------------------------------------------------------------
       
   582 // Parses the given xml and calls NextDataL and NextElementL methods when finds 
       
   583 // data or element. 
       
   584 // ------------------------------------------------------------------------------------------------
       
   585 void CNSmlXmlParser::ParseL( TPtrC8& aXml )
       
   586 	{
       
   587 
       
   588 	ResetBufferL(iBuffer);
       
   589 	ResetBufferL(iCompleteBuffer);
       
   590 
       
   591 	// boolean indicating if reading element name (true) or insides of 
       
   592 	// an element (false)
       
   593 	TBool readingElementName = EFalse;
       
   594 	TText c;
       
   595 
       
   596 	for( TInt i=0; i < aXml.Length(); ++i )
       
   597 		{
       
   598 		c = aXml[i];
       
   599 		switch(c)
       
   600 			{
       
   601 			case KElementStart:
       
   602 				// if currently reading element, error
       
   603 				if( readingElementName )
       
   604 					{
       
   605 					User::Leave(EInvalidXmlError);
       
   606 					}
       
   607 
       
   608 				if( aXml.Length()-i >= KCDataStart().Length() &&
       
   609 					!aXml.Mid(i, KCDataStart().Length()).Compare(KCDataStart()) )
       
   610 					{ // cdata
       
   611 					aXml.Set( aXml.Right( aXml.Length() - i ) );
       
   612 					TInt endPos = aXml.Find(KCDataEnd);
       
   613 
       
   614 					TPtrC8 cdata = _L8("");
       
   615 					if ( endPos == KErrNotFound )
       
   616 						{
       
   617 						User::Leave(EInvalidCDataStructure);
       
   618 						}
       
   619 
       
   620 					cdata.Set( aXml.Mid( KCDataStart().Length(), endPos - KCDataStart().Length() ) );
       
   621 					aXml.Set( aXml.Right( aXml.Length() - endPos - KCDataEnd().Length() ) );
       
   622 
       
   623 					i = -1;
       
   624 
       
   625 					// add current buffer to complete buffer
       
   626 					EntitiesToCharactersL( iBuffer, 0, iBuffer->Length() );
       
   627 					AddToCompleteL(*iBuffer);
       
   628 					ResetBufferL(iBuffer);
       
   629 					AddToCompleteL(cdata);
       
   630 					}
       
   631 #ifndef __NO_XML_COMMENTS_
       
   632 				else if( aXml.Length()-i >= KCommentStart().Length() &&
       
   633 					!aXml.Mid(i, KCommentStart().Length()).Compare(KCommentStart()) )
       
   634 					{ // comment
       
   635 					aXml.Set( aXml.Right( aXml.Length() - i ) );
       
   636 					TInt endPos = aXml.Find(KCommentEnd);
       
   637 
       
   638 					if ( endPos != KErrNotFound )
       
   639 						{
       
   640 						aXml.Set( aXml.Right( aXml.Length() - endPos - KCommentEnd().Length() ) );
       
   641 						}
       
   642 					else
       
   643 						{
       
   644 						User::Leave(EInvalidXmlError);
       
   645 						}
       
   646 
       
   647 					i = -1;
       
   648 					}
       
   649 #endif
       
   650 				else 
       
   651 					{
       
   652 					// send the buffer
       
   653 					EntitiesToCharactersL( iBuffer, 0, iBuffer->Length() );
       
   654 					AddToCompleteL(*iBuffer);
       
   655 					NextDataL(*iCompleteBuffer);
       
   656 					ResetBufferL(iBuffer);
       
   657 					ResetBufferL(iCompleteBuffer);
       
   658 					readingElementName = ETrue;
       
   659 					}
       
   660 
       
   661 				break;
       
   662 			case KElementEnd:
       
   663 				// stop reading element name
       
   664 				if( !readingElementName )
       
   665 					{
       
   666 					User::Leave(EInvalidXmlError);
       
   667 					}
       
   668 				else 
       
   669 					{
       
   670 					NextElementL(*iBuffer);
       
   671 					ResetBufferL(iBuffer);
       
   672 					readingElementName = EFalse;
       
   673 					}
       
   674 				break;
       
   675 			default:
       
   676 				// add char to buffer
       
   677 				AddToBufferL(c, iBuffer);
       
   678 				break;
       
   679 			}
       
   680 		}
       
   681 
       
   682 	EntitiesToCharactersL( iBuffer, 0, iBuffer->Length() );
       
   683 	AddToCompleteL(*iBuffer);
       
   684 	NextDataL(*iCompleteBuffer);
       
   685 	}
       
   686 
       
   687 
       
   688 // ------------------------------------------------------------------------------------------------
       
   689 // Adds the given string to iCompleteBuffer
       
   690 // ------------------------------------------------------------------------------------------------
       
   691 void CNSmlXmlParser::AddToCompleteL( const TPtrC8 aStr )
       
   692 	{
       
   693 	if(!iCompleteBuffer)
       
   694 		{
       
   695 		iCompleteBuffer = HBufC8::NewL(aStr.Length());
       
   696 		}
       
   697 
       
   698 	TPtr8 ptr = iCompleteBuffer->Des();
       
   699 	if( ptr.MaxLength() < iCompleteBuffer->Length()+aStr.Length() )
       
   700 		{
       
   701 		iCompleteBuffer = iCompleteBuffer->ReAllocL(iCompleteBuffer->Length()+aStr.Length());
       
   702 		ptr.Set(iCompleteBuffer->Des());
       
   703 		}
       
   704 
       
   705 	ptr.Append(aStr);
       
   706 	}
       
   707 
       
   708 
       
   709 // ------------------------------------------------------------------------------------------------
       
   710 // Deletes the given buffer and initializes it again to length 10
       
   711 // ------------------------------------------------------------------------------------------------
       
   712 void CNSmlXmlParser::ResetBufferL( HBufC8*& aBuf ) const
       
   713 	{
       
   714 	if( aBuf )
       
   715 		{
       
   716 		delete aBuf;
       
   717 		aBuf = NULL;
       
   718 		}
       
   719 
       
   720 	aBuf = HBufC8::NewL(10);
       
   721 	}
       
   722 
       
   723 
       
   724 // ------------------------------------------------------------------------------------------------
       
   725 // Adds the given char to given buffer
       
   726 // ------------------------------------------------------------------------------------------------
       
   727 void CNSmlXmlParser::AddToBufferL( const TText c, HBufC8*& aBuf ) const
       
   728 	{
       
   729 	TPtr8 ptr = aBuf->Des();
       
   730 	if( ptr.MaxLength() == aBuf->Length()+1 )
       
   731 		{
       
   732 		aBuf = aBuf->ReAllocL(aBuf->Length()+10);
       
   733 		ptr.Set(aBuf->Des());
       
   734 		}
       
   735 
       
   736 	TChar str = c;
       
   737 	ptr.Append(str);
       
   738 	}
       
   739 
       
   740 
       
   741 
       
   742 // ------------------------------------------------------------------------------------------------
       
   743 // Replaces all occurances of aTarget in aText with aItem. Returns an integer indicating 
       
   744 // the size change in aText. aStartPos and aEndPos indicate the start and end positions 
       
   745 // of aText to be parsed (if whole string should be parsed, use 0 and aText.Length()).
       
   746 // ------------------------------------------------------------------------------------------------
       
   747 TInt CNSmlXmlParser::ReplaceL( HBufC8*& aText, const TDesC8& aTarget, const TDesC8& aItem, TInt aStartPos, TInt aEndPos ) const
       
   748 	{
       
   749 	TInt change = 0;
       
   750 	TInt searchPos = aStartPos;
       
   751 	TPtrC8 text = aText->Mid(aStartPos, aEndPos-aStartPos);
       
   752 	TInt pos = text.Find(aTarget);
       
   753 
       
   754 	while ( pos != KErrNotFound )
       
   755 		{
       
   756 		pos += searchPos;
       
   757 
       
   758 		TInt currentChange = aItem.Length() - aTarget.Length();
       
   759 		change += currentChange;
       
   760 		aEndPos += currentChange;
       
   761 		searchPos = pos;
       
   762 
       
   763 		if ( currentChange > 0 )
       
   764 			{
       
   765 			searchPos += currentChange;
       
   766 
       
   767 			// check that aText is large enough
       
   768 			if ( aText->Des().MaxLength() < aText->Length()+currentChange )
       
   769 				{
       
   770 				aText = aText->ReAllocL(aText->Length()+currentChange);
       
   771 				}
       
   772 			}
       
   773 
       
   774 		// the actual replace
       
   775 		aText->Des().Replace(pos, aTarget.Length(), aItem);
       
   776 
       
   777 		text.Set( aText->Mid(searchPos, aEndPos-searchPos) );
       
   778 		pos = text.Find(aTarget);
       
   779 		}
       
   780 
       
   781 	return change;
       
   782 	}
       
   783 
       
   784 
       
   785 // ------------------------------------------------------------------------------------------------
       
   786 // 
       
   787 // ------------------------------------------------------------------------------------------------
       
   788 void CNSmlXmlParser::CheckDatetimeErrorL( const TInt error ) const
       
   789 	{
       
   790 	if ( error != KErrNone )
       
   791 		{
       
   792 		User::Leave( EInvalidDatetimeValue );
       
   793 		}
       
   794 	}
       
   795 
       
   796 //End of File
       
   797