您的位置:首页 > 其它

Symbian学习笔记(16) - 解析XML文件(下)

2008-04-23 16:55 531 查看
继续,刚才发表时出错,打开一看是别的人文章了!又白写了,晕……刚才的思路没了,重新来过吧。

书接上回,这篇介绍那个MContentHandler的实现,这是SAX解析方法的核心所在。

先看看我要解析的XML文件如下所示,其实很简单,因为它除了Element和Attribute以外没有其它东西了。


<?xml version="1.0" encoding="utf-8" ?>


<channels>


<channel id="10" title="时政" >


<content id="1001" title="广东牛奶中毒事件污染源调查结果1周后公布"/>


<content id="1002" title="河南淅川公安局因儿童被拐案设'局耻日'"/>


<content id="1003" title="深圳大学135名师生感染病毒引发腹泻"/>


</channel>


<channel id="11" title="国际">


<content id="1101" title="巴以将于4月7日恢复领导人级和谈"/>


<content id="1102" title="古巴解除长期禁令允许国民入住涉外酒店"/>


<content id="1103" title="联合国决定继续对刚果(金)实行武器禁运"/>


<content id="1104" title="俄拒绝接受美国进攻性战略武器问题建议"/>


</channel>


<channel id="12" title="财经">


<content id="1201" title="大飞机公司拟定名中国商用飞机有限公司"/>


<content id="1202" title="大部制新部委定编制方案6月底前上报"/>


</channel>


</channels>

我们的解析处理器的声明如下:


#include <xmlcontenthandler.h>


#include <xmldocumentparameters.h>




using namespace Xml;




class TNewsChannel




...{


public:


TInt id;


HBufC16 * title;


};




class TNewsContent




...{


public:


TInt id;


TInt pid;


HBufC16 * title;


};






class CChannelXmlHandler : public MContentHandler ...{


public:


// Constructors and destructor


~CChannelXmlHandler();


static CChannelXmlHandler* NewL();


static CChannelXmlHandler* NewLC();




RArray<TNewsChannel>* GetChannels();


RArray<TNewsContent>* GetContents();


TInt GetContent(TInt pid,TInt index);


TInt ContentCount(TInt pid);




private:




CChannelXmlHandler();


void ConstructL();




private: // from MContentHandler




void OnStartDocumentL( const RDocumentParameters &aDocParam,


TInt aErrorCode );




void OnEndDocumentL( TInt aErrorCode );




void OnStartElementL( const RTagInfo &aElement,


const RAttributeArray &aAttributes, TInt aErrorCode );




void OnEndElementL( const RTagInfo &aElement, TInt aErrorCode );




void OnContentL( const TDesC8 &aBytes, TInt aErrorCode );




// ... ...




private:


TInt iCurPID;


RArray<TNewsChannel> iChannels;


RArray<TNewsContent> iContents;




};

大多数是MContentHandler所声明的方法,这就是SAX事件解析模式的关键了,我们只需要在这些方法中做相应的处理即可。

除此之外,iChannels和iContents是我们定义了用来保存解析结果的成员,它的类型是RArray,关于RArray可以参考我的别一篇笔记:http://blog.csdn.net/sharetop/archive/2008/03/21/2203450.aspx

因为我们的XML比较简单,所以在CPP中只要处理OnStartElementL就可以了:


void CChannelXmlHandler::OnStartElementL( const Xml::RTagInfo &aElement,


const Xml::RAttributeArray &aAttributes, TInt aErrorCode )




...{




if(aElement.LocalName().DesC().Compare(KChannelName)==0)...{


TNewsChannel chn;




for(TInt i=0;i<aAttributes.Count();i++)...{




if(aAttributes[i].Attribute().LocalName().DesC().Compare(KTitleName)==0)...{


chn.title=CnvUtfConverter::ConvertToUnicodeFromUtf8L(aAttributes[i].Value().DesC());


}




else if(aAttributes[i].Attribute().LocalName().DesC().Compare(KIdName)==0)...{


TLex8 lex;


lex.Assign(aAttributes[i].Value().DesC());


lex.Val(chn.id);


}


}


iChannels.Append(chn);


iCurPID=chn.id;


}




else if(aElement.LocalName().DesC().Compare(KContentName)==0)...{


TNewsContent cnt;


cnt.pid=iCurPID;




for(TInt i=0;i<aAttributes.Count();i++)...{




if(aAttributes[i].Attribute().LocalName().DesC().Compare(KIdName)==0)...{


TLex8 lex;


lex.Assign(aAttributes[i].Value().DesC());


lex.Val(cnt.id);


}




else if(aAttributes[i].Attribute().LocalName().DesC().Compare(KTitleName)==0)...{


cnt.title=CnvUtfConverter::ConvertToUnicodeFromUtf8L(aAttributes[i].Value().DesC());


}


}


iContents.Append(cnt);


}


}

这个回调会在解析器遇到元素头时进入,然后我们就可以根据传入的参数取到当前元素的信息,如元素名称、属性值等,将它们保存在我们定义的数据成员中以备将来使用即可。

在使用这个解析器的地方,比如我们的AppView负责解析XML文件,那它应该包含一个MContentHandler的成员,并且它实现接口MXMLHandlerObserver。

于是,这样启动解析过程:


iChannelHandler=CChannelXmlHandler::NewL();


iXmlParser=CXMLActiveParser::NewL(*this,*iChannelHandler);


iXmlParser->StartL(KChannelXMLFile);

然后在它的OnParseCompleted方法中去iChannelHandler中取出解析结果,展示出来或者随便怎么用了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: