engine/src/OpmlParser.cpp
changeset 2 29cda98b007e
child 7 a7a43293ae56
equal deleted inserted replaced
1:5f8e5adbbed9 2:29cda98b007e
       
     1 /*
       
     2 * Copyright (c) 2007-2010 Sebastian Brannstrom, Lars Persson, EmbedDev AB
       
     3 *
       
     4 * All rights reserved.
       
     5 * This component and the accompanying materials are made available
       
     6 * under the terms of the License "Eclipse Public License v1.0"
       
     7 * which accompanies this distribution, and is available
       
     8 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     9 *
       
    10 * Initial Contributors:
       
    11 * EmbedDev AB - initial contribution.
       
    12 *
       
    13 * Contributors:
       
    14 *
       
    15 * Description:
       
    16 *
       
    17 */
       
    18 
       
    19 #include "OpmlParser.h"
       
    20 #include "debug.h"
       
    21 #include <f32file.h>
       
    22 #include <bautils.h>
       
    23 #include <s32file.h>
       
    24 #include <charconv.h>
       
    25 #include <xml/stringdictionarycollection.h>
       
    26 #include <utf.h>
       
    27 
       
    28 using namespace Xml;
       
    29 const TInt KMaxParseBuffer = 2048;
       
    30 const TInt KMaxStringBuffer = 1024;
       
    31 COpmlParser::COpmlParser(CFeedEngine& aFeedEngine, RFs& aFs) : iFeedEngine(aFeedEngine),iFs(aFs)
       
    32 {	
       
    33 }
       
    34 
       
    35 COpmlParser::~COpmlParser()
       
    36 {	
       
    37 }
       
    38 
       
    39 void COpmlParser::ParseOpmlL(const TFileName &feedFileName, TBool aSearching)
       
    40 	{
       
    41 	DP1("ParseOpmlL BEGIN: %S", &feedFileName);
       
    42 	
       
    43 	iSearching = aSearching;
       
    44 	_LIT8(KXmlMimeType, "text/xml");
       
    45 	// Contruct the parser object
       
    46 	CParser* parser = CParser::NewLC(KXmlMimeType, *this);
       
    47 	iOpmlState = EStateOpmlRoot;
       
    48 	iEncoding = EUtf8;
       
    49 	iNumFeedsAdded = 0;
       
    50 	ParseL(*parser, iFs, feedFileName);
       
    51 
       
    52 	CleanupStack::PopAndDestroy(parser);	
       
    53 	//DP("ParseFeedL END");
       
    54 	}
       
    55 
       
    56 // from MContentHandler
       
    57 void COpmlParser::OnStartDocumentL(const RDocumentParameters& aDocParam, TInt /*aErrorCode*/)
       
    58 	{
       
    59 	DP("OnStartDocumentL()");
       
    60 	HBufC* charset = HBufC::NewLC(KMaxParseBuffer);
       
    61 	charset->Des().Copy(aDocParam.CharacterSetName().DesC());
       
    62 	iEncoding = EUtf8;
       
    63 	if (charset->CompareF(_L("utf-8")) == 0) {
       
    64 		DP("setting UTF8");
       
    65 		iEncoding = EUtf8;
       
    66 	} else if (charset->CompareF(_L("ISO-8859-1")) == 0) {
       
    67 		iEncoding = EUtf8; //Latin1;
       
    68 	} else {
       
    69 		DP1("unknown charset: %S", &charset);
       
    70 	}
       
    71 	CleanupStack::PopAndDestroy(charset);
       
    72 	}
       
    73 
       
    74 void COpmlParser::OnEndDocumentL(TInt /*aErrorCode*/)
       
    75 	{
       
    76 	iFeedEngine.OpmlParsingComplete(iNumFeedsAdded);
       
    77 	//DP("OnEndDocumentL()");
       
    78 	}
       
    79 
       
    80 void COpmlParser::OnStartElementL(const RTagInfo& aElement, const RAttributeArray& aAttributes, TInt /*aErrorCode*/)
       
    81 	{
       
    82 	TBuf<KMaxStringBuffer> str;
       
    83 	str.Copy(aElement.LocalName().DesC());
       
    84 	DP2("OnStartElementL START state=%d, element=%S", iOpmlState, &str);
       
    85 	iBuffer.Zero();
       
    86 	switch (iOpmlState) {
       
    87 	case EStateOpmlRoot:
       
    88 		// <body>
       
    89 		if (str.CompareF(KTagBody) == 0) {
       
    90 			iOpmlState = EStateOpmlBody;
       
    91 		}
       
    92 		break;
       
    93 	case EStateOpmlBody:
       
    94 		// <body> <outline>
       
    95 		
       
    96 		if(str.CompareF(KTagOutline) == 0) {
       
    97 			iOpmlState = EStateOpmlOutline;
       
    98 		}
       
    99 		break;
       
   100 	case EStateOpmlOutline:
       
   101 		// <body> <outline> <outline...
       
   102 		if(str.CompareF(KTagOutline) == 0) {
       
   103 			iOpmlState=EStateOpmlOutlineOutline;
       
   104 			CFeedInfo* newFeed = CFeedInfo::NewLC();
       
   105 			
       
   106 			TBool hasTitle = EFalse;
       
   107 			TBool hasUrl = EFalse;
       
   108 			
       
   109 			for (int i=0;i<aAttributes.Count();i++) {
       
   110 				RAttribute attr = aAttributes[i];
       
   111 				TBuf<KMaxStringBuffer> attr16;
       
   112 				attr16.Copy(attr.Attribute().LocalName().DesC().Left(KMaxStringBuffer));
       
   113 				HBufC* val16 = CnvUtfConverter::ConvertToUnicodeFromUtf8L(
       
   114 						attr.Value().DesC().Left(KMaxParseBuffer));
       
   115 				CleanupStack::PushL(val16);
       
   116 				
       
   117 				// xmlUrl=...
       
   118 				if (attr16.Compare(KTagXmlUrl) == 0 || attr16.Compare(KTagUrl) == 0) {
       
   119 					newFeed->SetUrlL(*val16);
       
   120 					hasUrl = ETrue;			
       
   121 				// htmlUrl
       
   122 				} else if (attr16.Compare(KTagHtmlUrl) == 0) {
       
   123 					newFeed->SetLinkL(*val16);
       
   124 					hasUrl = ETrue;
       
   125 				// text=...
       
   126 				} else if (attr16.Compare(KTagTitle) == 0) {
       
   127 					newFeed->SetTitleL(*val16);
       
   128 					newFeed->SetCustomTitle();
       
   129 					hasTitle = ETrue;
       
   130 				// description=
       
   131 				} else if (attr16.Compare(KTagDescription) == 0) {
       
   132 					newFeed->SetDescriptionL(*val16);
       
   133 				} else if (attr16.Compare(KTagText) == 0) {
       
   134 					if (!hasTitle) {
       
   135 						newFeed->SetTitleL(*val16);
       
   136 						newFeed->SetCustomTitle();
       
   137 						hasTitle = ETrue;
       
   138 					}
       
   139 				} 
       
   140 				CleanupStack::PopAndDestroy(val16);
       
   141 			}
       
   142 
       
   143 			if (!hasUrl) {
       
   144 				break;
       
   145 			}
       
   146 			
       
   147 			if (!hasTitle) {
       
   148 				newFeed->SetTitleL(newFeed->Url());
       
   149 			}
       
   150 			
       
   151 			if (iSearching) {
       
   152 				iFeedEngine.AddSearchResultL(newFeed);
       
   153 				CleanupStack::Pop(newFeed);
       
   154 			} else {
       
   155 				iFeedEngine.AddFeedL(*newFeed);
       
   156 				CleanupStack::PopAndDestroy(newFeed);
       
   157 				iNumFeedsAdded++;
       
   158 			}
       
   159 		}
       
   160 		break;
       
   161 	default:
       
   162 		DP2("Ignoring tag %S when in state %d", &str, iOpmlState);
       
   163 		break;
       
   164 	}
       
   165 	DP1("OnStartElementL END state=%d", iOpmlState);
       
   166 	}
       
   167 
       
   168 void COpmlParser::OnEndElementL(const RTagInfo& aElement, TInt /*aErrorCode*/)
       
   169 	{
       
   170 	
       
   171 	TDesC8 lName = aElement.LocalName().DesC();
       
   172 	TBuf<KMaxStringBuffer> str;
       
   173 	str.Copy(aElement.LocalName().DesC());
       
   174 
       
   175 	DP2("OnEndElementL START state=%d, element=%S", iOpmlState, &str);
       
   176 
       
   177 	switch (iOpmlState) {
       
   178 		case EStateOpmlOutlineOutline:
       
   179 			iOpmlState=EStateOpmlOutline;
       
   180 			break;
       
   181 		case EStateOpmlOutline:
       
   182 			iOpmlState=EStateOpmlBody;
       
   183 			break;
       
   184 		case EStateOpmlBody:
       
   185 			iOpmlState = EStateOpmlRoot;
       
   186 			break;
       
   187 		default:
       
   188 			// fall back to body level when in doubt
       
   189 			iOpmlState = EStateOpmlBody;
       
   190 			//DP("Don't know how to handle end tag %S when in state %d"), &str, iFeedState);
       
   191 			break;
       
   192 	}
       
   193 
       
   194 	DP1("OnEndElementL END state=%d", iOpmlState);	
       
   195 	}
       
   196 
       
   197 void COpmlParser::OnContentL(const TDesC8& /*aBytes*/, TInt /*aErrorCode*/)
       
   198 	{
       
   199 	//DP("OnContentL()");
       
   200 	}
       
   201 
       
   202 void COpmlParser::OnStartPrefixMappingL(const RString& /*aPrefix*/, const RString& /*aUri*/, TInt /*aErrorCode*/)
       
   203 	{
       
   204 	//DP("OnStartPrefixMappingL()");
       
   205 	}
       
   206 
       
   207 void COpmlParser::OnEndPrefixMappingL(const RString& /*aPrefix*/, TInt /*aErrorCode*/)
       
   208 	{
       
   209 	//DP("OnEndPrefixMappingL()");
       
   210 	}
       
   211 
       
   212 void COpmlParser::OnIgnorableWhiteSpaceL(const TDesC8& /*aBytes*/, TInt /*aErrorCode*/)
       
   213 	{
       
   214 	//DP("OnIgnorableWhiteSpaceL()");
       
   215 	}
       
   216 
       
   217 void COpmlParser::OnSkippedEntityL(const RString& /*aName*/, TInt /*aErrorCode*/)
       
   218 	{
       
   219 	//DP("OnSkippedEntityL()");
       
   220 	}
       
   221 
       
   222 void COpmlParser::OnProcessingInstructionL(const TDesC8& /*aTarget*/, const TDesC8& /*aData*/, TInt /*aErrorCode*/)
       
   223 	{
       
   224 	//DP("OnProcessingInstructionL()");
       
   225 	}
       
   226 
       
   227 void COpmlParser::OnError(TInt aErrorCode)
       
   228 	{
       
   229 	DP1("COpmlParser::OnError %d", aErrorCode);
       
   230 	iFeedEngine.OpmlParsingComplete(iNumFeedsAdded);
       
   231 	}
       
   232 
       
   233 TAny* COpmlParser::GetExtendedInterface(const TInt32 /*aUid*/)
       
   234 	{
       
   235 	//DP("GetExtendedInterface()");
       
   236 	return NULL;
       
   237 	}