applayerprotocols/wappushsupport/XmlLib/XmlPars.cpp
changeset 0 b16258d2340f
equal deleted inserted replaced
-1:000000000000 0:b16258d2340f
       
     1 // Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 // Local includes
       
    17 //
       
    18 #include "XmlPars.h"
       
    19 
       
    20 // System includes
       
    21 //
       
    22 #include <attrlut.h>
       
    23 #include <cbnfnode.h>
       
    24 #include <xmlelemt.h>
       
    25 #include <cnode.h>
       
    26 #include <xmllib.h>	// For the error codes
       
    27 
       
    28 LOCAL_C TBool Compare(TInt aLength,const TText* aStringA,const TDesC& aStringB)
       
    29 	{
       
    30 	if(aLength==aStringB.Length())
       
    31 		{
       
    32 		const TText* stringB=aStringB.Ptr();
       
    33 		while(aLength>=(TInt)(sizeof(TInt32)/sizeof(TText)))
       
    34 			{
       
    35 			if(*(TInt32*)stringB!=*(TInt32*)aStringA)
       
    36 				return EFalse;
       
    37 			stringB+=(sizeof(TInt32)/sizeof(TText));
       
    38 			aStringA+=(sizeof(TInt32)/sizeof(TText));
       
    39 			aLength-=(sizeof(TInt32)/sizeof(TText));
       
    40 			}
       
    41 		while(aLength>0)
       
    42 			{
       
    43 			if(*stringB++!=*aStringA++)
       
    44 				return EFalse;
       
    45 			aLength--;
       
    46 			}
       
    47 		return ETrue;
       
    48 		}
       
    49 	return EFalse;
       
    50 	}
       
    51 
       
    52 CXmlParser::CXmlParser(CAttributeLookupTable& aAttributeLUT) 
       
    53 : CBNFParser(aAttributeLUT), iErrorCode(KErrNone), iDataGathering(EFalse)
       
    54 	{
       
    55 	}
       
    56 
       
    57 CXmlParser* CXmlParser::NewL(CAttributeLookupTable& aAttributeLUT)
       
    58 	{
       
    59 	CXmlParser* self = new(ELeave) CXmlParser(aAttributeLUT);
       
    60 	CleanupStack::PushL(self);
       
    61 	self->ConstructL();
       
    62 	CleanupStack::Pop(self);
       
    63 	return(self);
       
    64 	}
       
    65 
       
    66 CXmlParser::~CXmlParser()
       
    67 	{
       
    68 	__XML_LOG_ENTER(_L("CXmlParser::~CXmlParser()"));
       
    69 	PreAttribute(*this);	// Clears up attribute variables
       
    70 	PreExternalID(*this);
       
    71 	delete iName;
       
    72 	delete iCData;
       
    73 	delete iDTDUrl;
       
    74 	delete iDocType;
       
    75 	delete iXmlVersionString;
       
    76 	delete iDocRootName;
       
    77 	__XML_LOG_RETURN;
       
    78 	__XML_CLOSE_LOG;
       
    79 	}
       
    80 
       
    81 void CXmlParser::ConstructL()
       
    82 	{
       
    83 	__XML_OPEN_LOG(__LOG_WAP_FILE_NAME);
       
    84 	__XML_LOG_ENTER(_L("CXmlParser::CXmlParser()"));
       
    85 	__XML_LOG_RETURN;
       
    86 	}
       
    87 
       
    88 void CXmlParser::ResetL(CXmlElement* aRootNode)
       
    89 // Reseting method with which the parser can be prepared for parsing another document
       
    90 	{
       
    91 	__XML_LOG_ENTER(_L("CXmlParser::ResetL()"));
       
    92 	iRootNode = aRootNode;
       
    93 	iCurrentNode = iRootNode;
       
    94 	ResetL();
       
    95 	__XML_LOG_RETURN;
       
    96 	}
       
    97 
       
    98 void CXmlParser::ResetL()
       
    99 // Inherited reseting method
       
   100 	{
       
   101 	__XML_LOG_ENTER(_L("CXmlParser::ResetL()"));
       
   102 	CBNFParser::ResetL();
       
   103 
       
   104 	PreAttribute(*this);
       
   105 	PreExternalID(*this);
       
   106 	iRootTagFound = EFalse;
       
   107 	iDataGathering = EFalse;
       
   108 	iErrorCode = KErrNone;
       
   109 	delete iName;
       
   110 	iName = NULL;
       
   111 	delete iCData;
       
   112 	iCData = NULL;
       
   113 	delete iDTDUrl;
       
   114 	iDTDUrl = NULL;
       
   115 	delete iDocType;
       
   116 	iDocType = NULL;
       
   117 	delete iDocRootName;
       
   118 	iDocRootName = NULL;
       
   119 	delete iXmlVersionString;
       
   120 	iXmlVersionString = NULL;
       
   121 	__XML_LOG_RETURN;
       
   122 	}
       
   123 
       
   124 void CXmlParser::ContinueL()
       
   125 // Continue parsing without adding data
       
   126 	{
       
   127 	__XML_LOG_ENTER(_L("CXmlParser::ContinueL()"));
       
   128 	iErrorCode = KErrNone;
       
   129 	if( !iDataGathering )
       
   130 		{
       
   131 		ParseL();
       
   132 		}
       
   133 	__XML_LOG_RETURN;
       
   134 	}
       
   135 
       
   136 void CXmlParser::ProcessDataL(HBufC8& aData)
       
   137 // Parse incoming data. Data is copied.
       
   138 	{
       
   139 	__XML_LOG_ENTER(_L("CXmlParser::()"));
       
   140 	HBufC* newData = HBufC::NewL(aData.Length());
       
   141 	newData->Des().Copy(aData.Des());
       
   142 	ProcessDataL(newData);
       
   143 	__XML_LOG_RETURN;
       
   144 	}
       
   145 
       
   146 void CXmlParser::ProcessDataL(HBufC* aData)
       
   147 // Process given data. Parser takes owneship of the data.
       
   148 	{
       
   149 	__XML_LOG_ENTER(_L("CXmlParser::ProcessDataL()"));
       
   150 	EolNormalization(aData->Des());
       
   151 	
       
   152 	iString.AddStringL(aData);
       
   153 
       
   154 	if( iRootNode == NULL )
       
   155 		{
       
   156 		iErrorCode = EWapErrXmlLibMissingDocumentRootNode;
       
   157 		__XML_LOG(_L("ProcessDataL setting error code EWapErrXmlLibMissingDocumentRootNode"));
       
   158 		__XML_LOG_RETURN;
       
   159 		return;
       
   160 		}
       
   161 	if( !iDataGathering )
       
   162 		{
       
   163 		ParseL();
       
   164 		}
       
   165 	__XML_LOG_RETURN;
       
   166 	}
       
   167 
       
   168 void CXmlParser::CommitL()
       
   169 // All the data has been passed in. Finish.
       
   170 	{
       
   171 	__XML_LOG_ENTER(_L("CXmlParser::CommitL()"));
       
   172 	if( iDataGathering )
       
   173 		{
       
   174 		const HBufC* id = iLUT.Des2IDL(KXmlLibBufferedDocumentAttribute);
       
   175 		CDataNoDelete* attributeValue = new(ELeave) CDataNoDelete(iString.ContentL());
       
   176 		CleanupStack::PushL(attributeValue);
       
   177 		iRootNode->AddAttributeL(id, attributeValue);
       
   178 		CleanupStack::Pop(attributeValue);
       
   179 		iErrorCode = EWapErrXmlLibDocumentBuffered;
       
   180 		__XML_LOG(_L("CommitL setting error code EWapErrXmlLibDocumentBuffered"));
       
   181 		__XML_LOG_RETURN;
       
   182 		return;
       
   183 		}
       
   184 	CBNFParser::CommitL();
       
   185 	__XML_LOG_RETURN;
       
   186 	}
       
   187 
       
   188 //
       
   189 //	CALLBACK FUNCTIONS
       
   190 //
       
   191 
       
   192 // These methods are bound to specific rules and they are called when ever a rule finishes,
       
   193 // regardless of the success of the matching of the rule.
       
   194 // Functions, whose name start with "Post" are executed _after_ the rule and "Pre" rules
       
   195 // are executed prior to the matching attempt of a rule.
       
   196 
       
   197 
       
   198 void CXmlParser::PostCharDataL(CBNFParser& aParser)
       
   199 // Handle "ordinary" character data. This generates #PCDATA nodes for the body text
       
   200 // of the document. Nodes consisting only of white spaces are ignored.
       
   201 	{
       
   202 	__XML_EXT_LOG_ENTER(_L("CXmlParser::PostCharDataL()"));
       
   203 	CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser);
       
   204 
       
   205 	if( parser.RuleMatched() )
       
   206 		{
       
   207 		HBufC* data = parser.MarkedL();
       
   208 
       
   209 		TInt i=0;
       
   210 		TPtr text = data->Des();
       
   211 		for(; i < data->Length(); i++)
       
   212 			{
       
   213 			TInt ch=text[i];
       
   214 			if( !(ch == 0x9 || ch == 0xA || ch == 0xD || ch == 0x20)  )
       
   215 				{
       
   216 				break;
       
   217 				}
       
   218 			}
       
   219 		if( i >= data->Length() )
       
   220 			{
       
   221 			delete data;
       
   222 			parser.DeleteMark();
       
   223 			__XML_EXT_LOG_RETURN;
       
   224 			return;
       
   225 			}
       
   226 
       
   227 		parser.CharRefReplacement(text);
       
   228 
       
   229 		CleanupStack::PushL(data);
       
   230 		const HBufC* id = parser.iLUT.Des2IDL(KPCDataID);
       
   231 		CXmlElement* newNode = CXmlElement::NewL(id, parser.iCurrentNode);
       
   232 		parser.iCurrentNode->AppendChildL(newNode);  // Now the node is owned by the parent and would hence get deleted in a leave
       
   233 		newNode->SetDataL(data);
       
   234 		CleanupStack::Pop();
       
   235 		}
       
   236 	parser.DeleteMark();
       
   237 	__XML_EXT_LOG_RETURN;
       
   238 	}
       
   239 
       
   240 void CXmlParser::PostCDStart(CBNFParser& aParser)
       
   241 // Initialize matching of CDATA sections
       
   242 	{
       
   243 	__XML_EXT_LOG_ENTER(_L("CXmlParser::PostCDStart()"));
       
   244 	CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser);
       
   245 
       
   246 	if( parser.RuleMatched() )
       
   247 		{
       
   248 		delete parser.iCData;
       
   249 		parser.iCData = NULL;
       
   250 		}
       
   251 	__XML_EXT_LOG_RETURN;
       
   252 	}
       
   253 
       
   254 void CXmlParser::PostCDataL(CBNFParser& aParser)
       
   255 // Store the matched text withing CDATA section
       
   256 	{
       
   257 	__XML_EXT_LOG_ENTER(_L("CXmlParser::PostCData()"));
       
   258 	CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser);
       
   259 
       
   260 	if( parser.RuleMatched() )
       
   261 		{
       
   262 		parser.iCData = parser.MarkedL();
       
   263 		}
       
   264 	parser.DeleteMark();
       
   265 	__XML_EXT_LOG_RETURN;
       
   266 	}
       
   267 
       
   268 void CXmlParser::PostCDSectL(CBNFParser& aParser)
       
   269 // If whole of the CDATA section matches, a CDATA node is generated
       
   270 // and the data is attached to that node. In other cases the document
       
   271 // is in error.
       
   272 	{
       
   273 	__XML_EXT_LOG_ENTER(_L("CXmlParser::PostCDSectL()"));
       
   274 	CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser);
       
   275 
       
   276 	if( parser.RuleMatched() )
       
   277 		{
       
   278 		const HBufC* id = parser.iLUT.Des2IDL(KCDataID);
       
   279 		CXmlElement* newNode = CXmlElement::NewL(id, parser.iCurrentNode);
       
   280 		parser.iCurrentNode->AppendChildL(newNode);
       
   281 		newNode->SetDataL(parser.iCData);
       
   282 		parser.iCData = NULL;
       
   283 		}
       
   284 	else if( parser.iCData != NULL )
       
   285 		{
       
   286 		delete parser.iCData;
       
   287 		parser.iCData = NULL;
       
   288 		parser.iErrorCode = EWapErrXmlLibMissingCDATASectionEndTag;
       
   289 		parser.SetState(EStopped);
       
   290 		}
       
   291 	__XML_EXT_LOG_RETURN;
       
   292 	}
       
   293 
       
   294 
       
   295 void CXmlParser::PostNameL(CBNFParser& aParser)
       
   296 // Store string matching the Name -rule
       
   297 	{
       
   298 	__XML_EXT_LOG_ENTER(_L("CXmlParser::PostName()"));
       
   299 	CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser);
       
   300 
       
   301 	if( parser.RuleMatched() )
       
   302 		{
       
   303 		delete parser.iName;	// Get rid of the possibly errorneous, leftover name!
       
   304 		parser.iName = parser.MarkedL();
       
   305 		}
       
   306 	parser.DeleteMark();
       
   307 	__XML_EXT_LOG_RETURN;
       
   308 	}
       
   309 
       
   310 void CXmlParser::PostNodeNameL(CBNFParser& aParser)
       
   311 // Wrapper function for storing the matched Name string as a name of a Node.
       
   312 	{
       
   313 	__XML_EXT_LOG_ENTER(_L("CXmlParser::PostNodeNameL()"));
       
   314 	CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser);
       
   315 
       
   316 	if( parser.RuleMatched() )
       
   317 		{
       
   318 		// Validity constraint: root element name must match the Name declared in DOCTYPE
       
   319 		if( parser.iCurrentNode == parser.iRootNode )
       
   320 			{
       
   321 			if( parser.iDocRootName == NULL )
       
   322 				{
       
   323 				parser.iErrorCode = EWapErrXmlLibInvalidDocumentStructure;
       
   324 				parser.SetState(EStopped);
       
   325 				return;	
       
   326 				}
       
   327 			if( parser.iDocRootName->Compare(parser.iName->Des()) != 0 )
       
   328 				{
       
   329 				parser.iErrorCode = EWapErrXmlLibRootElementNameMismatch;
       
   330 				parser.SetState(EStopped);
       
   331 				return;
       
   332 				}
       
   333 			}
       
   334 		const HBufC* type = parser.iLUT.Des2IDL(parser.iName->Des());
       
   335 		parser.iCurrentNode->SetType(type);
       
   336 		delete parser.iName;
       
   337 		parser.iName = NULL;
       
   338 		}
       
   339 	__XML_EXT_LOG_RETURN;
       
   340 	}
       
   341 
       
   342 void CXmlParser::PreAttribute(CBNFParser& aParser)
       
   343 // Prepare for matching an attribute definition (attrName = "attrValue")
       
   344 	{
       
   345 	__XML_EXT_LOG_ENTER(_L("CXmlParser::PreAttribute()"));
       
   346 	CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser);
       
   347 
       
   348 	delete parser.iAttrName;
       
   349 	delete parser.iAttValue;
       
   350 	parser.iAttrName = parser.iAttValue = NULL;
       
   351 	__XML_EXT_LOG_RETURN;
       
   352 	}
       
   353 
       
   354 void CXmlParser::PostAttrName(CBNFParser& aParser)
       
   355 // Store the matched Name-string as attribute name
       
   356 	{
       
   357 	__XML_EXT_LOG_ENTER(_L("CXmlParser::PostAttrName()"));
       
   358 	CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser);
       
   359 
       
   360 	if( parser.RuleMatched() )
       
   361 		{
       
   362 		parser.iAttrName = parser.iName;
       
   363 		parser.iName = NULL;
       
   364 		}
       
   365 	__XML_EXT_LOG_RETURN;
       
   366 	}
       
   367 
       
   368 void CXmlParser::PostPureAttValueL(CBNFParser& aParser)
       
   369 // Store the matched string as attribute value
       
   370 	{
       
   371 	__XML_EXT_LOG_ENTER(_L("CXmlParser::PostPureAttValue()"));
       
   372 	CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser);
       
   373 
       
   374 	if( parser.RuleMatched() )
       
   375 		{
       
   376 		delete parser.iAttValue;
       
   377 		parser.iAttValue = parser.MarkedL();
       
   378 		}
       
   379 	parser.DeleteMark();
       
   380 	__XML_EXT_LOG_RETURN;
       
   381 	}
       
   382 
       
   383 void CXmlParser::PostAttributeL(CBNFParser& aParser)
       
   384 // Should all the parts of an attribute definition match, an attribute
       
   385 // is created for the current node.
       
   386 	{
       
   387 	__XML_EXT_LOG_ENTER(_L("CXmlParser::PostAttributeL()"));
       
   388 	CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser);
       
   389 
       
   390 	if( parser.RuleMatched() )
       
   391 		{
       
   392 		if(parser.iAttrName != NULL)
       
   393 			{
       
   394 			// Add the attribute
       
   395 			if(parser.iAttValue != NULL)
       
   396 				{
       
   397 				TPtr attrValText = parser.iAttValue->Des();
       
   398 				parser.CharRefReplacement(attrValText);
       
   399 				parser.iCurrentNode->SetAttributeL(*parser.iAttrName, *parser.iAttValue, parser.iLUT);
       
   400 				}
       
   401 			else
       
   402 				parser.iCurrentNode->SetAttributeL(*parser.iAttrName, KNullDesC, parser.iLUT);
       
   403 			}
       
   404 		delete parser.iAttValue;
       
   405 		delete parser.iAttrName;
       
   406 		parser.iAttrName = parser.iAttValue = NULL;
       
   407 		}
       
   408 	else if( parser.iAttValue != NULL || parser.iAttrName != NULL )
       
   409 		{
       
   410 		parser.iErrorCode = EWapErrXmlLibInvalidAttributeDeclaration;
       
   411 		parser.SetStatus(EStopped);
       
   412 		}
       
   413 	__XML_EXT_LOG_RETURN;
       
   414 	}
       
   415 
       
   416 void CXmlParser::PostTagStartL(CBNFParser& aParser)
       
   417 // A new tag start ("<") is matched, generate new node and attach it as child for its parent
       
   418 	{
       
   419 	__XML_EXT_LOG_ENTER(_L("CXmlParser::PostTagStartL()"));
       
   420 	CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser);
       
   421 
       
   422 	if( parser.RuleMatched() )
       
   423 		{
       
   424 		if( parser.iRootTagFound )
       
   425 			{
       
   426 			CXmlElement* newNode = CXmlElement::NewL(NULL, parser.iCurrentNode);
       
   427 			CleanupStack::PushL(newNode);
       
   428 			parser.iCurrentNode->AppendChildL(newNode);
       
   429 			CleanupStack::Pop();
       
   430 			parser.iCurrentNode = newNode;
       
   431 			}
       
   432 		else
       
   433 			{
       
   434 			parser.iRootTagFound = ETrue;
       
   435 			}
       
   436 		}
       
   437 	__XML_EXT_LOG_RETURN;
       
   438 	}
       
   439 
       
   440 void CXmlParser::PostEmptyElemClose(CBNFParser& aParser)
       
   441 // If we match a closing empty element (i.e. <tag /> ) then this tag has no children
       
   442 // and current node pointer is moved up to the parent
       
   443 	{
       
   444 	__XML_EXT_LOG_ENTER(_L("CXmlParser::PostEmptyElemClose()"));
       
   445 	CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser);
       
   446 
       
   447 	if( parser.RuleMatched() )
       
   448 		{
       
   449 		parser.iCurrentNode = (CXmlElement *)parser.iCurrentNode->Parent();
       
   450 		}
       
   451 	__XML_EXT_LOG_RETURN;
       
   452 	}
       
   453 
       
   454 void CXmlParser::PostETag(CBNFParser& aParser)
       
   455 // Post rule for an end tag. We check that the end tag name matches
       
   456 // the name of the node pointer by iCurrentNode (if everything is fine and
       
   457 // all the tags are properly opened and closed, the pointer should point
       
   458 // to the node that opened this tag). 
       
   459 	{
       
   460 	__XML_EXT_LOG_ENTER(_L("CXmlParser::PostETag()"));
       
   461 	CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser);
       
   462 
       
   463 	if( parser.RuleMatched() )
       
   464 		{
       
   465 		TDesC* type = (TDesC*)parser.iCurrentNode->Type();
       
   466 		if( type->Compare(*parser.iName) )
       
   467 			{
       
   468 			parser.iErrorCode = EWapErrXmlLibEndTagMismatch;
       
   469 			parser.SetState(EStopped);
       
   470 			}
       
   471 		else
       
   472 			{
       
   473 			// This is the end tag for iCurrentNode
       
   474 			if( parser.iCurrentNode != parser.iRootNode)
       
   475 				{
       
   476 				parser.iCurrentNode = (CXmlElement*)parser.iCurrentNode->Parent();
       
   477 				}
       
   478 			// Here we don't need to make a notification of the node being the document closing (e.g. </wml> )
       
   479 			// tag, since our rule tree won't match any subsequent tags and this will result in
       
   480 			// EWapErrXmlLibInvalidDocument on call to CommitL.
       
   481 			}
       
   482 		delete parser.iName;
       
   483 		parser.iName = NULL;
       
   484 		}
       
   485 	__XML_EXT_LOG_RETURN;
       
   486 	}
       
   487 
       
   488 void CXmlParser::PreExternalID(CBNFParser& aParser)
       
   489 // Prepare for matching an external ID
       
   490 	{
       
   491 	__XML_EXT_LOG_ENTER(_L("CXmlParser::PreExternalID()"));
       
   492 	CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser);
       
   493 
       
   494 	delete parser.iSystemLiteral;
       
   495 	delete parser.iPubidLiteral;
       
   496 	parser.iSystemLiteral = parser.iPubidLiteral = NULL;
       
   497 	__XML_EXT_LOG_RETURN;
       
   498 	}
       
   499 
       
   500 void CXmlParser::PostPureSystemLiteralL(CBNFParser& aParser)
       
   501 // Store the contents of the SystemLiteral
       
   502 	{
       
   503 	__XML_EXT_LOG_ENTER(_L("CXmlParser::PostPureSystemLiteral()"));
       
   504 	CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser);
       
   505 
       
   506 	if( parser.RuleMatched() )
       
   507 		{
       
   508 		parser.iSystemLiteral = parser.MarkedL();
       
   509 		}
       
   510 	parser.DeleteMark();
       
   511 	__XML_EXT_LOG_RETURN;
       
   512 	}
       
   513 
       
   514 void CXmlParser::PostPubidLiteralL(CBNFParser& aParser)
       
   515 // Post rule for PubidLiteral
       
   516 	{
       
   517 	__XML_EXT_LOG_ENTER(_L("CXmlParser::PostPubidLiteral()"));
       
   518 	CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser);
       
   519 
       
   520 	if( parser.RuleMatched() )
       
   521 		{
       
   522 		HBufC* data = parser.MarkedL();
       
   523 		// Since this entire rule matched, there must be quotation marks in the beginning
       
   524 		// and at the end of the string. Those are now removed.
       
   525 		TPtr pureLiteral = data->Des();
       
   526 		pureLiteral.Delete(pureLiteral.Length()-1,1);
       
   527 		pureLiteral.Delete(0,1);
       
   528 		parser.iPubidLiteral = data;
       
   529 		}
       
   530 	parser.DeleteMark();
       
   531 	__XML_EXT_LOG_RETURN;
       
   532 	}
       
   533 
       
   534 void CXmlParser::PostDTDidAndUrl(CBNFParser& aParser)
       
   535 // If this combination is successfully matched, we have a complete definition
       
   536 // for a DTD. This is signaled to the client who then can provide us with the
       
   537 // DTD tree is available.
       
   538 	{
       
   539 	__XML_EXT_LOG_ENTER(_L("CXmlParser::PostDTDidAndUrl()"));
       
   540 	CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser);
       
   541 
       
   542 	if( parser.RuleMatched() )
       
   543 		{
       
   544 		// NOTICE that PostDTDidAndUrl is a wrapper rule for an ExternalID and it is possible
       
   545 		// for an ExternalID to define just a URL, without the doctype. Here we assign
       
   546 		// the PubidLiteral to iDocType, which would in such case be NULL. Therefore the client
       
   547 		// using these values must check whether the doctype is NULL.
       
   548 		parser.iDocType = parser.iPubidLiteral;
       
   549 		parser.iDTDUrl = parser.iSystemLiteral;
       
   550 		parser.iPubidLiteral = parser.iSystemLiteral = NULL;
       
   551 		parser.iErrorCode = EDTDDefinitionFound;
       
   552 		parser.SetState(EPaused);
       
   553 		}
       
   554 	__XML_EXT_LOG_RETURN;
       
   555 	}
       
   556 
       
   557 void CXmlParser::PostCharReferenceValue(CBNFParser& aParser)
       
   558 // If character reference value rule didn't match, the document is in error
       
   559 // since, the beginning of a character reference (&#) did match
       
   560 	{
       
   561 	__XML_EXT_LOG_ENTER(_L("CXmlParser::PostCharReferenceValue()"));
       
   562 	CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser);
       
   563 
       
   564 	if( !parser.RuleMatched() )
       
   565 		{
       
   566 		parser.iErrorCode = EWapErrXmlLibInvalidCharacterReference;
       
   567 		parser.SetStatus(EStopped);
       
   568 		}
       
   569 	__XML_EXT_LOG_RETURN;
       
   570 	}
       
   571 
       
   572 _LIT(KLitLt,"lt");
       
   573 _LIT(KLitGt,"gt");
       
   574 _LIT(KLitAmp,"amp");
       
   575 _LIT(KLitApos,"apos");
       
   576 _LIT(KLitQuot,"quot");
       
   577 
       
   578 void CXmlParser::PostEntityRefL(CBNFParser& aParser)
       
   579 // After matching the an entity reference we substitute it
       
   580 // with the corresponding replacement text to the parsing text.
       
   581 // If the entity isn't one of the XML obligatory values,
       
   582 // the replacement text is retrieved from the DTD tree.
       
   583 // The parsing continues from the point where the replacement
       
   584 // text was inserted, not after it!
       
   585 	{
       
   586 	__XML_EXT_LOG_ENTER(_L("CXmlParser::PostEntityRefL()"));
       
   587 	CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser);
       
   588 
       
   589 	if( parser.RuleMatched() )
       
   590 		{
       
   591 		// The predefined entities (see XML specification, chapter 4.6)
       
   592 		const TText* stringPtr=parser.iName->Ptr();
       
   593 		TInt length=parser.iName->Length();
       
   594 		const TDesC* str=NULL;
       
   595 		if(Compare(length,stringPtr,KLitLt))
       
   596 			str=&KPredefEntityLT;
       
   597 		else if(Compare(length,stringPtr,KLitGt))
       
   598 			str=&KPredefEntityGT;
       
   599 		else if(Compare(length,stringPtr,KLitAmp))
       
   600 			str=&KPredefEntityAMP;
       
   601 		else if(Compare(length,stringPtr,KLitApos))
       
   602 			str=&KPredefEntityAPOS;
       
   603 		else if(Compare(length,stringPtr,KLitQuot))
       
   604 			str=&KPredefEntityQUOT;
       
   605 		HBufC* replacementText = NULL;
       
   606 		if( str )
       
   607 			replacementText = str->AllocL();
       
   608 		if( replacementText == NULL )
       
   609 			{
       
   610 			const HBufC* id = parser.iLUT.Des2IDL(parser.iName->Des());
       
   611 			CBNFNode* entityNode = REINTERPRET_CAST(CBNFNode*, parser.iDTD->Attribute(id) );
       
   612 			if( entityNode != NULL )
       
   613 				{
       
   614 				// On entity nodes the only child should be an AND node with an EExact child that
       
   615 				// that holds the replacement text data.
       
   616 				CTypedNode<TInt,const TDesC*>* child=entityNode->Child(0);
       
   617 				if( child != NULL && child->Type() == EExact )
       
   618 					{
       
   619 					replacementText = child->Data()->AllocL();
       
   620 					}
       
   621 				}
       
   622 			}
       
   623 
       
   624 		delete parser.iName;
       
   625 		parser.iName = NULL;
       
   626 
       
   627 		if( replacementText == NULL )
       
   628 			{
       
   629 			parser.iErrorCode = EWapErrXmlLibUnknownEntityReference;
       
   630 			parser.SetState(EStopped);
       
   631 			}
       
   632 
       
   633 		parser.iString.ReplaceMarkedL(replacementText);
       
   634 		}
       
   635 	parser.DeleteMark();
       
   636 	__XML_EXT_LOG_RETURN;
       
   637 	}
       
   638 
       
   639 
       
   640 void CXmlParser::PostVersionNumL(CBNFParser& aParser)
       
   641 // Store XML version string
       
   642 	{
       
   643 	__XML_EXT_LOG_ENTER(_L("CXmlParser::PostVersionNum()"));
       
   644 	CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser);
       
   645 
       
   646 	if( parser.RuleMatched() )
       
   647 		{
       
   648 		parser.iXmlVersionString = parser.MarkedL();
       
   649 		}
       
   650 	parser.DeleteMark();
       
   651 	__XML_EXT_LOG_RETURN;
       
   652 	}
       
   653 
       
   654 void CXmlParser::PostDoctypedecl(CBNFParser& aParser)
       
   655 // Check after a doctype declaration that there must have been
       
   656 // a DTD definition.
       
   657 	{
       
   658 	__XML_EXT_LOG_ENTER(_L("CXmlParser::PostDoctypedecl()"));
       
   659 	CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser);
       
   660 
       
   661 	if( parser.RuleMatched() )
       
   662 		{
       
   663 		if( parser.iDTDUrl == NULL )
       
   664 			{
       
   665 			parser.iErrorCode = ENoDTDDefined;
       
   666 			parser.SetState(EPaused);
       
   667 			}
       
   668 		}
       
   669 	__XML_EXT_LOG_RETURN;
       
   670 	}
       
   671 
       
   672 void CXmlParser::PostDocRootName(CBNFParser& aParser)
       
   673 // Store the document name definition in the doctypedecl
       
   674 // for later check, that the first tag has the same name
       
   675 	{
       
   676 	__XML_EXT_LOG_ENTER(_L("CXmlParser::PostDocRootName()"));
       
   677 	CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser);
       
   678 
       
   679 	if( parser.RuleMatched() )
       
   680 		{
       
   681 		parser.iDocRootName = parser.iName;
       
   682 		parser.iName = NULL;
       
   683 		}
       
   684 	__XML_EXT_LOG_RETURN;
       
   685 	}
       
   686 
       
   687 void CXmlParser::PostProlog(CBNFParser& aParser)
       
   688 // After the prolog part we can determine if we had wrong version
       
   689 // of Xml defined, if we didn't get a DTD and stuff.
       
   690 	{
       
   691 	__XML_EXT_LOG_ENTER(_L("CXmlParser::PostProlog()"));
       
   692 	CXmlParser& parser = REINTERPRET_CAST(CXmlParser&, aParser);
       
   693 
       
   694 	if( parser.iDTD == NULL )
       
   695 		{
       
   696 		// No DTD, no show. We can not proceed, unless we have a DTD!
       
   697 		parser.iErrorCode = EWapErrXmlLibNoDTD;
       
   698 		parser.SetState(EStopped);
       
   699 		}
       
   700 
       
   701 	if( parser.iXmlVersionString == NULL ||
       
   702 		parser.iXmlVersionString->Compare( KSupportedXmlVersion ) != 0 )
       
   703 		{
       
   704 		__XML_EXT_LOG1(_L("Looking for supported XML - \"%S\""), &KSupportedXmlVersion);
       
   705 
       
   706 		if (parser.iXmlVersionString==NULL)
       
   707 			{
       
   708 			__XML_EXT_LOG1(_L("But version string is NULL"), NULL);
       
   709 			}
       
   710 		else
       
   711 			{
       
   712 			TBuf<256> buf;
       
   713 			buf.Copy(*parser.iXmlVersionString);
       
   714 			__XML_EXT_LOG1(_L("Found XMLVersionString \"%S\""), &buf);
       
   715 			}
       
   716 		parser.iErrorCode = EWapErrXmlLibInvalidXmlVersionDefinition;
       
   717 		parser.SetState(EStopped);
       
   718 		}
       
   719 
       
   720 	delete parser.iXmlVersionString;
       
   721 	parser.iXmlVersionString = NULL;
       
   722 
       
   723 	// The mark set in the beginning of the document was to make sure that no data is deleted
       
   724 	// until we know for sure that we have a DTD and need not to buffer the data.
       
   725 	// We can now waste the already parsed data and that is allowed by removing the first
       
   726 	// mark. This point can not be reached if data gathering was active.
       
   727 	parser.DeleteMark();
       
   728 	__XML_EXT_LOG_RETURN;
       
   729 	}
       
   730 
       
   731 
       
   732 // A macro to define literal strings that are used to name and reference the rule
       
   733 // USAGE: _STRING(hello)
       
   734 //		this would result in definition of a literal called Khello that has value "hello"
       
   735 //		i.e. this equals to _LIT(Khello, "hello"); 
       
   736 #define _STRING(X) _LIT(K ## X, #X);
       
   737 
       
   738 CBNFNode* CXmlParser::TreeL()
       
   739 // Builds the rule tree to parse XML
       
   740 	{
       
   741 	__XML_LOG_ENTER(_L("CXmlParser::TreeL()"));
       
   742 
       
   743 	// save calling the exported function in CBNFNode dozens of times
       
   744 
       
   745 	const TDesC* rangeStart=CBNFNode::KRangeStart();
       
   746 	const TDesC* rangeEnd=CBNFNode::KRangeEnd();
       
   747 
       
   748 	CBNFNode* root = NewBNFL();
       
   749 	CleanupStack::PushL(root);
       
   750 
       
   751 	_STRING(document);
       
   752 	NewComponentL(root, *root, Kdocument);
       
   753 
       
   754 //
       
   755 //	Common "help rules"
       
   756 //
       
   757 	_STRING(S);
       
   758 	// Optional whitespace sequence: S?
       
   759 	_STRING(optS);
       
   760 	CBNFNode& optS = NewRuleL(root, KoptS, EOptional, NULL, NULL, NULL);
       
   761 	NewComponentL(root, optS, KS);
       
   762 
       
   763 	// Single quote: '
       
   764 	_STRING(singleQuote);
       
   765 	NewRuleL(root, KsingleQuote, EExact, _L("'"), NULL, NULL);
       
   766 
       
   767 	// Double quote
       
   768 	_STRING(doubleQuote);
       
   769 	NewRuleL(root, KdoubleQuote, EExact, _L("\""), NULL, NULL);
       
   770 
       
   771 	_STRING(Char);
       
   772 
       
   773 	// Number ::= [0-9]
       
   774 	_STRING(Number);
       
   775 	CBNFNode& Number = NewRuleL(root, KNumber, ERange, NULL, NULL, NULL);
       
   776 	AddComponentAttributeL(Number, rangeStart, '0');
       
   777 	AddComponentAttributeL(Number, rangeEnd, '9');
       
   778 
       
   779 	// HexNumber ::= [0-9a-fA-f]
       
   780 	_STRING(HexNumber);
       
   781 	CBNFNode& HexNumber = NewRuleL(root, KHexNumber, EOr, NULL, NULL, NULL);
       
   782 	NewComponentL(root, HexNumber, KNumber);
       
   783 	CBNFNode& HexNumber2 = NewComponentL(HexNumber, ERange);
       
   784 		AddComponentAttributeL(HexNumber2, rangeStart, 'a');
       
   785 		AddComponentAttributeL(HexNumber2, rangeEnd, 'f');
       
   786 	CBNFNode& HexNumber3 = NewComponentL(HexNumber, ERange);
       
   787 		AddComponentAttributeL(HexNumber3, rangeStart, 'A');
       
   788 		AddComponentAttributeL(HexNumber3, rangeEnd, 'F');
       
   789 
       
   790 	// HexValue ::= HexNumber+
       
   791 	_STRING(HexValue);
       
   792 	CBNFNode& HexValue = NewRuleL(root, KHexValue, ENMore, NULL, NULL, NULL);
       
   793 		AddComponentAttributeL(HexValue, CBNFNode::KNMoreMinimum(), 1);
       
   794 	NewComponentL(root, HexValue, KHexNumber);
       
   795 
       
   796 	// DecNumber ::= Digit+
       
   797 	_STRING(DecValue);
       
   798 	CBNFNode& DecValue = NewRuleL(root, KDecValue, ENMore, NULL, NULL, NULL);
       
   799 		AddComponentAttributeL(DecValue, CBNFNode::KNMoreMinimum(), 1);
       
   800 	NewComponentL(root, DecValue, KNumber);
       
   801 
       
   802 	// Latin char: [a-zA-Z]
       
   803 	_STRING(LatinChar);
       
   804 	CBNFNode& LatinChar = NewRuleL(root, KLatinChar, EOr, NULL, NULL, NULL);
       
   805 	CBNFNode& LatinChar1 = NewComponentL(LatinChar, ERange);
       
   806 		AddComponentAttributeL(LatinChar1, rangeStart, 'A');
       
   807 		AddComponentAttributeL(LatinChar1, rangeEnd, 'Z');
       
   808 	CBNFNode& LatinChar2 = NewComponentL(LatinChar, ERange);
       
   809 		AddComponentAttributeL(LatinChar2, rangeStart, 'a');
       
   810 		AddComponentAttributeL(LatinChar2, rangeEnd, 'z');
       
   811 
       
   812 //
       
   813 //	XML rules
       
   814 //
       
   815 	_STRING(prolog);
       
   816 	_STRING(element);
       
   817 	_STRING(Misc);
       
   818 	// XML specs rule [1]
       
   819 	// [1] document ::= prolog element Misc*
       
   820 	CBNFNode& document = NewRuleL(root, Kdocument, EAnd, NULL, NULL, NULL);
       
   821 	NewComponentL( root, document, Kprolog );
       
   822 	NewComponentL( root, document, Kelement );
       
   823 	CBNFNode& document3 = NewComponentL( document, ENMore );
       
   824 		NewComponentL( root, document3, KMisc);
       
   825 
       
   826 	// XML specs rule [2]
       
   827 	// [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] 
       
   828 	//
       
   829 	// Notes:
       
   830 	//	- Changed order of range 20-d7fff and selection of 9, 0xA and 0xD, since it is
       
   831 	//	  we probably can make match faster with the first range
       
   832 	//	- Removed the last range since we only support 16-bit chars
       
   833 	//  - Implemented this as its own ruletype
       
   834 	NewXmlRuleL(root, KChar, EChar);
       
   835 
       
   836 	// XML specs rule [3]
       
   837 	// [3] S ::= (#x20 | #x9 | #xD | #xA)+
       
   838 	//  - Implemented this as its own ruletype
       
   839 	NewXmlRuleL(root, KS, ES);
       
   840 
       
   841 	_STRING(Letter);
       
   842 	_STRING(FirstNameChar);
       
   843 	NewXmlRuleL(root, KFirstNameChar, EFirstNameChar);
       
   844 	_STRING(NMoreNameChar);
       
   845 	NewXmlRuleL(root, KNMoreNameChar, ENMoreNameChar);
       
   846 	// XML specs rule [5]
       
   847 	// [5] Name ::= (Letter | '_' | ':') (NameChar)*
       
   848 	_STRING(Name);
       
   849 	CBNFNode& Name = NewRuleL(root, KName, EAnd, NULL, MarkCallback, PostNameL);
       
   850 		NewComponentL(root, Name, KFirstNameChar);
       
   851 		NewComponentL(root, Name, KNMoreNameChar);
       
   852 
       
   853 	_STRING(Reference);
       
   854 	// Help rule
       
   855 	// Attribute value without the quote marks
       
   856 	// PureAttValue ::= ([^<&"] | Reference)*
       
   857 	_STRING(PureAttValueDQ);
       
   858 	CBNFNode& PureAttValueDQ = NewRuleL(root, KPureAttValueDQ, ENMore, NULL, MarkCallback, PostPureAttValueL);
       
   859 	CBNFNode& PureAttValueDQ1 = NewComponentL(PureAttValueDQ, EOr);
       
   860 		NewComponentL(PureAttValueDQ1, ESelect, _L("^<&\"") );
       
   861 		NewComponentL(root, PureAttValueDQ1, KReference);
       
   862 
       
   863 	_STRING(PureAttValueSQ);
       
   864 	CBNFNode& PureAttValueSQ = NewRuleL(root, KPureAttValueSQ, ENMore, NULL, MarkCallback, PostPureAttValueL);
       
   865 	CBNFNode& PureAttValueSQ1 = NewComponentL(PureAttValueSQ, EOr);
       
   866 		NewComponentL(PureAttValueSQ1, ESelect, _L("^<&'") );
       
   867 		NewComponentL(root, PureAttValueSQ1, KReference);
       
   868 
       
   869 		// XML specs rule [10]
       
   870 	// [10] AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'"
       
   871 	_STRING(AttValue);
       
   872 	CBNFNode& AttValue = NewRuleL(root, KAttValue, EOr, NULL, NULL, NULL );
       
   873 	CBNFNode& AttValue1 = NewComponentL(AttValue, EAnd);
       
   874 		NewComponentL(root, AttValue1, KdoubleQuote);
       
   875 		NewComponentL(root, AttValue1, KPureAttValueDQ);
       
   876 		NewComponentL(root, AttValue1, KdoubleQuote);
       
   877 	CBNFNode& AttValue2 = NewComponentL(AttValue, EAnd);
       
   878 		NewComponentL(root, AttValue2, KsingleQuote);
       
   879 		NewComponentL(root, AttValue2, KPureAttValueSQ);
       
   880 		NewComponentL(root, AttValue2, KsingleQuote);
       
   881 
       
   882 	// Help rule
       
   883 	// System literal without the quotation marks
       
   884 	// PureSystemLiteral ::= [^"]*
       
   885 	_STRING(PureSystemLiteralDoubleQuote);
       
   886 	CBNFNode& PureSystemLiteralDQ = NewRuleL(root, KPureSystemLiteralDoubleQuote, ENMore, NULL, MarkCallback, PostPureSystemLiteralL);
       
   887 	NewComponentL(PureSystemLiteralDQ, ESelect, _L("^\"") );
       
   888 
       
   889 	_STRING(PureSystemLiteralSingleQuote);
       
   890 	CBNFNode& PureSystemLiteralSQ = NewRuleL(root, KPureSystemLiteralSingleQuote, ENMore, NULL, MarkCallback, PostPureSystemLiteralL);
       
   891 	NewComponentL(PureSystemLiteralSQ, ESelect, _L("^'") );
       
   892 
       
   893 	// XML specs rule [11]
       
   894 	// [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
       
   895 	_STRING(SystemLiteral);
       
   896 	CBNFNode& SystemLiteral = NewRuleL(root, KSystemLiteral, EOr, NULL, NULL, NULL);
       
   897 	CBNFNode& SystemLiteral1 = NewComponentL(SystemLiteral, EAnd);
       
   898 		NewComponentL(root, SystemLiteral1, KdoubleQuote);
       
   899 		NewComponentL(root, SystemLiteral1, KPureSystemLiteralDoubleQuote);
       
   900 		NewComponentL(root, SystemLiteral1, KdoubleQuote);
       
   901 	CBNFNode& SystemLiteral2 = NewComponentL(SystemLiteral, EAnd);
       
   902 		NewComponentL(root, SystemLiteral2, KsingleQuote);
       
   903 		NewComponentL(root, SystemLiteral2, KPureSystemLiteralSingleQuote);
       
   904 		NewComponentL(root, SystemLiteral2, KsingleQuote);
       
   905 
       
   906 	_STRING(PubidChar);
       
   907 	// XML specs rule [12]
       
   908 	// [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
       
   909 	_STRING(PubidLiteral);
       
   910 	CBNFNode& PubidLiteral = NewRuleL(root, KPubidLiteral, EOr, NULL, MarkCallback, PostPubidLiteralL);
       
   911 	CBNFNode& PubidLiteral1 = NewComponentL(PubidLiteral, EAnd);
       
   912 		NewComponentL(root, PubidLiteral1, KdoubleQuote);
       
   913 		CBNFNode& PubidLiteral12 = NewComponentL(PubidLiteral1, ENMore);
       
   914 			NewComponentL(root, PubidLiteral12, KPubidChar);
       
   915 		NewComponentL(root, PubidLiteral1, KdoubleQuote);
       
   916 	CBNFNode& PubidLiteral2 = NewComponentL(PubidLiteral, EAnd);
       
   917 		NewComponentL(root, PubidLiteral2, KsingleQuote);
       
   918 		CBNFNode& PubidLiteral22 = NewComponentL(PubidLiteral2, ENMore);
       
   919 			CBNFNode& PubidLiteral221 = NewComponentL(PubidLiteral22, EWithout);
       
   920 				NewComponentL(root, PubidLiteral221, KPubidChar);
       
   921 				NewComponentL(PubidLiteral221, EExact, _L("'") );
       
   922 		NewComponentL(root, PubidLiteral2, KsingleQuote);
       
   923 
       
   924 	// XML specs rule [13]
       
   925 	// [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
       
   926 	CBNFNode& PubidChar = NewRuleL(root, KPubidChar, EOr, NULL, NULL, NULL);
       
   927 	NewComponentL(PubidChar, ESelect, _L(" \r\n") );
       
   928 	NewComponentL(root, PubidChar, KLatinChar);
       
   929 	NewComponentL(root, PubidChar, KNumber);
       
   930 	NewComponentL(PubidChar, ESelect, _L("-'()+,./:=?;!*#@$_%") );
       
   931 
       
   932 	_STRING(CharRef);
       
   933 	// XML specs rule [14]
       
   934 	// [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
       
   935 	// valid CharData shall has length more than zero.
       
   936 	// Also character references are included to the char data and replaced later.
       
   937 	// CharData ::= (([^<&]+ - ([^<&]* ']]>' [^<&]*)) | CharRef)+
       
   938 	//
       
   939 	// Optimized:
       
   940 	// CharData ::= ( [^<&]+ | CharRef )+
       
   941 	_STRING(CharData);
       
   942 	CBNFNode& CharData = NewRuleL(root, KCharData, ENMore, NULL, MarkCallback, PostCharDataL);
       
   943 		AddComponentAttributeL(CharData, CBNFNode::KNMoreMinimum(), 1);
       
   944 	CBNFNode& CharData1 = NewComponentL(CharData, EOr);
       
   945 		CBNFNode& CharData11 = NewComponentL(CharData1, ENMore);
       
   946 			AddComponentAttributeL(CharData11, CBNFNode::KNMoreMinimum(), 1);
       
   947 			NewComponentL(CharData11, ESelect, _L("^<&") );
       
   948 		NewComponentL(root, CharData1, KCharRef);
       
   949 
       
   950 	// XML specs rule [15]
       
   951 	// [15] Comment ::= "<!--" ((Char - '-') | ('-' (Char - '-')))* "-->"
       
   952 	_STRING(Comment);
       
   953 	CBNFNode& Comment = NewRuleL(root, KComment, EAnd, NULL, NULL, NULL);
       
   954 	NewComponentL(Comment, EExact, _L("<!--"));
       
   955 		CBNFNode& Comment0 = NewComponentL(Comment, ENMore);
       
   956 			CBNFNode& Comment1 = NewComponentL(Comment0, EOr);
       
   957 				CBNFNode& Comment11 = NewComponentL(Comment1, EWithout);
       
   958 					NewComponentL(root, Comment11, KChar);
       
   959 					NewComponentL(Comment11, EExact, _L("-"));
       
   960 				CBNFNode& Comment12 = NewComponentL(Comment1, EAnd);
       
   961 					NewComponentL(Comment12, EExact, _L("-"));
       
   962 					CBNFNode& Comment122 = NewComponentL(Comment12, EWithout);
       
   963 						NewComponentL(root, Comment122, KChar);
       
   964 						NewComponentL(Comment122, EExact, _L("-"));
       
   965 	NewComponentL(Comment, EExact, _L("-->"));
       
   966 
       
   967 	_STRING(PITarget);
       
   968 	// XML specs rule [16]
       
   969 	// [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
       
   970 	// PIs are wasted, reformulated the rule:
       
   971 	// PI ::= '<?' PITarget (Char - '?>')* '?>'
       
   972 	_STRING(PI);
       
   973 	CBNFNode& PI = NewRuleL(root, KPI, EAnd, NULL, NULL, NULL);
       
   974 	NewComponentL(PI, EExact, _L("<?") );
       
   975 	NewComponentL(root, PI, KPITarget);
       
   976 	CBNFNode& PI4 = NewComponentL(PI, ENMore);
       
   977 		CBNFNode& PI41 = NewComponentL(PI4, EWithout);
       
   978 			NewComponentL(root, PI41, KChar);
       
   979 			NewComponentL(PI41, EExact, _L("?>") );
       
   980 	NewComponentL(PI, EExact, _L("?>") );
       
   981 
       
   982 	// XML specs rule [17]
       
   983 	// [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
       
   984 	CBNFNode& PITarget = NewRuleL(root, KPITarget, EWithout, NULL, NULL, NULL);
       
   985 	NewComponentL(root, PITarget, KName);
       
   986 	CBNFNode& PITarget2 = NewComponentL(PITarget, EAnd);
       
   987 		NewComponentL(PITarget2, ESelect, _L("Xx") );
       
   988 		NewComponentL(PITarget2, ESelect, _L("Mm") );
       
   989 		NewComponentL(PITarget2, ESelect, _L("Ll") );
       
   990 
       
   991 	_STRING(CDStart);
       
   992 	_STRING(CData);
       
   993 	_STRING(CDEnd);
       
   994 	// XML specs rule [18]
       
   995 	// [18] CDSect ::= CDStart CData CDEnd
       
   996 	_STRING(CDSect);
       
   997 	CBNFNode& CDSect = NewRuleL(root, KCDSect, EAnd, NULL, NULL, PostCDSectL);
       
   998 	NewComponentL(root, CDSect, KCDStart);
       
   999 	NewComponentL(root, CDSect, KCData);
       
  1000 	NewComponentL(root, CDSect, KCDEnd);
       
  1001 
       
  1002 	// XML specs rule [19]
       
  1003 	// [19] CDStart ::= '<![CDATA['
       
  1004 	NewRuleL(root, KCDStart, EExact, _L("<![CDATA["), NULL, PostCDStart);
       
  1005 
       
  1006 	// XML specs rule [20]
       
  1007 	// [20] CData ::= (Char* - (Char* ']]>' Char*))
       
  1008 	// Modified:
       
  1009 	// CData ::= (Char - ']]>')*
       
  1010 	CBNFNode& CData = NewRuleL(root, KCData, ENMore, NULL, MarkCallback, PostCDataL);
       
  1011 	CBNFNode& CData1 = NewComponentL(CData, EWithout);
       
  1012 		NewComponentL(root, CData1, KChar);
       
  1013 		NewComponentL(CData1, EExact, _L("]]>") );
       
  1014 
       
  1015 	// XML specs rule [21]
       
  1016 	// [21] CDEnd ::= ']]>'
       
  1017 	NewRuleL(root, KCDEnd, EExact, _L("]]>"), NULL, NULL);
       
  1018 
       
  1019 	_STRING(XMLDecl);
       
  1020 	_STRING(doctypedecl);
       
  1021 	// XML specs rule [22]
       
  1022 	// [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
       
  1023 	CBNFNode& prolog = NewRuleL(root, Kprolog, EAnd, NULL, MarkCallback, PostProlog);
       
  1024 	CBNFNode& prolog1 = NewComponentL(prolog, EOptional);
       
  1025 		NewComponentL(root, prolog1, KXMLDecl);
       
  1026 	CBNFNode& prolog2 = NewComponentL(prolog, ENMore);
       
  1027 		NewComponentL(root, prolog2, KMisc);
       
  1028 	CBNFNode& prolog3 = NewComponentL(prolog, EOptional);
       
  1029 		CBNFNode& prolog31 = NewComponentL(prolog3, EAnd);
       
  1030 			NewComponentL(root, prolog31, Kdoctypedecl);
       
  1031 			CBNFNode& prolog312 = NewComponentL(prolog31, ENMore);
       
  1032 				NewComponentL(root, prolog312, KMisc);
       
  1033 
       
  1034 	_STRING(VersionInfo);
       
  1035 	_STRING(EncodingDecl);
       
  1036 	_STRING(SDDecl);
       
  1037 	// XML specs rule [23]
       
  1038 	// [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
       
  1039 	CBNFNode& XMLDecl = NewRuleL(root, KXMLDecl, EAnd, NULL, NULL, NULL);
       
  1040 	NewComponentL(root, XMLDecl, KoptS);
       
  1041 	NewComponentL(XMLDecl, EExact, _L("<?xml") );
       
  1042 	NewComponentL(root, XMLDecl, KVersionInfo);
       
  1043 	CBNFNode& XMLDecl3 = NewComponentL(XMLDecl, EOptional);
       
  1044 		NewComponentL(root, XMLDecl3, KEncodingDecl);
       
  1045 	CBNFNode& XMLDecl4 = NewComponentL(XMLDecl, EOptional);
       
  1046 		NewComponentL(root, XMLDecl4, KSDDecl);
       
  1047 	NewComponentL(root, XMLDecl, KoptS);
       
  1048 	NewComponentL(XMLDecl, EExact, _L("?>") );
       
  1049 
       
  1050 	_STRING(Eq);
       
  1051 	_STRING(VersionNum);
       
  1052 	// XML specs rule [24]
       
  1053 	// [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
       
  1054 	CBNFNode& VersionInfo = NewRuleL(root, KVersionInfo, EAnd, NULL, NULL, NULL);
       
  1055 	NewComponentL(root, VersionInfo, KS);
       
  1056 	NewComponentL(VersionInfo, EExact, _L("version") );
       
  1057 	NewComponentL(root, VersionInfo, KEq);
       
  1058 	CBNFNode& VersionInfo4 = NewComponentL(VersionInfo, EOr);
       
  1059 		CBNFNode& VersionInfo41 = NewComponentL(VersionInfo4, EAnd);
       
  1060 			NewComponentL(root, VersionInfo41, KsingleQuote);
       
  1061 			NewComponentL(root, VersionInfo41, KVersionNum);
       
  1062 			NewComponentL(root, VersionInfo41, KsingleQuote);
       
  1063 		CBNFNode& VersionInfo42 = NewComponentL(VersionInfo4, EAnd);
       
  1064 			NewComponentL(root, VersionInfo42, KdoubleQuote);
       
  1065 			NewComponentL(root, VersionInfo42, KVersionNum);
       
  1066 			NewComponentL(root, VersionInfo42, KdoubleQuote);
       
  1067 
       
  1068 	// XML specs rule [25]
       
  1069 	// [25] Eq ::= S? '=' S?
       
  1070 	CBNFNode& Eq = NewRuleL(root, KEq, EAnd, NULL, NULL, NULL);
       
  1071 	NewComponentL(root, Eq, KoptS);
       
  1072 	NewComponentL(Eq, EExact, _L("=") );
       
  1073 	NewComponentL(root, Eq, KoptS);
       
  1074 
       
  1075 	// XML specs rule [26]
       
  1076 	// [26] VersionNum ::= ([a-zA-Z0-9_.:] | '-')+
       
  1077 	CBNFNode& VersionNum = NewRuleL(root, KVersionNum, ENMore, NULL, MarkCallback, PostVersionNumL);
       
  1078 		AddComponentAttributeL(VersionNum, CBNFNode::KNMoreMinimum(), 1);
       
  1079 	CBNFNode& VersionNum1 = NewComponentL(VersionNum, EOr);
       
  1080 		CBNFNode& VersionNum11 = NewComponentL(VersionNum1, ERange);
       
  1081 			AddComponentAttributeL(VersionNum11, rangeStart, 'a');
       
  1082 			AddComponentAttributeL(VersionNum11, rangeEnd, 'z');
       
  1083 		CBNFNode& VersionNum12 = NewComponentL(VersionNum1, ERange);
       
  1084 			AddComponentAttributeL(VersionNum12, rangeStart, 'A');
       
  1085 			AddComponentAttributeL(VersionNum12, rangeEnd, 'Z');
       
  1086 		CBNFNode& VersionNum13 = NewComponentL(VersionNum1, ERange);
       
  1087 			AddComponentAttributeL(VersionNum13, rangeStart, '0');
       
  1088 			AddComponentAttributeL(VersionNum13, rangeEnd, '9');
       
  1089 		NewComponentL(VersionNum1, ESelect, _L("-_.:") );
       
  1090 
       
  1091 	// XML specs rule [27]
       
  1092 	// [27] Misc ::= Comment | PI | S
       
  1093 	//
       
  1094 	// Notes:
       
  1095 	//	- Put S (whitespace) first, since it is the most probable match here
       
  1096 	CBNFNode& Misc = NewRuleL(root, KMisc, EOr, NULL, NULL, NULL);
       
  1097 	NewComponentL(root, Misc, KS);
       
  1098 	NewComponentL(root, Misc, KComment);
       
  1099 	NewComponentL(root, Misc, KPI);
       
  1100 
       
  1101 	// Help rule
       
  1102 	// a rule, that can succesfully ignore a valid inline dtd
       
  1103 	// inlineDTD ::= ( S | Comment | ( <! ("[^"]*" | '[^']*' | Char-'>')* > ) | PI )*
       
  1104 	_STRING(inlineDTD);
       
  1105 	CBNFNode& inlineDTD = NewRuleL(root, KinlineDTD, EOr, NULL, NULL, NULL);
       
  1106 	CBNFNode& inlineDTD0 = NewComponentL(inlineDTD, ENMore);
       
  1107 	CBNFNode& inlineDTD1 = NewComponentL(inlineDTD0, EOr);
       
  1108 		NewComponentL(root, inlineDTD1, KS);
       
  1109 		NewComponentL(root, inlineDTD1, KComment);
       
  1110 		CBNFNode& inlineDTD12 = NewComponentL(inlineDTD1, EAnd);
       
  1111 			NewComponentL(inlineDTD12, EExact, _L("<!") );
       
  1112 			CBNFNode& inlineDTD122 = NewComponentL(inlineDTD12, ENMore);
       
  1113 				CBNFNode& inlineDTD1221 = NewComponentL(inlineDTD122, EOr);
       
  1114 					CBNFNode& inlineDTD12211 = NewComponentL(inlineDTD1221, EAnd);
       
  1115 						NewComponentL(root, inlineDTD12211, KdoubleQuote);
       
  1116 						CBNFNode& inlineDTD122112 = NewComponentL(inlineDTD12211, ENMore);
       
  1117 							NewComponentL(inlineDTD122112, ESelect, _L("^\"") );
       
  1118 						NewComponentL(root, inlineDTD12211, KdoubleQuote);
       
  1119 					CBNFNode& inlineDTD12212 = NewComponentL(inlineDTD1221, EAnd);
       
  1120 						NewComponentL(root, inlineDTD12212, KsingleQuote);
       
  1121 						CBNFNode& inlineDTD122122 = NewComponentL(inlineDTD12212, ENMore);
       
  1122 							NewComponentL(inlineDTD122122, ESelect, _L("^'") );
       
  1123 						NewComponentL(root, inlineDTD12212, KsingleQuote);
       
  1124 					CBNFNode& inlineDTD12213 = NewComponentL(inlineDTD1221, EWithout);
       
  1125 						NewComponentL(root, inlineDTD12213, KChar);
       
  1126 						NewComponentL(inlineDTD12213, EExact, _L(">") );
       
  1127 			NewComponentL(inlineDTD12, EExact, _L(">") );
       
  1128 		NewComponentL(root, inlineDTD1, KPI);
       
  1129 
       
  1130 	_STRING(ExternalID);
       
  1131 	// Help rule
       
  1132 	// DTD doctype and url
       
  1133 	_STRING(DTDidAndUrl);
       
  1134 	CBNFNode& DTDidAndUrl = NewRuleL(root, KDTDidAndUrl, EAnd, NULL, NULL, PostDTDidAndUrl);
       
  1135 	NewComponentL(root, DTDidAndUrl, KExternalID);
       
  1136 
       
  1137 	// Help rule
       
  1138 	// KDocRootName = Name
       
  1139 	_STRING(DocRootName);
       
  1140 	CBNFNode& docRootName = NewRuleL(root, KDocRootName, EAnd, NULL, NULL, PostDocRootName);
       
  1141 	NewComponentL(root, docRootName, KName);
       
  1142 
       
  1143 	// XML specs rule [28]
       
  1144 	// [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S? ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
       
  1145 	// NOTE: part contained inside braces is not handled here, but is interpreted as
       
  1146 	//       inline DTD and shall be handled by the DTDDH. The actual form of this rule here is:
       
  1147 	// [28] doctypedecl ::= '<!DOCTYPE' S DocRootName (S DTDidAndUrl)? S? ('[' inlineDTD ']' S?)? '>'
       
  1148 	CBNFNode& doctypedecl = NewRuleL(root, Kdoctypedecl, EAnd, NULL, NULL, PostDoctypedecl);
       
  1149 	NewComponentL(doctypedecl, EExact, _L("<!DOCTYPE") );
       
  1150 	NewComponentL(root, doctypedecl, KS);
       
  1151 	NewComponentL(root, doctypedecl, KDocRootName);
       
  1152 	CBNFNode& doctypedecl4 = NewComponentL(doctypedecl, EOptional);
       
  1153 		CBNFNode& doctypedecl41 = NewComponentL(doctypedecl4, EAnd);
       
  1154 			NewComponentL(root, doctypedecl41, KS);
       
  1155 			NewComponentL(root, doctypedecl41, KDTDidAndUrl);
       
  1156 	NewComponentL(root, doctypedecl, KoptS);
       
  1157 	CBNFNode& doctypedecl6 = NewComponentL(doctypedecl, EOptional);
       
  1158 		CBNFNode& doctypedecl61 = NewComponentL(doctypedecl6, EAnd);
       
  1159 			NewComponentL(doctypedecl61, EExact, _L("[") );
       
  1160 			NewComponentL(root, doctypedecl61, KinlineDTD);
       
  1161 			NewComponentL(doctypedecl61, EExact, _L("]") );
       
  1162 			NewComponentL(root, doctypedecl61, KoptS);
       
  1163 	NewComponentL(doctypedecl, EExact, _L(">") );
       
  1164 
       
  1165 	// Help rule
       
  1166 	// yes | no
       
  1167 	_STRING(YesOrNo);
       
  1168 	CBNFNode& YesOrNo = NewRuleL(root, KYesOrNo, EOr, NULL, NULL, NULL);
       
  1169 	NewComponentL(YesOrNo, EExact, _L("yes") );
       
  1170 	NewComponentL(YesOrNo, EExact, _L("no") );
       
  1171 
       
  1172 	// XML specs rule [32]
       
  1173 	// [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"'))
       
  1174 	CBNFNode& SDDecl = NewRuleL(root, KSDDecl, EAnd, NULL, NULL, NULL);
       
  1175 	NewComponentL(root, SDDecl, KS);
       
  1176 	NewComponentL(SDDecl, EExact, _L("standalone") );
       
  1177 	NewComponentL(root, SDDecl, KEq);
       
  1178 	CBNFNode& SDDecl4 = NewComponentL(SDDecl, EOr);
       
  1179 		CBNFNode& SDDecl41 = NewComponentL(SDDecl4, EAnd);
       
  1180 			NewComponentL(root, SDDecl41, KsingleQuote);
       
  1181 			NewComponentL(root, SDDecl41, KYesOrNo);
       
  1182 			NewComponentL(root, SDDecl41, KsingleQuote);
       
  1183 		CBNFNode& SDDecl42 = NewComponentL(SDDecl4, EAnd);
       
  1184 			NewComponentL(root, SDDecl42, KdoubleQuote);
       
  1185 			NewComponentL(root, SDDecl42, KYesOrNo);
       
  1186 			NewComponentL(root, SDDecl42, KdoubleQuote);
       
  1187 
       
  1188 
       
  1189 	// Help rule
       
  1190 	// EmptyElemTag closing "/>"
       
  1191 	// EmptyElemClose ::= "/>"
       
  1192 	_STRING(EmptyElemClose);
       
  1193 	NewRuleL(root, KEmptyElemClose, EExact, _L("/>"), NULL, PostEmptyElemClose);
       
  1194 
       
  1195 	_STRING(Tag);
       
  1196 	_STRING(content);
       
  1197 	_STRING(ETag);
       
  1198 	// XML specs rule [39]
       
  1199 	// [39] element ::= EmptyElemTag | STag content ETag 
       
  1200 	// For the sake of efficency and to make it possible to consume the matching
       
  1201 	// tokens immediately, we have rearranged this rule as follows:
       
  1202 	// element ::= Tag ( "/>" | '>' content ETag)
       
  1203 	CBNFNode& element = NewRuleL(root, Kelement, EAnd, NULL, NULL, NULL);
       
  1204 	NewComponentL(root, element, KTag);
       
  1205 	CBNFNode& element2 = NewComponentL(element, EOr);
       
  1206 		NewComponentL(root, element2, KEmptyElemClose);
       
  1207 		CBNFNode& element22 = NewComponentL(element2, EAnd);
       
  1208 			NewComponentL(element22, EExact, _L(">") );
       
  1209 			NewComponentL(root, element22, Kcontent);
       
  1210 			NewComponentL(root, element22, KETag);
       
  1211 
       
  1212 	// Help rule
       
  1213 	// NodeName ::= Name
       
  1214 	// This is basically a wrapper for Name to be able to attach it to the current node
       
  1215 	_STRING(NodeName);
       
  1216 	CBNFNode& NodeName = NewRuleL(root, KNodeName, EOr, NULL, NULL, PostNodeNameL);
       
  1217 	NewComponentL(root, NodeName, KName);
       
  1218 
       
  1219 	// Help rule
       
  1220 	// TagStart ::= '<'
       
  1221 	_STRING(TagStart);
       
  1222 	NewRuleL(root, KTagStart, EExact, _L("<"), NULL, PostTagStartL);
       
  1223 
       
  1224 	_STRING(Attribute);
       
  1225 	// XML specs rule [40]
       
  1226 	// [40] STag ::= '<' Name (S Attribute)* S? '>' 
       
  1227 	// The ending '>' is left out to make this a common Tag for both the STag and
       
  1228 	// EmptyElemTag.
       
  1229 	// Tag ::= '<' NodeName (S Attribute)* S?
       
  1230 	CBNFNode& Tag = NewRuleL(root, KTag, EAnd, NULL, NULL, NULL);
       
  1231 	NewComponentL(root, Tag, KTagStart);
       
  1232 	NewComponentL(root, Tag, KNodeName);
       
  1233 	CBNFNode& Tag3 = NewComponentL(Tag, ENMore);
       
  1234 		CBNFNode& Tag31 = NewComponentL(Tag3, EAnd);
       
  1235 			NewComponentL(root, Tag31, KS);
       
  1236 			NewComponentL(root, Tag31, KAttribute);
       
  1237 	NewComponentL(root, Tag, KoptS);
       
  1238 
       
  1239 	// Help rule
       
  1240 	// AttrName := Name
       
  1241 	_STRING(AttrName);
       
  1242 	CBNFNode& AttrName = NewRuleL(root, KAttrName, EOr, NULL, NULL, PostAttrName);
       
  1243 	NewComponentL(root, AttrName, KName);
       
  1244 
       
  1245 	// XML specs rule [41]
       
  1246 	// [41] Attribute ::= Name Eq AttValue 
       
  1247 	CBNFNode& Attribute = NewRuleL(root, KAttribute, EAnd, NULL, PreAttribute, PostAttributeL);
       
  1248 	NewComponentL(root, Attribute, KAttrName);
       
  1249 	NewComponentL(root, Attribute, KEq);
       
  1250 	NewComponentL(root, Attribute, KAttValue);
       
  1251 
       
  1252 	// XML specs rule [42]
       
  1253 	// [42] ETag ::= '</' Name S? '>'
       
  1254 	CBNFNode& ETag = NewRuleL(root, KETag, EAnd, NULL, NULL, PostETag);
       
  1255 	NewComponentL(ETag, EExact, _L("</") );
       
  1256 	NewComponentL(root, ETag, KName);
       
  1257 	NewComponentL(root, ETag, KoptS);
       
  1258 	NewComponentL(ETag, EExact, _L(">") );
       
  1259 
       
  1260 	_STRING(EntityRef);
       
  1261 	// XML specs rule [43]
       
  1262 	// [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
       
  1263 	// To make it work properly, the rule is rearranged. Now we can immediately consume
       
  1264 	// matching patterns.
       
  1265 	// content ::= (EntityRef | CDSect | PI | Comment | (element - "</") | CharData)*
       
  1266 	CBNFNode& content = NewRuleL(root, Kcontent, ENMore, NULL, NULL, NULL);
       
  1267 	CBNFNode& content1 = NewComponentL(content, EOr);
       
  1268 		NewComponentL(root, content1, KEntityRef);
       
  1269 		NewComponentL(root, content1, KCDSect);
       
  1270 		NewComponentL(root, content1, KPI);
       
  1271 		NewComponentL(root, content1, KComment);
       
  1272 		// This prevents the element matching to ETag!
       
  1273 		CBNFNode& content14 = NewComponentL(content1, EWithout);
       
  1274 			NewComponentL(root, content14, Kelement);
       
  1275 			NewComponentL(content14, EExact, _L("</") );
       
  1276 		NewComponentL(root, content1, KCharData);
       
  1277 
       
  1278 	// Help rules
       
  1279 	// For hex and decimal character reference values
       
  1280 
       
  1281 	// HexCharRefVal = [0-9a-fA-F]+ ';'
       
  1282 	_STRING(HexCharRefValue);
       
  1283 	CBNFNode& HexCharRefVal = NewRuleL(root, KHexCharRefValue, EAnd, NULL, NULL, PostCharReferenceValue);
       
  1284 		NewComponentL(root, HexCharRefVal, KHexValue);
       
  1285 		NewComponentL(HexCharRefVal, EExact, _L(";") );
       
  1286 
       
  1287 	// DecCharRefVal = [0-9]+ ';'
       
  1288 	_STRING(DecCharRefValue);
       
  1289 	CBNFNode& DecCharRefVal = NewRuleL(root, KDecCharRefValue, EAnd, NULL, NULL, PostCharReferenceValue);
       
  1290 		NewComponentL(root, DecCharRefVal, KDecValue);
       
  1291 		NewComponentL(DecCharRefVal, EExact, _L(";") );
       
  1292 
       
  1293 	// XML specs rule [66]
       
  1294 	// [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';' 
       
  1295 	// Swapped places for hex and dec reference to improve performance
       
  1296 	// CharRef ::= '&#x' [0-9a-fA-F]+ ';' | '&#' [0-9]+ ';'
       
  1297 	CBNFNode& CharRef = NewRuleL(root, KCharRef, EOr, NULL, NULL, NULL);
       
  1298 	CBNFNode& CharRef2 = NewComponentL(CharRef, EAnd);
       
  1299 		NewComponentL(CharRef2, EExact, _L("&#x") );
       
  1300 		NewComponentL(root, CharRef2, KHexCharRefValue);
       
  1301 	CBNFNode& CharRef1 = NewComponentL(CharRef, EAnd);
       
  1302 		NewComponentL(CharRef1, EExact, _L("&#") );
       
  1303 		NewComponentL(root, CharRef1, KDecCharRefValue);
       
  1304 
       
  1305 	// XML specs rule [67]
       
  1306 	// [67] Reference ::= EntityRef | CharRef
       
  1307 	CBNFNode& Reference = NewRuleL(root, KReference, EOr, NULL, NULL, NULL);
       
  1308 	NewComponentL(root, Reference, KEntityRef);
       
  1309 	NewComponentL(root, Reference, KCharRef);
       
  1310 
       
  1311 	// XML specs rule [68]
       
  1312 	// [68] EntityRef ::= '&' Name ';'
       
  1313 	CBNFNode& EntityRef = NewRuleL(root, KEntityRef, EAnd, NULL, MarkCallback, PostEntityRefL);
       
  1314 	NewComponentL(EntityRef, EExact, _L("&") );
       
  1315 	NewComponentL(root, EntityRef, KName);
       
  1316 	NewComponentL(EntityRef, EExact, _L(";") );
       
  1317 
       
  1318 	// XML specs rule [75]
       
  1319 	// [75] ExternalID ::= 'SYSTEM' S SystemLiteral  | 'PUBLIC' S PubidLiteral S SystemLiteral
       
  1320 	CBNFNode& ExternalID = NewRuleL(root, KExternalID, EOr, NULL, PreExternalID, NULL);
       
  1321 	CBNFNode& ExternalID1 = NewComponentL(ExternalID, EAnd);
       
  1322 		NewComponentL(ExternalID1, EExact, _L("SYSTEM") );
       
  1323 		NewComponentL(root, ExternalID1, KS);
       
  1324 		NewComponentL(root, ExternalID1, KSystemLiteral);
       
  1325 	CBNFNode& ExternalID2 = NewComponentL(ExternalID, EAnd);
       
  1326 		NewComponentL(ExternalID2, EExact, _L("PUBLIC") );
       
  1327 		NewComponentL(root, ExternalID2, KS);
       
  1328 		NewComponentL(root, ExternalID2, KPubidLiteral);
       
  1329 		NewComponentL(root, ExternalID2, KS);
       
  1330 		NewComponentL(root, ExternalID2, KSystemLiteral);
       
  1331 
       
  1332 	_STRING(EncName);
       
  1333 	// XML specs rule [80]
       
  1334 	// [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" )
       
  1335 	CBNFNode& EncodingDecl = NewRuleL(root, KEncodingDecl, EAnd, NULL, NULL, NULL );
       
  1336 	NewComponentL(root, EncodingDecl, KS);
       
  1337 	NewComponentL(EncodingDecl, EExact, _L("encoding") );
       
  1338 	NewComponentL(root, EncodingDecl, KEq);
       
  1339 	CBNFNode& EncodingDecl4 = NewComponentL(EncodingDecl, EOr);
       
  1340 		CBNFNode& EncodingDecl41 = NewComponentL(EncodingDecl4, EAnd);
       
  1341 			NewComponentL(root, EncodingDecl41, KdoubleQuote);
       
  1342 			NewComponentL(root, EncodingDecl41, KEncName);
       
  1343 			NewComponentL(root, EncodingDecl41, KdoubleQuote);
       
  1344 		CBNFNode& EncodingDecl42 = NewComponentL(EncodingDecl4, EAnd);
       
  1345 			NewComponentL(root, EncodingDecl42, KsingleQuote);
       
  1346 			NewComponentL(root, EncodingDecl42, KEncName);
       
  1347 			NewComponentL(root, EncodingDecl42, KsingleQuote);
       
  1348 
       
  1349 	// XML specs rule [81]
       
  1350 	// [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')* 
       
  1351 	CBNFNode& EncName = NewRuleL(root, KEncName, EAnd, NULL, NULL, NULL);
       
  1352 	NewComponentL(root, EncName, KLatinChar);
       
  1353 	CBNFNode& EncName2 = NewComponentL(EncName, ENMore);
       
  1354 		CBNFNode& EncName21 = NewComponentL(EncName2, EOr);
       
  1355 			NewComponentL(root, EncName21, KLatinChar);
       
  1356 			NewComponentL(root, EncName21, KNumber);
       
  1357 			NewComponentL(EncName21, ESelect, _L("-._") );
       
  1358 
       
  1359 	// A modified Letter rule
       
  1360 	NewXmlRuleL(root, KLetter, ELetter);
       
  1361 
       
  1362 	CleanupStack::Pop();
       
  1363 	__XML_LOG_RETURN;
       
  1364 	return(root);
       
  1365 	}
       
  1366 
       
  1367 TBool CXmlParser::PerformRuleL(CBNFNode& aRule, CFragmentedString::TStringMatch& aMatched)
       
  1368 // Overriden perform rule method to implement our own rule types
       
  1369 	{
       
  1370     TBool performedMatch;
       
  1371     switch (aRule.Type())
       
  1372         {
       
  1373 	case EChar:
       
  1374 		performedMatch = CharL(aMatched);
       
  1375 		break;
       
  1376 	case ELetter:
       
  1377 		performedMatch = LetterL(aMatched);
       
  1378 		break;
       
  1379 	case ES:
       
  1380 		performedMatch = SL(aMatched);
       
  1381 		break;
       
  1382 	case EFirstNameChar:
       
  1383 		performedMatch = FirstNameCharL(aMatched);
       
  1384 		break;
       
  1385 	case ENMoreNameChar:
       
  1386 		performedMatch = NMoreNameCharL(aMatched);
       
  1387 		break;
       
  1388     default:
       
  1389 		performedMatch = CBNFParser::PerformRuleL(aRule, aMatched);
       
  1390 		break;
       
  1391         }
       
  1392     return performedMatch;
       
  1393     }
       
  1394 
       
  1395 TBool CXmlParser::CharL(CFragmentedString::TStringMatch& aMatched)
       
  1396 // Implementation of the Char rule as its own type of rule
       
  1397 // [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD]
       
  1398     {
       
  1399 	aMatched = iString.MatchRange(0x20, 0xD7FF);
       
  1400 	if( aMatched == CFragmentedString::EMatch)
       
  1401 		{
       
  1402 		iString.ConsumeMatched();
       
  1403 		return ETrue;
       
  1404 		}
       
  1405 	else if( aMatched == CFragmentedString::EInsufficientData )
       
  1406 		return ETrue;
       
  1407 
       
  1408 	aMatched = iString.MatchSelect(_L("\t\r\n"));
       
  1409 
       
  1410 	if( aMatched != CFragmentedString::EMatch )
       
  1411 		aMatched = iString.MatchRange(0xe000, 0xfffd);
       
  1412 
       
  1413 	if( aMatched == CFragmentedString::EMatch)
       
  1414 		iString.ConsumeMatched();
       
  1415 
       
  1416     return ETrue;
       
  1417     }
       
  1418 
       
  1419 TBool CXmlParser::LetterL(CFragmentedString::TStringMatch& aMatched)
       
  1420 // Implementation of the modified letter rule
       
  1421 // Letter ::= [0x41-0x5a] | [0x61-0x7a] | [0xc0-0xd6] | [0xd8-0xf6] | [0xf8-0xff] | [0x100-0xd7a3]
       
  1422     {
       
  1423 	TInt low[6] = {0x41, 0x61, 0xc0, 0xd8, 0xf8, 0x100};
       
  1424 	TInt high[6] = {0x5a, 0x7a, 0xd6, 0xf6, 0xff, 0xd7a3};
       
  1425 	TInt i;
       
  1426 	for(i=0; i<6; ++i)
       
  1427 		{
       
  1428 		aMatched = iString.MatchRange(low[i], high[i]);
       
  1429 		if( aMatched == CFragmentedString::EMatch )
       
  1430 			{
       
  1431 			iString.ConsumeMatched();
       
  1432 			break;
       
  1433 			}
       
  1434 		else if( aMatched == CFragmentedString::EInsufficientData )
       
  1435 			break;
       
  1436 		}
       
  1437 
       
  1438     return ETrue;
       
  1439     }
       
  1440 
       
  1441 _LIT(KWhiteSpace," \t\n\r");
       
  1442 TBool CXmlParser::SL(CFragmentedString::TStringMatch& aMatched)
       
  1443 // Implementaion if the whitespace rule
       
  1444 // [3] S ::= (#x20 | #x9 | #xD | #xA)+
       
  1445 	{
       
  1446 	TBool foundWhiteSpace = EFalse;
       
  1447 	aMatched = iString.MatchSelect(KWhiteSpace());
       
  1448 	if( aMatched == CFragmentedString::EMatch )
       
  1449 		foundWhiteSpace = ETrue;
       
  1450 	while( aMatched == CFragmentedString::EMatch )
       
  1451 		{
       
  1452 		aMatched = iString.MatchSelect(KWhiteSpace());
       
  1453 		if( aMatched == CFragmentedString::EMatch)
       
  1454 			iString.ConsumeMatched();
       
  1455 		}
       
  1456 	if( foundWhiteSpace )
       
  1457 		{
       
  1458 		aMatched = CFragmentedString::EMatch;
       
  1459 		}
       
  1460 
       
  1461 	return ETrue;;
       
  1462 	}
       
  1463 
       
  1464 TBool CXmlParser::FirstNameCharL(CFragmentedString::TStringMatch& aMatched)
       
  1465 // Additional rule to speed up the check of the validity of the first
       
  1466 // character for a Name
       
  1467 // FirstNameChar ::= Letter | [_:]
       
  1468 	{
       
  1469 	LetterL(aMatched);
       
  1470 	if( aMatched == CFragmentedString::EInsufficientData )
       
  1471 		return ETrue;
       
  1472 	else if( aMatched != CFragmentedString::EMatch )
       
  1473 		aMatched = iString.MatchSelect(_L("_:"));
       
  1474 
       
  1475 	if( aMatched == CFragmentedString::EMatch )
       
  1476 		iString.ConsumeMatched();
       
  1477 
       
  1478 	return ETrue;
       
  1479 	}
       
  1480 
       
  1481 TBool CXmlParser::NMoreNameCharL(CFragmentedString::TStringMatch& aMatched)
       
  1482 // Implementation of zero or more name characters rule
       
  1483 // NMoreNameChar ::= (Letter | [0-9] | [.-_:\x000B7])*
       
  1484 	{
       
  1485 	aMatched = CFragmentedString::EMatch;
       
  1486 	while( aMatched == CFragmentedString::EMatch )
       
  1487 		{
       
  1488 		LetterL(aMatched);
       
  1489 		if( aMatched == CFragmentedString::EInsufficientData )
       
  1490 			return ETrue;
       
  1491 		else if( aMatched != CFragmentedString::EMatch )
       
  1492 			aMatched = iString.MatchRange('0', '9');
       
  1493 
       
  1494 		if( aMatched != CFragmentedString::EMatch )
       
  1495 			aMatched = iString.MatchSelect(_L(".-_:\x00B7"));
       
  1496 
       
  1497 		if( aMatched == CFragmentedString::EMatch )
       
  1498 			iString.ConsumeMatched();
       
  1499 		}
       
  1500 
       
  1501 	// We return every time EMatch, since if we are here trying to match this
       
  1502 	// rule the first character already matched and even if we don't the name
       
  1503 	// is still valid.
       
  1504 	aMatched = CFragmentedString::EMatch;
       
  1505 
       
  1506 	return ETrue;
       
  1507 	}
       
  1508 
       
  1509 //
       
  1510 //	UTILITY FUNCTIONS
       
  1511 //
       
  1512 
       
  1513 void CXmlParser::CharRefReplacement(TPtr& aString)
       
  1514 // A method to replace character references to the given string with the referenced character
       
  1515 // This method does minimal set of checks since when this method is called the string has
       
  1516 // already been parsed and hence the references it contains are valid (this is ensured by the
       
  1517 // reference parsing rules). Therefore, this method should be called just before the data
       
  1518 // is being attached as an attribute value or as CDATA to a node. The reason why we don't replace
       
  1519 // the values during the parsing (i.e. when the values are checked) is that if the rule would
       
  1520 // later fail and the string would be re-parsed then the replaced characters might cause
       
  1521 // errorneous situations and unintended references to appear.
       
  1522 	{
       
  1523 	__XML_LOG_ENTER(_L("CXmlParser::CharRefReplacement()"));
       
  1524 	_LIT(KCharRefMatchingPattern, "*&#*;*");
       
  1525 
       
  1526 	TPtrC examinable = aString;
       
  1527 	TInt examinableOffset = 0;
       
  1528 	TInt referenceOffset = examinable.Match(KCharRefMatchingPattern);
       
  1529 	while( referenceOffset != KErrNotFound )
       
  1530 		{
       
  1531 		TPtrC reference(examinable.Mid(referenceOffset));
       
  1532 		TInt referenceValueOffset = 2;
       
  1533 		TRadix system = EDecimal;
       
  1534 		if( reference[2] == 'x' )
       
  1535 			{
       
  1536 			referenceValueOffset++;
       
  1537 			system = EHex;
       
  1538 			}
       
  1539 		TLex valueString(reference.Mid(referenceValueOffset, reference.Locate(';')-referenceValueOffset) );
       
  1540 		TUint16 referenceValue = 32;	// just in case something fails, we shall insert space
       
  1541 		valueString.Val(referenceValue, system);
       
  1542 		aString.Delete(examinableOffset+referenceOffset, reference.Locate(';') );
       
  1543 		aString[examinableOffset+referenceOffset] = referenceValue;
       
  1544 
       
  1545 		examinable.Set(aString.Mid(examinableOffset+referenceOffset+1));
       
  1546 		examinableOffset += referenceOffset+1;
       
  1547 		referenceOffset = examinable.Match(KCharRefMatchingPattern);
       
  1548 		}
       
  1549 	__XML_LOG_RETURN;
       
  1550 	} 
       
  1551 
       
  1552 void CXmlParser::EolNormalization(TPtr aString)
       
  1553 // End-of-Line -normalization
       
  1554 // Changes 0xD chars to 0xA, combination of 0xD,0xA is reduced to 0xA
       
  1555 	{
       
  1556 	__XML_LOG_ENTER(_L("CXmlParser::EolNormalization()"));
       
  1557 	TInt offset;
       
  1558 	for( offset = aString.Locate(0xD); offset != KErrNotFound; offset=aString.Locate(0xD) )
       
  1559 		{
       
  1560 		if( aString.Length() > offset+1 && 
       
  1561 			aString[offset+1] == 0xA )
       
  1562 			{
       
  1563 			aString.Delete(offset,1);
       
  1564 			}
       
  1565 		else
       
  1566 			{
       
  1567 			aString[offset] = 0xA;
       
  1568 			}
       
  1569 		}
       
  1570 	__XML_LOG_RETURN;
       
  1571 	}
       
  1572 
       
  1573 CBNFNode& CXmlParser::NewXmlRuleL(CBNFNode* aRootRule, const TDesC& aRuleName, TXmlParserNodeTypes aRuleType)
       
  1574 	{
       
  1575 	CBNFNode& newRule = NewRuleL(aRootRule, aRuleName, EAnd, NULL, NULL, NULL);
       
  1576 	newRule.SetType(aRuleType);
       
  1577 	return newRule;
       
  1578 	}
       
  1579 
       
  1580 CBNFNode&  CXmlParser::NewXmlRuleL(CBNFNode* aRootRule, const TDesC& aRuleName, TXmlParserNodeTypes aRuleType, HBufC* aData, TRuleCallback* aPreRule, TRuleCallback* aPostRule)
       
  1581 	{
       
  1582 	CBNFNode& newRule = NewRuleL(aRootRule, aRuleName, EAnd, aData, aPreRule, aPostRule);
       
  1583 	newRule.SetType(aRuleType);
       
  1584 	return newRule;
       
  1585 	}