Symbian學(xué)習(xí)筆記(15)
網(wǎng)上也有這方面的資料,建議參考:
http://wiki.forum.nokia.com/index.php/How_to_parse_XML_file_using_CParser_class
不過(guò),要注意的是Symbian中的CParser是基于SAX方式來(lái)解析的也就是說(shuō)它是基于事件流方式,對(duì)于SAX,如果做過(guò)JAVA開(kāi)發(fā)的一般不會(huì)陌生了。與DOM相比SAX方式在操作上會(huì)有點(diǎn)麻煩而且顯得沒(méi)那么好理解。
簡(jiǎn)要比較一下吧,DOM是將XML在內(nèi)存中展開(kāi)成一個(gè)樹(shù)的模型,我們可以方便地訪問(wèn)它的每個(gè)子節(jié)點(diǎn),可讀可寫(xiě)。但是SAX呢?我們只能通過(guò)一個(gè)單向文本流去解析XML,在過(guò)程中有多個(gè)事件回調(diào)(開(kāi)始某個(gè)元素處理、結(jié)束某個(gè)元素處理等等),它是單向只讀的。
下面我們來(lái)詳細(xì)說(shuō)明一下如何實(shí)現(xiàn)吧。
首先,我們建立一個(gè)解析器派生于CActive,由它負(fù)責(zé)整個(gè)解析過(guò)程(因?yàn)檫@是一個(gè)異步操作)。
#include <xmlcontenthandler.h>
using namespace Xml;
class MXMLHandlerObserver
...{
public:
virtual void OnParseCompleted( TInt aError ) = 0;
};
class CXMLActiveParser : public CActive ...{
public:
~CXMLActiveParser();
static CXMLActiveParser* NewL(MXMLHandlerObserver& aObserver,MContentHandler& aHandler);
static CXMLActiveParser* NewLC(MXMLHandlerObserver& aObserver,MContentHandler& aHandler);
public:
void StartL(const TDesC& aFileName);
private:
CXMLActiveParser(MXMLHandlerObserver& aObserver,MContentHandler& aHandler);
void ConstructL();
private:
void RunL();
void DoCancel();
TInt RunError(TInt aError);
private:
CParser* iParser;
HBufC8* iBuffer;
RFile iFile;
MContentHandler *iHandler;
MXMLHandlerObserver *iObserver;
RFs iFs;
};
除了CActive所必需的東西以外,我們?cè)黾恿?iParser 成員負(fù)責(zé)解析,iBuffer保存文件內(nèi)容以供給iParser去解析,而iHandler是SAX所特有的回調(diào)處理類(后面詳述),iObserver 則是自定義的一個(gè)接口,其實(shí)是一個(gè)Notifer,就是在解析完成后調(diào)用它的OnParseCompleted方法。
實(shí)現(xiàn)的部分主要功能在Construct、Start和Run三個(gè)函數(shù)中:
CActiveScheduler::Add( this); // Add to scheduler
iParser = CParser::NewL( KXmlMimeType, *iHandler );
iFs.Connect();
}
void CXMLActiveParser::StartL(const TDesC& aFileName) ...{
Cancel();
User::LeaveIfError( iFile.Open( /**//*CCoeEnv::Static()->FsSession()*/iFs, aFileName,
EFileRead ) );
delete iBuffer;
iBuffer = 0;
iBuffer = HBufC8::NewL( KFileBufferSize );
TPtr8 bufferPtr( iBuffer->Des() );
iFile.Read( bufferPtr, KFileBufferSize, iStatus );
SetActive();
iParser->ParseBeginL();
}
void CXMLActiveParser::RunL() ...{
if ( KErrNone == iStatus.Int() )...{
if ( iBuffer->Length() == 0)...{
iParser->ParseEndL();
iFile.Close();
delete iBuffer;
iBuffer = 0;
iObserver->OnParseCompleted(KErrNone);
}
else ...{
iParser->ParseL( *iBuffer );
TPtr8 bufferPtr( iBuffer->Des() );
iFile.Read( bufferPtr, KFileBufferSize, iStatus );
SetActive();
}
}
else ...{
//error handler.
iObserver->OnParseCompleted(iStatus.Int());
}
}
注意CParser在NewL時(shí)告訴它文檔類型是 _LIT8( KXmlMimeType, "text/xml" ) ,以及它需要的回調(diào)處理器是iHandler。然后在StartL時(shí)讀入XML文件,準(zhǔn)備解析。在RunL中如果未完成則開(kāi)始解析,真到完成后則調(diào)用 iObserver的onParseCompleted通知觀察者“我處理完了,請(qǐng)拿走結(jié)果吧”。
【編輯推薦】