diff -r 000000000000 -r b16258d2340f applayerprotocols/wappushsupport/XmlLib/XmlPars.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/applayerprotocols/wappushsupport/XmlLib/XmlPars.cpp Tue Feb 02 01:09:52 2010 +0200 @@ -0,0 +1,1585 @@ +// Copyright (c) 1999-2009 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: +// + +// Local includes +// +#include "XmlPars.h" + +// System includes +// +#include +#include +#include +#include +#include // For the error codes + +LOCAL_C TBool Compare(TInt aLength,const TText* aStringA,const TDesC& aStringB) + { + if(aLength==aStringB.Length()) + { + const TText* stringB=aStringB.Ptr(); + while(aLength>=(TInt)(sizeof(TInt32)/sizeof(TText))) + { + if(*(TInt32*)stringB!=*(TInt32*)aStringA) + return EFalse; + stringB+=(sizeof(TInt32)/sizeof(TText)); + aStringA+=(sizeof(TInt32)/sizeof(TText)); + aLength-=(sizeof(TInt32)/sizeof(TText)); + } + while(aLength>0) + { + if(*stringB++!=*aStringA++) + return EFalse; + aLength--; + } + return ETrue; + } + return EFalse; + } + +CXmlParser::CXmlParser(CAttributeLookupTable& aAttributeLUT) +: CBNFParser(aAttributeLUT), iErrorCode(KErrNone), iDataGathering(EFalse) + { + } + +CXmlParser* CXmlParser::NewL(CAttributeLookupTable& aAttributeLUT) + { + CXmlParser* self = new(ELeave) CXmlParser(aAttributeLUT); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return(self); + } + +CXmlParser::~CXmlParser() + { + __XML_LOG_ENTER(_L("CXmlParser::~CXmlParser()")); + PreAttribute(*this); // Clears up attribute variables + PreExternalID(*this); + delete iName; + delete iCData; + delete iDTDUrl; + delete iDocType; + delete iXmlVersionString; + delete iDocRootName; + __XML_LOG_RETURN; + __XML_CLOSE_LOG; + } + +void CXmlParser::ConstructL() + { + __XML_OPEN_LOG(__LOG_WAP_FILE_NAME); + __XML_LOG_ENTER(_L("CXmlParser::CXmlParser()")); + __XML_LOG_RETURN; + } + +void CXmlParser::ResetL(CXmlElement* aRootNode) +// Reseting method with which the parser can be prepared for parsing another document + { + __XML_LOG_ENTER(_L("CXmlParser::ResetL()")); + iRootNode = aRootNode; + iCurrentNode = iRootNode; + ResetL(); + __XML_LOG_RETURN; + } + +void CXmlParser::ResetL() +// Inherited reseting method + { + __XML_LOG_ENTER(_L("CXmlParser::ResetL()")); + CBNFParser::ResetL(); + + PreAttribute(*this); + PreExternalID(*this); + iRootTagFound = EFalse; + iDataGathering = EFalse; + iErrorCode = KErrNone; + delete iName; + iName = NULL; + delete iCData; + iCData = NULL; + delete iDTDUrl; + iDTDUrl = NULL; + delete iDocType; + iDocType = NULL; + delete iDocRootName; + iDocRootName = NULL; + delete iXmlVersionString; + iXmlVersionString = NULL; + __XML_LOG_RETURN; + } + +void CXmlParser::ContinueL() +// Continue parsing without adding data + { + __XML_LOG_ENTER(_L("CXmlParser::ContinueL()")); + iErrorCode = KErrNone; + if( !iDataGathering ) + { + ParseL(); + } + __XML_LOG_RETURN; + } + +void CXmlParser::ProcessDataL(HBufC8& aData) +// Parse incoming data. Data is copied. + { + __XML_LOG_ENTER(_L("CXmlParser::()")); + HBufC* newData = HBufC::NewL(aData.Length()); + newData->Des().Copy(aData.Des()); + ProcessDataL(newData); + __XML_LOG_RETURN; + } + +void CXmlParser::ProcessDataL(HBufC* aData) +// Process given data. Parser takes owneship of the data. + { + __XML_LOG_ENTER(_L("CXmlParser::ProcessDataL()")); + EolNormalization(aData->Des()); + + iString.AddStringL(aData); + + if( iRootNode == NULL ) + { + iErrorCode = EWapErrXmlLibMissingDocumentRootNode; + __XML_LOG(_L("ProcessDataL setting error code EWapErrXmlLibMissingDocumentRootNode")); + __XML_LOG_RETURN; + return; + } + if( !iDataGathering ) + { + ParseL(); + } + __XML_LOG_RETURN; + } + +void CXmlParser::CommitL() +// All the data has been passed in. Finish. + { + __XML_LOG_ENTER(_L("CXmlParser::CommitL()")); + if( iDataGathering ) + { + const HBufC* id = iLUT.Des2IDL(KXmlLibBufferedDocumentAttribute); + CDataNoDelete* attributeValue = new(ELeave) CDataNoDelete(iString.ContentL()); + CleanupStack::PushL(attributeValue); + iRootNode->AddAttributeL(id, attributeValue); + CleanupStack::Pop(attributeValue); + iErrorCode = EWapErrXmlLibDocumentBuffered; + __XML_LOG(_L("CommitL setting error code EWapErrXmlLibDocumentBuffered")); + __XML_LOG_RETURN; + return; + } + CBNFParser::CommitL(); + __XML_LOG_RETURN; + } + +// +// CALLBACK FUNCTIONS +// + +// These methods are bound to specific rules and they are called when ever a rule finishes, +// regardless of the success of the matching of the rule. +// Functions, whose name start with "Post" are executed _after_ the rule and "Pre" rules +// are executed prior to the matching attempt of a rule. + + +void CXmlParser::PostCharDataL(CBNFParser& aParser) +// Handle "ordinary" character data. This generates #PCDATA nodes for the body text +// of the document. Nodes consisting only of white spaces are ignored. + { + __XML_EXT_LOG_ENTER(_L("CXmlParser::PostCharDataL()")); + CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser); + + if( parser.RuleMatched() ) + { + HBufC* data = parser.MarkedL(); + + TInt i=0; + TPtr text = data->Des(); + for(; i < data->Length(); i++) + { + TInt ch=text[i]; + if( !(ch == 0x9 || ch == 0xA || ch == 0xD || ch == 0x20) ) + { + break; + } + } + if( i >= data->Length() ) + { + delete data; + parser.DeleteMark(); + __XML_EXT_LOG_RETURN; + return; + } + + parser.CharRefReplacement(text); + + CleanupStack::PushL(data); + const HBufC* id = parser.iLUT.Des2IDL(KPCDataID); + CXmlElement* newNode = CXmlElement::NewL(id, parser.iCurrentNode); + parser.iCurrentNode->AppendChildL(newNode); // Now the node is owned by the parent and would hence get deleted in a leave + newNode->SetDataL(data); + CleanupStack::Pop(); + } + parser.DeleteMark(); + __XML_EXT_LOG_RETURN; + } + +void CXmlParser::PostCDStart(CBNFParser& aParser) +// Initialize matching of CDATA sections + { + __XML_EXT_LOG_ENTER(_L("CXmlParser::PostCDStart()")); + CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser); + + if( parser.RuleMatched() ) + { + delete parser.iCData; + parser.iCData = NULL; + } + __XML_EXT_LOG_RETURN; + } + +void CXmlParser::PostCDataL(CBNFParser& aParser) +// Store the matched text withing CDATA section + { + __XML_EXT_LOG_ENTER(_L("CXmlParser::PostCData()")); + CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser); + + if( parser.RuleMatched() ) + { + parser.iCData = parser.MarkedL(); + } + parser.DeleteMark(); + __XML_EXT_LOG_RETURN; + } + +void CXmlParser::PostCDSectL(CBNFParser& aParser) +// If whole of the CDATA section matches, a CDATA node is generated +// and the data is attached to that node. In other cases the document +// is in error. + { + __XML_EXT_LOG_ENTER(_L("CXmlParser::PostCDSectL()")); + CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser); + + if( parser.RuleMatched() ) + { + const HBufC* id = parser.iLUT.Des2IDL(KCDataID); + CXmlElement* newNode = CXmlElement::NewL(id, parser.iCurrentNode); + parser.iCurrentNode->AppendChildL(newNode); + newNode->SetDataL(parser.iCData); + parser.iCData = NULL; + } + else if( parser.iCData != NULL ) + { + delete parser.iCData; + parser.iCData = NULL; + parser.iErrorCode = EWapErrXmlLibMissingCDATASectionEndTag; + parser.SetState(EStopped); + } + __XML_EXT_LOG_RETURN; + } + + +void CXmlParser::PostNameL(CBNFParser& aParser) +// Store string matching the Name -rule + { + __XML_EXT_LOG_ENTER(_L("CXmlParser::PostName()")); + CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser); + + if( parser.RuleMatched() ) + { + delete parser.iName; // Get rid of the possibly errorneous, leftover name! + parser.iName = parser.MarkedL(); + } + parser.DeleteMark(); + __XML_EXT_LOG_RETURN; + } + +void CXmlParser::PostNodeNameL(CBNFParser& aParser) +// Wrapper function for storing the matched Name string as a name of a Node. + { + __XML_EXT_LOG_ENTER(_L("CXmlParser::PostNodeNameL()")); + CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser); + + if( parser.RuleMatched() ) + { + // Validity constraint: root element name must match the Name declared in DOCTYPE + if( parser.iCurrentNode == parser.iRootNode ) + { + if( parser.iDocRootName == NULL ) + { + parser.iErrorCode = EWapErrXmlLibInvalidDocumentStructure; + parser.SetState(EStopped); + return; + } + if( parser.iDocRootName->Compare(parser.iName->Des()) != 0 ) + { + parser.iErrorCode = EWapErrXmlLibRootElementNameMismatch; + parser.SetState(EStopped); + return; + } + } + const HBufC* type = parser.iLUT.Des2IDL(parser.iName->Des()); + parser.iCurrentNode->SetType(type); + delete parser.iName; + parser.iName = NULL; + } + __XML_EXT_LOG_RETURN; + } + +void CXmlParser::PreAttribute(CBNFParser& aParser) +// Prepare for matching an attribute definition (attrName = "attrValue") + { + __XML_EXT_LOG_ENTER(_L("CXmlParser::PreAttribute()")); + CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser); + + delete parser.iAttrName; + delete parser.iAttValue; + parser.iAttrName = parser.iAttValue = NULL; + __XML_EXT_LOG_RETURN; + } + +void CXmlParser::PostAttrName(CBNFParser& aParser) +// Store the matched Name-string as attribute name + { + __XML_EXT_LOG_ENTER(_L("CXmlParser::PostAttrName()")); + CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser); + + if( parser.RuleMatched() ) + { + parser.iAttrName = parser.iName; + parser.iName = NULL; + } + __XML_EXT_LOG_RETURN; + } + +void CXmlParser::PostPureAttValueL(CBNFParser& aParser) +// Store the matched string as attribute value + { + __XML_EXT_LOG_ENTER(_L("CXmlParser::PostPureAttValue()")); + CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser); + + if( parser.RuleMatched() ) + { + delete parser.iAttValue; + parser.iAttValue = parser.MarkedL(); + } + parser.DeleteMark(); + __XML_EXT_LOG_RETURN; + } + +void CXmlParser::PostAttributeL(CBNFParser& aParser) +// Should all the parts of an attribute definition match, an attribute +// is created for the current node. + { + __XML_EXT_LOG_ENTER(_L("CXmlParser::PostAttributeL()")); + CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser); + + if( parser.RuleMatched() ) + { + if(parser.iAttrName != NULL) + { + // Add the attribute + if(parser.iAttValue != NULL) + { + TPtr attrValText = parser.iAttValue->Des(); + parser.CharRefReplacement(attrValText); + parser.iCurrentNode->SetAttributeL(*parser.iAttrName, *parser.iAttValue, parser.iLUT); + } + else + parser.iCurrentNode->SetAttributeL(*parser.iAttrName, KNullDesC, parser.iLUT); + } + delete parser.iAttValue; + delete parser.iAttrName; + parser.iAttrName = parser.iAttValue = NULL; + } + else if( parser.iAttValue != NULL || parser.iAttrName != NULL ) + { + parser.iErrorCode = EWapErrXmlLibInvalidAttributeDeclaration; + parser.SetStatus(EStopped); + } + __XML_EXT_LOG_RETURN; + } + +void CXmlParser::PostTagStartL(CBNFParser& aParser) +// A new tag start ("<") is matched, generate new node and attach it as child for its parent + { + __XML_EXT_LOG_ENTER(_L("CXmlParser::PostTagStartL()")); + CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser); + + if( parser.RuleMatched() ) + { + if( parser.iRootTagFound ) + { + CXmlElement* newNode = CXmlElement::NewL(NULL, parser.iCurrentNode); + CleanupStack::PushL(newNode); + parser.iCurrentNode->AppendChildL(newNode); + CleanupStack::Pop(); + parser.iCurrentNode = newNode; + } + else + { + parser.iRootTagFound = ETrue; + } + } + __XML_EXT_LOG_RETURN; + } + +void CXmlParser::PostEmptyElemClose(CBNFParser& aParser) +// If we match a closing empty element (i.e. ) then this tag has no children +// and current node pointer is moved up to the parent + { + __XML_EXT_LOG_ENTER(_L("CXmlParser::PostEmptyElemClose()")); + CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser); + + if( parser.RuleMatched() ) + { + parser.iCurrentNode = (CXmlElement *)parser.iCurrentNode->Parent(); + } + __XML_EXT_LOG_RETURN; + } + +void CXmlParser::PostETag(CBNFParser& aParser) +// Post rule for an end tag. We check that the end tag name matches +// the name of the node pointer by iCurrentNode (if everything is fine and +// all the tags are properly opened and closed, the pointer should point +// to the node that opened this tag). + { + __XML_EXT_LOG_ENTER(_L("CXmlParser::PostETag()")); + CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser); + + if( parser.RuleMatched() ) + { + TDesC* type = (TDesC*)parser.iCurrentNode->Type(); + if( type->Compare(*parser.iName) ) + { + parser.iErrorCode = EWapErrXmlLibEndTagMismatch; + parser.SetState(EStopped); + } + else + { + // This is the end tag for iCurrentNode + if( parser.iCurrentNode != parser.iRootNode) + { + parser.iCurrentNode = (CXmlElement*)parser.iCurrentNode->Parent(); + } + // Here we don't need to make a notification of the node being the document closing (e.g. ) + // tag, since our rule tree won't match any subsequent tags and this will result in + // EWapErrXmlLibInvalidDocument on call to CommitL. + } + delete parser.iName; + parser.iName = NULL; + } + __XML_EXT_LOG_RETURN; + } + +void CXmlParser::PreExternalID(CBNFParser& aParser) +// Prepare for matching an external ID + { + __XML_EXT_LOG_ENTER(_L("CXmlParser::PreExternalID()")); + CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser); + + delete parser.iSystemLiteral; + delete parser.iPubidLiteral; + parser.iSystemLiteral = parser.iPubidLiteral = NULL; + __XML_EXT_LOG_RETURN; + } + +void CXmlParser::PostPureSystemLiteralL(CBNFParser& aParser) +// Store the contents of the SystemLiteral + { + __XML_EXT_LOG_ENTER(_L("CXmlParser::PostPureSystemLiteral()")); + CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser); + + if( parser.RuleMatched() ) + { + parser.iSystemLiteral = parser.MarkedL(); + } + parser.DeleteMark(); + __XML_EXT_LOG_RETURN; + } + +void CXmlParser::PostPubidLiteralL(CBNFParser& aParser) +// Post rule for PubidLiteral + { + __XML_EXT_LOG_ENTER(_L("CXmlParser::PostPubidLiteral()")); + CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser); + + if( parser.RuleMatched() ) + { + HBufC* data = parser.MarkedL(); + // Since this entire rule matched, there must be quotation marks in the beginning + // and at the end of the string. Those are now removed. + TPtr pureLiteral = data->Des(); + pureLiteral.Delete(pureLiteral.Length()-1,1); + pureLiteral.Delete(0,1); + parser.iPubidLiteral = data; + } + parser.DeleteMark(); + __XML_EXT_LOG_RETURN; + } + +void CXmlParser::PostDTDidAndUrl(CBNFParser& aParser) +// If this combination is successfully matched, we have a complete definition +// for a DTD. This is signaled to the client who then can provide us with the +// DTD tree is available. + { + __XML_EXT_LOG_ENTER(_L("CXmlParser::PostDTDidAndUrl()")); + CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser); + + if( parser.RuleMatched() ) + { + // NOTICE that PostDTDidAndUrl is a wrapper rule for an ExternalID and it is possible + // for an ExternalID to define just a URL, without the doctype. Here we assign + // the PubidLiteral to iDocType, which would in such case be NULL. Therefore the client + // using these values must check whether the doctype is NULL. + parser.iDocType = parser.iPubidLiteral; + parser.iDTDUrl = parser.iSystemLiteral; + parser.iPubidLiteral = parser.iSystemLiteral = NULL; + parser.iErrorCode = EDTDDefinitionFound; + parser.SetState(EPaused); + } + __XML_EXT_LOG_RETURN; + } + +void CXmlParser::PostCharReferenceValue(CBNFParser& aParser) +// If character reference value rule didn't match, the document is in error +// since, the beginning of a character reference (&#) did match + { + __XML_EXT_LOG_ENTER(_L("CXmlParser::PostCharReferenceValue()")); + CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser); + + if( !parser.RuleMatched() ) + { + parser.iErrorCode = EWapErrXmlLibInvalidCharacterReference; + parser.SetStatus(EStopped); + } + __XML_EXT_LOG_RETURN; + } + +_LIT(KLitLt,"lt"); +_LIT(KLitGt,"gt"); +_LIT(KLitAmp,"amp"); +_LIT(KLitApos,"apos"); +_LIT(KLitQuot,"quot"); + +void CXmlParser::PostEntityRefL(CBNFParser& aParser) +// After matching the an entity reference we substitute it +// with the corresponding replacement text to the parsing text. +// If the entity isn't one of the XML obligatory values, +// the replacement text is retrieved from the DTD tree. +// The parsing continues from the point where the replacement +// text was inserted, not after it! + { + __XML_EXT_LOG_ENTER(_L("CXmlParser::PostEntityRefL()")); + CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser); + + if( parser.RuleMatched() ) + { + // The predefined entities (see XML specification, chapter 4.6) + const TText* stringPtr=parser.iName->Ptr(); + TInt length=parser.iName->Length(); + const TDesC* str=NULL; + if(Compare(length,stringPtr,KLitLt)) + str=&KPredefEntityLT; + else if(Compare(length,stringPtr,KLitGt)) + str=&KPredefEntityGT; + else if(Compare(length,stringPtr,KLitAmp)) + str=&KPredefEntityAMP; + else if(Compare(length,stringPtr,KLitApos)) + str=&KPredefEntityAPOS; + else if(Compare(length,stringPtr,KLitQuot)) + str=&KPredefEntityQUOT; + HBufC* replacementText = NULL; + if( str ) + replacementText = str->AllocL(); + if( replacementText == NULL ) + { + const HBufC* id = parser.iLUT.Des2IDL(parser.iName->Des()); + CBNFNode* entityNode = REINTERPRET_CAST(CBNFNode*, parser.iDTD->Attribute(id) ); + if( entityNode != NULL ) + { + // On entity nodes the only child should be an AND node with an EExact child that + // that holds the replacement text data. + CTypedNode* child=entityNode->Child(0); + if( child != NULL && child->Type() == EExact ) + { + replacementText = child->Data()->AllocL(); + } + } + } + + delete parser.iName; + parser.iName = NULL; + + if( replacementText == NULL ) + { + parser.iErrorCode = EWapErrXmlLibUnknownEntityReference; + parser.SetState(EStopped); + } + + parser.iString.ReplaceMarkedL(replacementText); + } + parser.DeleteMark(); + __XML_EXT_LOG_RETURN; + } + + +void CXmlParser::PostVersionNumL(CBNFParser& aParser) +// Store XML version string + { + __XML_EXT_LOG_ENTER(_L("CXmlParser::PostVersionNum()")); + CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser); + + if( parser.RuleMatched() ) + { + parser.iXmlVersionString = parser.MarkedL(); + } + parser.DeleteMark(); + __XML_EXT_LOG_RETURN; + } + +void CXmlParser::PostDoctypedecl(CBNFParser& aParser) +// Check after a doctype declaration that there must have been +// a DTD definition. + { + __XML_EXT_LOG_ENTER(_L("CXmlParser::PostDoctypedecl()")); + CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser); + + if( parser.RuleMatched() ) + { + if( parser.iDTDUrl == NULL ) + { + parser.iErrorCode = ENoDTDDefined; + parser.SetState(EPaused); + } + } + __XML_EXT_LOG_RETURN; + } + +void CXmlParser::PostDocRootName(CBNFParser& aParser) +// Store the document name definition in the doctypedecl +// for later check, that the first tag has the same name + { + __XML_EXT_LOG_ENTER(_L("CXmlParser::PostDocRootName()")); + CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser); + + if( parser.RuleMatched() ) + { + parser.iDocRootName = parser.iName; + parser.iName = NULL; + } + __XML_EXT_LOG_RETURN; + } + +void CXmlParser::PostProlog(CBNFParser& aParser) +// After the prolog part we can determine if we had wrong version +// of Xml defined, if we didn't get a DTD and stuff. + { + __XML_EXT_LOG_ENTER(_L("CXmlParser::PostProlog()")); + CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser); + + if( parser.iDTD == NULL ) + { + // No DTD, no show. We can not proceed, unless we have a DTD! + parser.iErrorCode = EWapErrXmlLibNoDTD; + parser.SetState(EStopped); + } + + if( parser.iXmlVersionString == NULL || + parser.iXmlVersionString->Compare( KSupportedXmlVersion ) != 0 ) + { + __XML_EXT_LOG1(_L("Looking for supported XML - \"%S\""), &KSupportedXmlVersion); + + if (parser.iXmlVersionString==NULL) + { + __XML_EXT_LOG1(_L("But version string is NULL"), NULL); + } + else + { + TBuf<256> buf; + buf.Copy(*parser.iXmlVersionString); + __XML_EXT_LOG1(_L("Found XMLVersionString \"%S\""), &buf); + } + parser.iErrorCode = EWapErrXmlLibInvalidXmlVersionDefinition; + parser.SetState(EStopped); + } + + delete parser.iXmlVersionString; + parser.iXmlVersionString = NULL; + + // The mark set in the beginning of the document was to make sure that no data is deleted + // until we know for sure that we have a DTD and need not to buffer the data. + // We can now waste the already parsed data and that is allowed by removing the first + // mark. This point can not be reached if data gathering was active. + parser.DeleteMark(); + __XML_EXT_LOG_RETURN; + } + + +// A macro to define literal strings that are used to name and reference the rule +// USAGE: _STRING(hello) +// this would result in definition of a literal called Khello that has value "hello" +// i.e. this equals to _LIT(Khello, "hello"); +#define _STRING(X) _LIT(K ## X, #X); + +CBNFNode* CXmlParser::TreeL() +// Builds the rule tree to parse XML + { + __XML_LOG_ENTER(_L("CXmlParser::TreeL()")); + + // save calling the exported function in CBNFNode dozens of times + + const TDesC* rangeStart=CBNFNode::KRangeStart(); + const TDesC* rangeEnd=CBNFNode::KRangeEnd(); + + CBNFNode* root = NewBNFL(); + CleanupStack::PushL(root); + + _STRING(document); + NewComponentL(root, *root, Kdocument); + +// +// Common "help rules" +// + _STRING(S); + // Optional whitespace sequence: S? + _STRING(optS); + CBNFNode& optS = NewRuleL(root, KoptS, EOptional, NULL, NULL, NULL); + NewComponentL(root, optS, KS); + + // Single quote: ' + _STRING(singleQuote); + NewRuleL(root, KsingleQuote, EExact, _L("'"), NULL, NULL); + + // Double quote + _STRING(doubleQuote); + NewRuleL(root, KdoubleQuote, EExact, _L("\""), NULL, NULL); + + _STRING(Char); + + // Number ::= [0-9] + _STRING(Number); + CBNFNode& Number = NewRuleL(root, KNumber, ERange, NULL, NULL, NULL); + AddComponentAttributeL(Number, rangeStart, '0'); + AddComponentAttributeL(Number, rangeEnd, '9'); + + // HexNumber ::= [0-9a-fA-f] + _STRING(HexNumber); + CBNFNode& HexNumber = NewRuleL(root, KHexNumber, EOr, NULL, NULL, NULL); + NewComponentL(root, HexNumber, KNumber); + CBNFNode& HexNumber2 = NewComponentL(HexNumber, ERange); + AddComponentAttributeL(HexNumber2, rangeStart, 'a'); + AddComponentAttributeL(HexNumber2, rangeEnd, 'f'); + CBNFNode& HexNumber3 = NewComponentL(HexNumber, ERange); + AddComponentAttributeL(HexNumber3, rangeStart, 'A'); + AddComponentAttributeL(HexNumber3, rangeEnd, 'F'); + + // HexValue ::= HexNumber+ + _STRING(HexValue); + CBNFNode& HexValue = NewRuleL(root, KHexValue, ENMore, NULL, NULL, NULL); + AddComponentAttributeL(HexValue, CBNFNode::KNMoreMinimum(), 1); + NewComponentL(root, HexValue, KHexNumber); + + // DecNumber ::= Digit+ + _STRING(DecValue); + CBNFNode& DecValue = NewRuleL(root, KDecValue, ENMore, NULL, NULL, NULL); + AddComponentAttributeL(DecValue, CBNFNode::KNMoreMinimum(), 1); + NewComponentL(root, DecValue, KNumber); + + // Latin char: [a-zA-Z] + _STRING(LatinChar); + CBNFNode& LatinChar = NewRuleL(root, KLatinChar, EOr, NULL, NULL, NULL); + CBNFNode& LatinChar1 = NewComponentL(LatinChar, ERange); + AddComponentAttributeL(LatinChar1, rangeStart, 'A'); + AddComponentAttributeL(LatinChar1, rangeEnd, 'Z'); + CBNFNode& LatinChar2 = NewComponentL(LatinChar, ERange); + AddComponentAttributeL(LatinChar2, rangeStart, 'a'); + AddComponentAttributeL(LatinChar2, rangeEnd, 'z'); + +// +// XML rules +// + _STRING(prolog); + _STRING(element); + _STRING(Misc); + // XML specs rule [1] + // [1] document ::= prolog element Misc* + CBNFNode& document = NewRuleL(root, Kdocument, EAnd, NULL, NULL, NULL); + NewComponentL( root, document, Kprolog ); + NewComponentL( root, document, Kelement ); + CBNFNode& document3 = NewComponentL( document, ENMore ); + NewComponentL( root, document3, KMisc); + + // XML specs rule [2] + // [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] + // + // Notes: + // - Changed order of range 20-d7fff and selection of 9, 0xA and 0xD, since it is + // we probably can make match faster with the first range + // - Removed the last range since we only support 16-bit chars + // - Implemented this as its own ruletype + NewXmlRuleL(root, KChar, EChar); + + // XML specs rule [3] + // [3] S ::= (#x20 | #x9 | #xD | #xA)+ + // - Implemented this as its own ruletype + NewXmlRuleL(root, KS, ES); + + _STRING(Letter); + _STRING(FirstNameChar); + NewXmlRuleL(root, KFirstNameChar, EFirstNameChar); + _STRING(NMoreNameChar); + NewXmlRuleL(root, KNMoreNameChar, ENMoreNameChar); + // XML specs rule [5] + // [5] Name ::= (Letter | '_' | ':') (NameChar)* + _STRING(Name); + CBNFNode& Name = NewRuleL(root, KName, EAnd, NULL, MarkCallback, PostNameL); + NewComponentL(root, Name, KFirstNameChar); + NewComponentL(root, Name, KNMoreNameChar); + + _STRING(Reference); + // Help rule + // Attribute value without the quote marks + // PureAttValue ::= ([^<&"] | Reference)* + _STRING(PureAttValueDQ); + CBNFNode& PureAttValueDQ = NewRuleL(root, KPureAttValueDQ, ENMore, NULL, MarkCallback, PostPureAttValueL); + CBNFNode& PureAttValueDQ1 = NewComponentL(PureAttValueDQ, EOr); + NewComponentL(PureAttValueDQ1, ESelect, _L("^<&\"") ); + NewComponentL(root, PureAttValueDQ1, KReference); + + _STRING(PureAttValueSQ); + CBNFNode& PureAttValueSQ = NewRuleL(root, KPureAttValueSQ, ENMore, NULL, MarkCallback, PostPureAttValueL); + CBNFNode& PureAttValueSQ1 = NewComponentL(PureAttValueSQ, EOr); + NewComponentL(PureAttValueSQ1, ESelect, _L("^<&'") ); + NewComponentL(root, PureAttValueSQ1, KReference); + + // XML specs rule [10] + // [10] AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'" + _STRING(AttValue); + CBNFNode& AttValue = NewRuleL(root, KAttValue, EOr, NULL, NULL, NULL ); + CBNFNode& AttValue1 = NewComponentL(AttValue, EAnd); + NewComponentL(root, AttValue1, KdoubleQuote); + NewComponentL(root, AttValue1, KPureAttValueDQ); + NewComponentL(root, AttValue1, KdoubleQuote); + CBNFNode& AttValue2 = NewComponentL(AttValue, EAnd); + NewComponentL(root, AttValue2, KsingleQuote); + NewComponentL(root, AttValue2, KPureAttValueSQ); + NewComponentL(root, AttValue2, KsingleQuote); + + // Help rule + // System literal without the quotation marks + // PureSystemLiteral ::= [^"]* + _STRING(PureSystemLiteralDoubleQuote); + CBNFNode& PureSystemLiteralDQ = NewRuleL(root, KPureSystemLiteralDoubleQuote, ENMore, NULL, MarkCallback, PostPureSystemLiteralL); + NewComponentL(PureSystemLiteralDQ, ESelect, _L("^\"") ); + + _STRING(PureSystemLiteralSingleQuote); + CBNFNode& PureSystemLiteralSQ = NewRuleL(root, KPureSystemLiteralSingleQuote, ENMore, NULL, MarkCallback, PostPureSystemLiteralL); + NewComponentL(PureSystemLiteralSQ, ESelect, _L("^'") ); + + // XML specs rule [11] + // [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'") + _STRING(SystemLiteral); + CBNFNode& SystemLiteral = NewRuleL(root, KSystemLiteral, EOr, NULL, NULL, NULL); + CBNFNode& SystemLiteral1 = NewComponentL(SystemLiteral, EAnd); + NewComponentL(root, SystemLiteral1, KdoubleQuote); + NewComponentL(root, SystemLiteral1, KPureSystemLiteralDoubleQuote); + NewComponentL(root, SystemLiteral1, KdoubleQuote); + CBNFNode& SystemLiteral2 = NewComponentL(SystemLiteral, EAnd); + NewComponentL(root, SystemLiteral2, KsingleQuote); + NewComponentL(root, SystemLiteral2, KPureSystemLiteralSingleQuote); + NewComponentL(root, SystemLiteral2, KsingleQuote); + + _STRING(PubidChar); + // XML specs rule [12] + // [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'" + _STRING(PubidLiteral); + CBNFNode& PubidLiteral = NewRuleL(root, KPubidLiteral, EOr, NULL, MarkCallback, PostPubidLiteralL); + CBNFNode& PubidLiteral1 = NewComponentL(PubidLiteral, EAnd); + NewComponentL(root, PubidLiteral1, KdoubleQuote); + CBNFNode& PubidLiteral12 = NewComponentL(PubidLiteral1, ENMore); + NewComponentL(root, PubidLiteral12, KPubidChar); + NewComponentL(root, PubidLiteral1, KdoubleQuote); + CBNFNode& PubidLiteral2 = NewComponentL(PubidLiteral, EAnd); + NewComponentL(root, PubidLiteral2, KsingleQuote); + CBNFNode& PubidLiteral22 = NewComponentL(PubidLiteral2, ENMore); + CBNFNode& PubidLiteral221 = NewComponentL(PubidLiteral22, EWithout); + NewComponentL(root, PubidLiteral221, KPubidChar); + NewComponentL(PubidLiteral221, EExact, _L("'") ); + NewComponentL(root, PubidLiteral2, KsingleQuote); + + // XML specs rule [13] + // [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] + CBNFNode& PubidChar = NewRuleL(root, KPubidChar, EOr, NULL, NULL, NULL); + NewComponentL(PubidChar, ESelect, _L(" \r\n") ); + NewComponentL(root, PubidChar, KLatinChar); + NewComponentL(root, PubidChar, KNumber); + NewComponentL(PubidChar, ESelect, _L("-'()+,./:=?;!*#@$_%") ); + + _STRING(CharRef); + // XML specs rule [14] + // [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*) + // valid CharData shall has length more than zero. + // Also character references are included to the char data and replaced later. + // CharData ::= (([^<&]+ - ([^<&]* ']]>' [^<&]*)) | CharRef)+ + // + // Optimized: + // CharData ::= ( [^<&]+ | CharRef )+ + _STRING(CharData); + CBNFNode& CharData = NewRuleL(root, KCharData, ENMore, NULL, MarkCallback, PostCharDataL); + AddComponentAttributeL(CharData, CBNFNode::KNMoreMinimum(), 1); + CBNFNode& CharData1 = NewComponentL(CharData, EOr); + CBNFNode& CharData11 = NewComponentL(CharData1, ENMore); + AddComponentAttributeL(CharData11, CBNFNode::KNMoreMinimum(), 1); + NewComponentL(CharData11, ESelect, _L("^<&") ); + NewComponentL(root, CharData1, KCharRef); + + // XML specs rule [15] + // [15] Comment ::= "" + _STRING(Comment); + CBNFNode& Comment = NewRuleL(root, KComment, EAnd, NULL, NULL, NULL); + NewComponentL(Comment, EExact, _L("")); + + _STRING(PITarget); + // XML specs rule [16] + // [16] PI ::= '' Char*)))? '?>' + // PIs are wasted, reformulated the rule: + // PI ::= '')* '?>' + _STRING(PI); + CBNFNode& PI = NewRuleL(root, KPI, EAnd, NULL, NULL, NULL); + NewComponentL(PI, EExact, _L("") ); + NewComponentL(PI, EExact, _L("?>") ); + + // XML specs rule [17] + // [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l')) + CBNFNode& PITarget = NewRuleL(root, KPITarget, EWithout, NULL, NULL, NULL); + NewComponentL(root, PITarget, KName); + CBNFNode& PITarget2 = NewComponentL(PITarget, EAnd); + NewComponentL(PITarget2, ESelect, _L("Xx") ); + NewComponentL(PITarget2, ESelect, _L("Mm") ); + NewComponentL(PITarget2, ESelect, _L("Ll") ); + + _STRING(CDStart); + _STRING(CData); + _STRING(CDEnd); + // XML specs rule [18] + // [18] CDSect ::= CDStart CData CDEnd + _STRING(CDSect); + CBNFNode& CDSect = NewRuleL(root, KCDSect, EAnd, NULL, NULL, PostCDSectL); + NewComponentL(root, CDSect, KCDStart); + NewComponentL(root, CDSect, KCData); + NewComponentL(root, CDSect, KCDEnd); + + // XML specs rule [19] + // [19] CDStart ::= '' Char*)) + // Modified: + // CData ::= (Char - ']]>')* + CBNFNode& CData = NewRuleL(root, KCData, ENMore, NULL, MarkCallback, PostCDataL); + CBNFNode& CData1 = NewComponentL(CData, EWithout); + NewComponentL(root, CData1, KChar); + NewComponentL(CData1, EExact, _L("]]>") ); + + // XML specs rule [21] + // [21] CDEnd ::= ']]>' + NewRuleL(root, KCDEnd, EExact, _L("]]>"), NULL, NULL); + + _STRING(XMLDecl); + _STRING(doctypedecl); + // XML specs rule [22] + // [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)? + CBNFNode& prolog = NewRuleL(root, Kprolog, EAnd, NULL, MarkCallback, PostProlog); + CBNFNode& prolog1 = NewComponentL(prolog, EOptional); + NewComponentL(root, prolog1, KXMLDecl); + CBNFNode& prolog2 = NewComponentL(prolog, ENMore); + NewComponentL(root, prolog2, KMisc); + CBNFNode& prolog3 = NewComponentL(prolog, EOptional); + CBNFNode& prolog31 = NewComponentL(prolog3, EAnd); + NewComponentL(root, prolog31, Kdoctypedecl); + CBNFNode& prolog312 = NewComponentL(prolog31, ENMore); + NewComponentL(root, prolog312, KMisc); + + _STRING(VersionInfo); + _STRING(EncodingDecl); + _STRING(SDDecl); + // XML specs rule [23] + // [23] XMLDecl ::= '' + CBNFNode& XMLDecl = NewRuleL(root, KXMLDecl, EAnd, NULL, NULL, NULL); + NewComponentL(root, XMLDecl, KoptS); + NewComponentL(XMLDecl, EExact, _L("") ); + + _STRING(Eq); + _STRING(VersionNum); + // XML specs rule [24] + // [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ") + CBNFNode& VersionInfo = NewRuleL(root, KVersionInfo, EAnd, NULL, NULL, NULL); + NewComponentL(root, VersionInfo, KS); + NewComponentL(VersionInfo, EExact, _L("version") ); + NewComponentL(root, VersionInfo, KEq); + CBNFNode& VersionInfo4 = NewComponentL(VersionInfo, EOr); + CBNFNode& VersionInfo41 = NewComponentL(VersionInfo4, EAnd); + NewComponentL(root, VersionInfo41, KsingleQuote); + NewComponentL(root, VersionInfo41, KVersionNum); + NewComponentL(root, VersionInfo41, KsingleQuote); + CBNFNode& VersionInfo42 = NewComponentL(VersionInfo4, EAnd); + NewComponentL(root, VersionInfo42, KdoubleQuote); + NewComponentL(root, VersionInfo42, KVersionNum); + NewComponentL(root, VersionInfo42, KdoubleQuote); + + // XML specs rule [25] + // [25] Eq ::= S? '=' S? + CBNFNode& Eq = NewRuleL(root, KEq, EAnd, NULL, NULL, NULL); + NewComponentL(root, Eq, KoptS); + NewComponentL(Eq, EExact, _L("=") ); + NewComponentL(root, Eq, KoptS); + + // XML specs rule [26] + // [26] VersionNum ::= ([a-zA-Z0-9_.:] | '-')+ + CBNFNode& VersionNum = NewRuleL(root, KVersionNum, ENMore, NULL, MarkCallback, PostVersionNumL); + AddComponentAttributeL(VersionNum, CBNFNode::KNMoreMinimum(), 1); + CBNFNode& VersionNum1 = NewComponentL(VersionNum, EOr); + CBNFNode& VersionNum11 = NewComponentL(VersionNum1, ERange); + AddComponentAttributeL(VersionNum11, rangeStart, 'a'); + AddComponentAttributeL(VersionNum11, rangeEnd, 'z'); + CBNFNode& VersionNum12 = NewComponentL(VersionNum1, ERange); + AddComponentAttributeL(VersionNum12, rangeStart, 'A'); + AddComponentAttributeL(VersionNum12, rangeEnd, 'Z'); + CBNFNode& VersionNum13 = NewComponentL(VersionNum1, ERange); + AddComponentAttributeL(VersionNum13, rangeStart, '0'); + AddComponentAttributeL(VersionNum13, rangeEnd, '9'); + NewComponentL(VersionNum1, ESelect, _L("-_.:") ); + + // XML specs rule [27] + // [27] Misc ::= Comment | PI | S + // + // Notes: + // - Put S (whitespace) first, since it is the most probable match here + CBNFNode& Misc = NewRuleL(root, KMisc, EOr, NULL, NULL, NULL); + NewComponentL(root, Misc, KS); + NewComponentL(root, Misc, KComment); + NewComponentL(root, Misc, KPI); + + // Help rule + // a rule, that can succesfully ignore a valid inline dtd + // inlineDTD ::= ( S | Comment | ( ')* > ) | PI )* + _STRING(inlineDTD); + CBNFNode& inlineDTD = NewRuleL(root, KinlineDTD, EOr, NULL, NULL, NULL); + CBNFNode& inlineDTD0 = NewComponentL(inlineDTD, ENMore); + CBNFNode& inlineDTD1 = NewComponentL(inlineDTD0, EOr); + NewComponentL(root, inlineDTD1, KS); + NewComponentL(root, inlineDTD1, KComment); + CBNFNode& inlineDTD12 = NewComponentL(inlineDTD1, EAnd); + NewComponentL(inlineDTD12, EExact, _L("") ); + NewComponentL(inlineDTD12, EExact, _L(">") ); + NewComponentL(root, inlineDTD1, KPI); + + _STRING(ExternalID); + // Help rule + // DTD doctype and url + _STRING(DTDidAndUrl); + CBNFNode& DTDidAndUrl = NewRuleL(root, KDTDidAndUrl, EAnd, NULL, NULL, PostDTDidAndUrl); + NewComponentL(root, DTDidAndUrl, KExternalID); + + // Help rule + // KDocRootName = Name + _STRING(DocRootName); + CBNFNode& docRootName = NewRuleL(root, KDocRootName, EAnd, NULL, NULL, PostDocRootName); + NewComponentL(root, docRootName, KName); + + // XML specs rule [28] + // [28] doctypedecl ::= '' + // NOTE: part contained inside braces is not handled here, but is interpreted as + // inline DTD and shall be handled by the DTDDH. The actual form of this rule here is: + // [28] doctypedecl ::= '' + CBNFNode& doctypedecl = NewRuleL(root, Kdoctypedecl, EAnd, NULL, NULL, PostDoctypedecl); + NewComponentL(doctypedecl, EExact, _L("") ); + + // Help rule + // yes | no + _STRING(YesOrNo); + CBNFNode& YesOrNo = NewRuleL(root, KYesOrNo, EOr, NULL, NULL, NULL); + NewComponentL(YesOrNo, EExact, _L("yes") ); + NewComponentL(YesOrNo, EExact, _L("no") ); + + // XML specs rule [32] + // [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"')) + CBNFNode& SDDecl = NewRuleL(root, KSDDecl, EAnd, NULL, NULL, NULL); + NewComponentL(root, SDDecl, KS); + NewComponentL(SDDecl, EExact, _L("standalone") ); + NewComponentL(root, SDDecl, KEq); + CBNFNode& SDDecl4 = NewComponentL(SDDecl, EOr); + CBNFNode& SDDecl41 = NewComponentL(SDDecl4, EAnd); + NewComponentL(root, SDDecl41, KsingleQuote); + NewComponentL(root, SDDecl41, KYesOrNo); + NewComponentL(root, SDDecl41, KsingleQuote); + CBNFNode& SDDecl42 = NewComponentL(SDDecl4, EAnd); + NewComponentL(root, SDDecl42, KdoubleQuote); + NewComponentL(root, SDDecl42, KYesOrNo); + NewComponentL(root, SDDecl42, KdoubleQuote); + + + // Help rule + // EmptyElemTag closing "/>" + // EmptyElemClose ::= "/>" + _STRING(EmptyElemClose); + NewRuleL(root, KEmptyElemClose, EExact, _L("/>"), NULL, PostEmptyElemClose); + + _STRING(Tag); + _STRING(content); + _STRING(ETag); + // XML specs rule [39] + // [39] element ::= EmptyElemTag | STag content ETag + // For the sake of efficency and to make it possible to consume the matching + // tokens immediately, we have rearranged this rule as follows: + // element ::= Tag ( "/>" | '>' content ETag) + CBNFNode& element = NewRuleL(root, Kelement, EAnd, NULL, NULL, NULL); + NewComponentL(root, element, KTag); + CBNFNode& element2 = NewComponentL(element, EOr); + NewComponentL(root, element2, KEmptyElemClose); + CBNFNode& element22 = NewComponentL(element2, EAnd); + NewComponentL(element22, EExact, _L(">") ); + NewComponentL(root, element22, Kcontent); + NewComponentL(root, element22, KETag); + + // Help rule + // NodeName ::= Name + // This is basically a wrapper for Name to be able to attach it to the current node + _STRING(NodeName); + CBNFNode& NodeName = NewRuleL(root, KNodeName, EOr, NULL, NULL, PostNodeNameL); + NewComponentL(root, NodeName, KName); + + // Help rule + // TagStart ::= '<' + _STRING(TagStart); + NewRuleL(root, KTagStart, EExact, _L("<"), NULL, PostTagStartL); + + _STRING(Attribute); + // XML specs rule [40] + // [40] STag ::= '<' Name (S Attribute)* S? '>' + // The ending '>' is left out to make this a common Tag for both the STag and + // EmptyElemTag. + // Tag ::= '<' NodeName (S Attribute)* S? + CBNFNode& Tag = NewRuleL(root, KTag, EAnd, NULL, NULL, NULL); + NewComponentL(root, Tag, KTagStart); + NewComponentL(root, Tag, KNodeName); + CBNFNode& Tag3 = NewComponentL(Tag, ENMore); + CBNFNode& Tag31 = NewComponentL(Tag3, EAnd); + NewComponentL(root, Tag31, KS); + NewComponentL(root, Tag31, KAttribute); + NewComponentL(root, Tag, KoptS); + + // Help rule + // AttrName := Name + _STRING(AttrName); + CBNFNode& AttrName = NewRuleL(root, KAttrName, EOr, NULL, NULL, PostAttrName); + NewComponentL(root, AttrName, KName); + + // XML specs rule [41] + // [41] Attribute ::= Name Eq AttValue + CBNFNode& Attribute = NewRuleL(root, KAttribute, EAnd, NULL, PreAttribute, PostAttributeL); + NewComponentL(root, Attribute, KAttrName); + NewComponentL(root, Attribute, KEq); + NewComponentL(root, Attribute, KAttValue); + + // XML specs rule [42] + // [42] ETag ::= '' + CBNFNode& ETag = NewRuleL(root, KETag, EAnd, NULL, NULL, PostETag); + NewComponentL(ETag, EExact, _L("") ); + + _STRING(EntityRef); + // XML specs rule [43] + // [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)* + // To make it work properly, the rule is rearranged. Now we can immediately consume + // matching patterns. + // content ::= (EntityRef | CDSect | PI | Comment | (element - " offset+1 && + aString[offset+1] == 0xA ) + { + aString.Delete(offset,1); + } + else + { + aString[offset] = 0xA; + } + } + __XML_LOG_RETURN; + } + +CBNFNode& CXmlParser::NewXmlRuleL(CBNFNode* aRootRule, const TDesC& aRuleName, TXmlParserNodeTypes aRuleType) + { + CBNFNode& newRule = NewRuleL(aRootRule, aRuleName, EAnd, NULL, NULL, NULL); + newRule.SetType(aRuleType); + return newRule; + } + +CBNFNode& CXmlParser::NewXmlRuleL(CBNFNode* aRootRule, const TDesC& aRuleName, TXmlParserNodeTypes aRuleType, HBufC* aData, TRuleCallback* aPreRule, TRuleCallback* aPostRule) + { + CBNFNode& newRule = NewRuleL(aRootRule, aRuleName, EAnd, aData, aPreRule, aPostRule); + newRule.SetType(aRuleType); + return newRule; + }