--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/omads/omadsextensions/dsutils/emailxmlutils/src/nsmlxmlparser.cpp Mon Nov 23 14:46:41 2009 +0200
@@ -0,0 +1,797 @@
+/*
+* Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Sources
+*
+*/
+
+
+// 1.2 Changes: nsmlxmlparser module added
+
+// ------------------------------------------------------------------------------------------------
+// Includes
+// ------------------------------------------------------------------------------------------------
+#include <s32buf.h>
+#include <s32file.h>
+#include "nsmlxmlparser.h"
+
+
+// ------------------------------------------------------------------------------------------------
+//
+// CNSmlXmlParser methods
+//
+// ------------------------------------------------------------------------------------------------
+
+// ------------------------------------------------------------------------------------------------
+// Constructor
+// ------------------------------------------------------------------------------------------------
+EXPORT_C CNSmlXmlParser::CNSmlXmlParser()
+ {
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Destructor.
+// ------------------------------------------------------------------------------------------------
+EXPORT_C CNSmlXmlParser::~CNSmlXmlParser()
+ {
+ if( iBuffer ) delete iBuffer;
+ if ( iCompleteBuffer ) delete iCompleteBuffer;
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Parses the given string for cdata areas and entitys. If a cdata area is
+// found, the data in it is skipped over. The entities outside cdata are converted
+// into characters they represent (but only if cdata is found).
+// Note: This method is intended for processing the CDATA used right after <Data>.
+// I.e. this method removes the cdata-elements used for wrapping the whole xml data
+// and processes the string so that the inner cdatas used in the xml become valid.
+// THIS METHOD SHOULD BE CALLED RIGHT IN THE BEGINNING OF PARSING IF <Data>-BLOCK
+// IS WRAPPED WITHIN CDATA.
+// ------------------------------------------------------------------------------------------------
+void CNSmlXmlParser::PreProcessL( HBufC8* aXml ) const
+ {
+ // take a modifiable pointer
+ TPtr8 xml = aXml->Des();
+
+ // the string used for searching and moving in the string
+ TPtrC8 searchString(*aXml);
+
+ // the current position in the original string
+ TInt searchStartPos = 0;
+
+ // find the first cdata start
+ TInt cdataStartPos = searchString.Find(KCDataStart);
+
+ // If CDATA is not found from beginning then data is not inside CDATA and then
+ // preprocessing is not needed
+ if ( cdataStartPos != 0 )
+ {
+ return;
+ }
+
+ TInt cdataEndPos = KErrNotFound;
+
+ // while cdata is found
+ while ( cdataStartPos != KErrNotFound )
+ {
+ cdataStartPos += searchStartPos;
+
+ // find an end of cdata before entities are converted
+ cdataEndPos = searchString.Find(KCDataEnd);
+
+ // convert entities between search start and cdata start
+ TInt entityChange = EntitiesToCharactersL(aXml, searchStartPos, cdataStartPos);
+ xml.Set(aXml->Des());
+ cdataStartPos += entityChange;
+
+ if ( cdataEndPos != KErrNotFound )
+ {
+ cdataEndPos += entityChange;
+ cdataEndPos += searchStartPos;
+
+ // if the end is before start -> error
+ if (cdataEndPos < cdataStartPos)
+ User::Leave( EInvalidCDataStructure );
+
+ // remove cdata end
+ xml.Delete(cdataEndPos, KCDataEnd().Length());
+ // remove cdata start
+ xml.Delete(cdataStartPos, KCDataStart().Length());
+
+ searchStartPos = cdataEndPos - KCDataStart().Length();
+ searchString.Set( xml.Right(xml.Length() - searchStartPos) );
+ }
+ else
+ {
+ // the end of cdata was not found or cdata end was before start -> error
+ User::Leave( EInvalidCDataStructure );
+ }
+
+ // find a new cdata start that is after the found end
+ cdataStartPos = searchString.Find(KCDataStart);
+
+ }
+
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Return the TNSmlBoolean-value's string-representation.
+// ------------------------------------------------------------------------------------------------
+TPtrC8 CNSmlXmlParser::BooleanToString( const TNSmlBoolean aValue ) const
+ {
+ TPtrC8 str;
+ switch(aValue)
+ {
+ case EBooleanTrue:
+ {
+ str.Set(KStringTrue);
+ break;
+ }
+ case EBooleanFalse:
+ {
+ str.Set(KStringFalse);
+ break;
+ }
+ default:
+ {
+ str.Set(KStringEmpty);
+ }
+ }
+
+ return str;
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Returns the TTime-value's string-representation.
+// ------------------------------------------------------------------------------------------------
+TBuf8<KDateTimeLength> CNSmlXmlParser::DateTimeToStringL( const TTime& aValue ) const
+ {
+ TBuf<KDateTimeLength> str;
+
+ // aValue is not changed but Z character is added to the end of string.
+ // Messaging uses UTC times and that is reason why time is not changed.
+ aValue.FormatL( str, _L("%F%Y%M%DT%H%T%SZ") );
+
+ // from 16-bit to 8-bit
+ TBuf8<KDateTimeLength> dt;
+ dt.Copy(str);
+
+ return dt;
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Returns the integer value's string-representation.
+// ------------------------------------------------------------------------------------------------
+TBuf8<KIntegerMaxLength> CNSmlXmlParser::IntegerToString( const TInt aValue ) const
+ {
+ TBuf8<KIntegerMaxLength> str;
+ str.AppendNum(aValue);
+ return str;
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Returns the boolean representation of the string or leaves if error (EInvalidBooleanValue).
+// ------------------------------------------------------------------------------------------------
+TNSmlBoolean CNSmlXmlParser::StringToBooleanL( const TPtrC8& aValue ) const
+ {
+ if( aValue == KStringTrue )
+ return EBooleanTrue;
+ else if( aValue == KStringFalse || aValue == KStringEmpty )
+ return EBooleanFalse;
+ else
+ User::Leave(EInvalidBooleanValue);
+
+ return EBooleanMissing;
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Returns the integer representation of the string or leaves if error (EInvalidIntegerValue).
+// ------------------------------------------------------------------------------------------------
+TInt CNSmlXmlParser::StringToIntegerL( const TPtrC8& aValue ) const
+ {
+ if (aValue.Length() <= 0)
+ return 0;
+
+ // convert the data to an integer
+ TLex8 lex(aValue);
+ TUint uValue = 0;
+ TBool isNegative = EFalse;
+
+ TChar c = lex.Peek();
+
+ // check for a minus or plus sign
+ if ( c == '-' )
+ {
+ isNegative = ETrue;
+ lex.Inc();
+ }
+ else if ( c == '+' )
+ {
+ lex.Inc();
+ }
+
+ TRadix radix = EDecimal;
+ c = lex.Peek();
+
+ if (c == '0') // octal or hex
+ {
+ lex.Get();
+ c = lex.Get();
+ if ( c == 'x' || c == 'X' )
+ {
+ radix = EHex;
+ }
+ else
+ {
+ radix = EOctal;
+ lex.UnGet(); // back up
+ }
+ }
+
+ TInt err = lex.Val(uValue, radix);
+ if ( err != KErrNone )
+ User::Leave(EInvalidIntegerValue);
+
+ TInt value = uValue;
+
+ return isNegative ? value*(-1) : value;
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Returns the TTime representation of the string or leaves if error (EInvalidDatetimeValue).
+// UTC times are not supported, i.e. datetimes that have Z-ending are treated as
+// local times.
+// ------------------------------------------------------------------------------------------------
+TTime CNSmlXmlParser::StringToTTimeL( TPtrC8& aValue ) const
+ {
+ // check that there is data
+ if (aValue.Length() <= 0)
+ User::Leave( EInvalidDatetimeValue );
+
+ // format the data into a TTime
+
+ if (aValue[aValue.Length()-1] == 'Z')
+ {
+ // The datetime is in UTC, which is not supported
+ // no correction done, treat as local time
+ aValue.Set( aValue.Left( aValue.Length()-1 ) );
+ }
+
+ TDateTime datetime(0,(TMonth)0,0,0,0,0,0);
+
+ // read datetime and check errors
+
+ TInt error = KErrNone;
+
+ // read year
+ TPtrC8 str = aValue.Left(4);
+ TLex8 lex(str);
+ TInt value;
+ error = lex.Val(value);
+ CheckDatetimeErrorL( error );
+ error = datetime.SetYear(value);
+ CheckDatetimeErrorL( error );
+
+ // read month
+ str.Set(aValue.Mid(4, 2));
+ lex.Assign(str);
+ error = lex.Val(value);
+ CheckDatetimeErrorL( error );
+ --value;
+ error = datetime.SetMonth((TMonth)value);
+ CheckDatetimeErrorL( error );
+
+ // read day
+ str.Set(aValue.Mid(6, 2));
+ lex.Assign(str);
+ error = lex.Val(value);
+ CheckDatetimeErrorL( error );
+ --value;
+ error = datetime.SetDay(value);
+ CheckDatetimeErrorL( error );
+
+ // Skip character 'T' and read hour
+ str.Set(aValue.Mid(9, 2));
+ lex.Assign(str);
+ error = lex.Val(value);
+ CheckDatetimeErrorL( error );
+ error = datetime.SetHour(value);
+ CheckDatetimeErrorL( error );
+
+ // minutes
+ str.Set(aValue.Mid(11, 2));
+ lex.Assign(str);
+ error = lex.Val(value);
+ CheckDatetimeErrorL( error );
+ error = datetime.SetMinute(value);
+ CheckDatetimeErrorL( error );
+
+ // seconds
+ str.Set(aValue.Mid(13, 2));
+ lex.Assign(str);
+ error = lex.Val(value);
+ CheckDatetimeErrorL( error );
+ error = datetime.SetSecond(value);
+ CheckDatetimeErrorL( error );
+
+ return TTime(datetime);
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Adds start element, the value and end element to aPtr.
+// ------------------------------------------------------------------------------------------------
+void CNSmlXmlParser::AppendElement( TPtr8& aPtr, const TDesC8& aElementName, const TDesC8& aValue ) const
+ {
+ // start element
+ aPtr.Append(KElementStart);
+ aPtr.Append(aElementName);
+ aPtr.Append(KElementEnd);
+
+ // value
+ aPtr.Append(aValue);
+
+ // end element
+ aPtr.Append(KElementStart);
+ aPtr.Append(KCharacterSlash);
+ aPtr.Append(aElementName);
+ aPtr.Append(KElementEnd);
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Forms an element using the given element name and appends it to the given string.
+// ------------------------------------------------------------------------------------------------
+void CNSmlXmlParser::AppendElement( TPtr8& aPtr, const TDesC8& aElementName ) const
+ {
+ aPtr.Append(KElementStart);
+ aPtr.Append(aElementName);
+ aPtr.Append(KElementEnd);
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Forms an end element using the given element name and appends it to the given string.
+// ------------------------------------------------------------------------------------------------
+void CNSmlXmlParser::AppendEndElement( TPtr8& aPtr, const TDesC8& aElementName ) const
+ {
+ aPtr.Append(KElementStart);
+ aPtr.Append(KCharacterSlash);
+ aPtr.Append(aElementName);
+ aPtr.Append(KElementEnd);
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Returns the total length of start and end tag.
+// ------------------------------------------------------------------------------------------------
+TInt CNSmlXmlParser::SizeOfElements( const TDesC8& aElementName ) const
+ {
+ TInt size = 0;
+
+ // start element plus end element ( 1 = length of '/' char )
+ size += 2*aElementName.Length() + 1;
+ size += 2*KElementStartEndWidth; // '<' and '>'
+
+ return size;
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Returns the length of the given boolean element and it's data if it was a string.
+// ------------------------------------------------------------------------------------------------
+TInt CNSmlXmlParser::SizeOfBoolean( const TNSmlBoolean aValue, const TDesC8& aElementName ) const
+ {
+ TInt size = 0;
+ size += SizeOfElements( aElementName );
+ switch ( aValue )
+ {
+ case EBooleanTrue:
+ return size+4; // "true"
+ case EBooleanFalse:
+ return size+5; // "false"
+ default:
+ return 0;
+ }
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Returns the length of the given datetime element and it's data if it was a string.
+// ------------------------------------------------------------------------------------------------
+TInt CNSmlXmlParser::SizeOfDatetime( const TDesC8& aElementName ) const
+ {
+ TInt size = SizeOfElements( aElementName ) + KDateTimeLength;
+ return size;
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Returns the maximum length of the given integer element and it's data if it was a string.
+// ------------------------------------------------------------------------------------------------
+TInt CNSmlXmlParser::SizeOfInteger( const TDesC8& aElementName ) const
+ {
+ TInt size = SizeOfElements( aElementName ) + KIntegerMaxLength;
+ return size;
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Returns the length of the given string element and it's data if it was a string.
+// ------------------------------------------------------------------------------------------------
+TInt CNSmlXmlParser::SizeOfString( const HBufC8* aValue, const TDesC8& aElementName ) const
+ {
+ TInt size = SizeOfElements( aElementName ) + aValue->Length();
+ return size;
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Finds entities and replaces them with the characters they represent. Returns
+// an integer indicating the size change in aXml.
+// ------------------------------------------------------------------------------------------------
+TInt CNSmlXmlParser::EntitiesToCharactersL( HBufC8*& aXml, TInt aStartPos, TInt aEndPos ) const
+ {
+ TInt change = 0;
+ TInt changeSum = 0;
+
+ change = ReplaceL(aXml, KEntityLT, KLessThan, aStartPos, aEndPos);
+ changeSum += change;
+ aEndPos += change;
+
+ change = ReplaceL(aXml, KEntityGT, KGreaterThan, aStartPos, aEndPos);
+ changeSum += change;
+ aEndPos += change;
+
+ change = ReplaceL(aXml, KEntityAMP, KAmpersand, aStartPos, aEndPos);
+ changeSum += change;
+ aEndPos += change;
+
+ change = ReplaceL(aXml, KEntityAPOS, KApostrophe, aStartPos, aEndPos);
+ changeSum += change;
+ aEndPos += change;
+
+ change = ReplaceL(aXml, KEntityQUOT, KQuotation, aStartPos, aEndPos);
+ changeSum += change;
+
+ return changeSum;
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Finds special characters and replaces them with corresponding entities. Returns
+// an integer indicating the size change in aXml.
+// ------------------------------------------------------------------------------------------------
+TInt CNSmlXmlParser::CharactersToEntitiesL( HBufC8*& aXml, TInt aStartPos, TInt aEndPos ) const
+ {
+ TInt change = 0;
+ TInt changeSum = 0;
+
+ // Note: this replace has to be the first one, since it changes
+ // &-characters to &s and all the other replaces generate
+ // &-characters as they are entities.
+ change = ReplaceL(aXml, KAmpersand, KEntityAMP, aStartPos, aEndPos);
+ changeSum += change;
+ aEndPos += change;
+
+ change = ReplaceL(aXml, KLessThan, KEntityLT, aStartPos, aEndPos);
+ changeSum += change;
+ aEndPos += change;
+
+ change = ReplaceL(aXml, KGreaterThan, KEntityGT, aStartPos, aEndPos);
+ changeSum += change;
+ aEndPos += change;
+
+ change = ReplaceL(aXml, KApostrophe, KEntityAPOS, aStartPos, aEndPos);
+ changeSum += change;
+ aEndPos += change;
+
+ change = ReplaceL(aXml, KQuotation, KEntityQUOT, aStartPos, aEndPos);
+ changeSum += change;
+
+ return changeSum;
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Returns ETrue if all the characters in the given text are whitespace
+// characters, else EFalse.
+// ------------------------------------------------------------------------------------------------
+TBool CNSmlXmlParser::IsWhitespace( const TDesC8& aText ) const
+ {
+ // loop the string character by character
+ TText c;
+ for ( TInt i=0; i < aText.Length(); ++i )
+ {
+ c = aText[i];
+ switch( c )
+ {
+ case KWhitespaceEmpty:
+ break;
+ case KWhitespaceLineFeed:
+ break;
+ case KWhitespaceNewLine:
+ break;
+ case KWhitespaceTabular:
+ break;
+ case KWhitespaceLineFeedNewLine:
+ break;
+ default:
+ return EFalse;
+ }
+ }
+
+ return ETrue;
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Leaves with EInvalidXmlError if the given string is not whitespace.
+// ------------------------------------------------------------------------------------------------
+void CNSmlXmlParser::LeaveIfNotWhiteSpaceL( const TDesC8& aText ) const
+ {
+ if ( !IsWhitespace( aText ) )
+ {
+ User::Leave( EInvalidXmlError );
+ }
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Maps the given value to TNSmlParserGeneratorError.
+// ------------------------------------------------------------------------------------------------
+TNSmlParserGeneratorError CNSmlXmlParser::CheckError( const TInt error ) const
+ {
+ if ( error == KErrNoMemory )
+ {
+ return EOutOfMemory;
+ }
+ else if ( error < KErrNone )
+ {
+ // some system wide error, should not occur
+ return EUnknownError;
+ }
+ else if ( error != EErrorNone )
+ {
+ return (TNSmlParserGeneratorError)error;
+ }
+
+ return EErrorNone;
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Parses the given xml and calls NextDataL and NextElementL methods when finds
+// data or element.
+// ------------------------------------------------------------------------------------------------
+void CNSmlXmlParser::ParseL( TPtrC8& aXml )
+ {
+
+ ResetBufferL(iBuffer);
+ ResetBufferL(iCompleteBuffer);
+
+ // boolean indicating if reading element name (true) or insides of
+ // an element (false)
+ TBool readingElementName = EFalse;
+ TText c;
+
+ for( TInt i=0; i < aXml.Length(); ++i )
+ {
+ c = aXml[i];
+ switch(c)
+ {
+ case KElementStart:
+ // if currently reading element, error
+ if( readingElementName )
+ {
+ User::Leave(EInvalidXmlError);
+ }
+
+ if( aXml.Length()-i >= KCDataStart().Length() &&
+ !aXml.Mid(i, KCDataStart().Length()).Compare(KCDataStart()) )
+ { // cdata
+ aXml.Set( aXml.Right( aXml.Length() - i ) );
+ TInt endPos = aXml.Find(KCDataEnd);
+
+ TPtrC8 cdata = _L8("");
+ if ( endPos == KErrNotFound )
+ {
+ User::Leave(EInvalidCDataStructure);
+ }
+
+ cdata.Set( aXml.Mid( KCDataStart().Length(), endPos - KCDataStart().Length() ) );
+ aXml.Set( aXml.Right( aXml.Length() - endPos - KCDataEnd().Length() ) );
+
+ i = -1;
+
+ // add current buffer to complete buffer
+ EntitiesToCharactersL( iBuffer, 0, iBuffer->Length() );
+ AddToCompleteL(*iBuffer);
+ ResetBufferL(iBuffer);
+ AddToCompleteL(cdata);
+ }
+#ifndef __NO_XML_COMMENTS_
+ else if( aXml.Length()-i >= KCommentStart().Length() &&
+ !aXml.Mid(i, KCommentStart().Length()).Compare(KCommentStart()) )
+ { // comment
+ aXml.Set( aXml.Right( aXml.Length() - i ) );
+ TInt endPos = aXml.Find(KCommentEnd);
+
+ if ( endPos != KErrNotFound )
+ {
+ aXml.Set( aXml.Right( aXml.Length() - endPos - KCommentEnd().Length() ) );
+ }
+ else
+ {
+ User::Leave(EInvalidXmlError);
+ }
+
+ i = -1;
+ }
+#endif
+ else
+ {
+ // send the buffer
+ EntitiesToCharactersL( iBuffer, 0, iBuffer->Length() );
+ AddToCompleteL(*iBuffer);
+ NextDataL(*iCompleteBuffer);
+ ResetBufferL(iBuffer);
+ ResetBufferL(iCompleteBuffer);
+ readingElementName = ETrue;
+ }
+
+ break;
+ case KElementEnd:
+ // stop reading element name
+ if( !readingElementName )
+ {
+ User::Leave(EInvalidXmlError);
+ }
+ else
+ {
+ NextElementL(*iBuffer);
+ ResetBufferL(iBuffer);
+ readingElementName = EFalse;
+ }
+ break;
+ default:
+ // add char to buffer
+ AddToBufferL(c, iBuffer);
+ break;
+ }
+ }
+
+ EntitiesToCharactersL( iBuffer, 0, iBuffer->Length() );
+ AddToCompleteL(*iBuffer);
+ NextDataL(*iCompleteBuffer);
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Adds the given string to iCompleteBuffer
+// ------------------------------------------------------------------------------------------------
+void CNSmlXmlParser::AddToCompleteL( const TPtrC8 aStr )
+ {
+ if(!iCompleteBuffer)
+ {
+ iCompleteBuffer = HBufC8::NewL(aStr.Length());
+ }
+
+ TPtr8 ptr = iCompleteBuffer->Des();
+ if( ptr.MaxLength() < iCompleteBuffer->Length()+aStr.Length() )
+ {
+ iCompleteBuffer = iCompleteBuffer->ReAllocL(iCompleteBuffer->Length()+aStr.Length());
+ ptr.Set(iCompleteBuffer->Des());
+ }
+
+ ptr.Append(aStr);
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Deletes the given buffer and initializes it again to length 10
+// ------------------------------------------------------------------------------------------------
+void CNSmlXmlParser::ResetBufferL( HBufC8*& aBuf ) const
+ {
+ if( aBuf )
+ {
+ delete aBuf;
+ aBuf = NULL;
+ }
+
+ aBuf = HBufC8::NewL(10);
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+// Adds the given char to given buffer
+// ------------------------------------------------------------------------------------------------
+void CNSmlXmlParser::AddToBufferL( const TText c, HBufC8*& aBuf ) const
+ {
+ TPtr8 ptr = aBuf->Des();
+ if( ptr.MaxLength() == aBuf->Length()+1 )
+ {
+ aBuf = aBuf->ReAllocL(aBuf->Length()+10);
+ ptr.Set(aBuf->Des());
+ }
+
+ TChar str = c;
+ ptr.Append(str);
+ }
+
+
+
+// ------------------------------------------------------------------------------------------------
+// Replaces all occurances of aTarget in aText with aItem. Returns an integer indicating
+// the size change in aText. aStartPos and aEndPos indicate the start and end positions
+// of aText to be parsed (if whole string should be parsed, use 0 and aText.Length()).
+// ------------------------------------------------------------------------------------------------
+TInt CNSmlXmlParser::ReplaceL( HBufC8*& aText, const TDesC8& aTarget, const TDesC8& aItem, TInt aStartPos, TInt aEndPos ) const
+ {
+ TInt change = 0;
+ TInt searchPos = aStartPos;
+ TPtrC8 text = aText->Mid(aStartPos, aEndPos-aStartPos);
+ TInt pos = text.Find(aTarget);
+
+ while ( pos != KErrNotFound )
+ {
+ pos += searchPos;
+
+ TInt currentChange = aItem.Length() - aTarget.Length();
+ change += currentChange;
+ aEndPos += currentChange;
+ searchPos = pos;
+
+ if ( currentChange > 0 )
+ {
+ searchPos += currentChange;
+
+ // check that aText is large enough
+ if ( aText->Des().MaxLength() < aText->Length()+currentChange )
+ {
+ aText = aText->ReAllocL(aText->Length()+currentChange);
+ }
+ }
+
+ // the actual replace
+ aText->Des().Replace(pos, aTarget.Length(), aItem);
+
+ text.Set( aText->Mid(searchPos, aEndPos-searchPos) );
+ pos = text.Find(aTarget);
+ }
+
+ return change;
+ }
+
+
+// ------------------------------------------------------------------------------------------------
+//
+// ------------------------------------------------------------------------------------------------
+void CNSmlXmlParser::CheckDatetimeErrorL( const TInt error ) const
+ {
+ if ( error != KErrNone )
+ {
+ User::Leave( EInvalidDatetimeValue );
+ }
+ }
+
+//End of File
+