Symbian学习笔记(18) - 初探Web Services API 的使用(中)

继续刚才的,现在来看具体代码,先是ConnectL的实现:

void CWebEngine::ConnectL()

	{

		CSenXmlServiceDescription* pattern = CSenXmlServiceDescription::NewLC();	

		pattern->SetFrameworkIdL(KDefaultBasicWebServicesFrameworkID);

		pattern->SetEndPointL(KWSEndPoint);

		delete iConnection;

		iConnection = NULL;

		iConnection = CSenServiceConnection::NewL(*this, *pattern);

		CleanupStack::PopAndDestroy(pattern); 

	}

这里注意一点与那个AddressBook例子不同的是我们声明了不同框架类型是KDefaultBasicWebServicesFrameworkID,并且这样只需要提供EndPoint而不需要Contract了。KWSEndPoint的值是在CPP前声明了:_LIT8(KWSEndPoint,"http://192.168.0.201/uim/PService.asmx");

CSenServiceConnection::NewL的两个参数,一是自己(即MSenServiceConsumer)负责处理回调,二是一个CSenXmlServiceDescription负责参数配置。

在回调SetStatus中我只是简单地打印出状态值。

再看那个SayHello的实现吧,在这个函数中要负责封装SOAP消息包,这时我才遇到了使用Symbian的WebServiceAPI烦人的问题:原来这个SOAP包要自己封装啊!同样SOAP的结果也要自己去解析!!

void CWebEngine::SayHello()

	{

		if(iConnectionState==1){

			//send 

			CSenSoapEnvelope  *env = CSenSoapEnvelope::NewL();

			CleanupStack::PushL(env);

			

			env->SetSoapActionL(KWSContract);	

			env->BodyL().AddElementL(KWSNamespace,KWSHelloworld);

			iConnection->SendL(*env);

			

			CleanupStack::PopAndDestroy(env);

		}

	}

好在HelloWorld不需要参数,所以这个SOAP请求还算简单,注意这个SetSoapActionL函数它的KWSContract就是那个"urn:pservice:helloworld" (见上篇中的SOAP请求描述)。因为CSenSoapEnvelope同样派生于CSenBaseFragment,所以它的Body也可以增加下级节点,上面的代码很好理解。

一旦调用了iConnection->SendL以后,手机会弹出选择接入点,说明这里开始连接网络了,得到结果后,我们回调HandleMessageL中处理结果。

void CWebEngine::HandleMessageL(const TDesC8& aMessage)

	{

		RDebug::Printf("===================HandleMessageL");

		LOG_ALL(aMessage);

		SetReader(*iXmlReader);

		ParseL(aMessage);

	}

这里我们将得到的结果(完整的SOAP响应的XML内容)交给iXmlReader去解析,于是此时又会涉及到另两个回调StartElement和EndElement。注意这里补充一下iXmlReader的初始化在WebEngine的ConstructL中完成:

void CWebEngine::ConstructL()

	{

		LOG_OPEN();

		CSenBaseFragment::BaseConstructL(KQueryResponseLocalName);

		iXmlReader = CSenXmlReader::NewL();

	}

两句话:一是因为自己是派生于CSenBaseFragment,所以先调用BaseConstructL构造一下自己是一个HelloWorldResponse标签的XML节点。二是构造出iXmlReader实例。

下面继续说解析XML的回调处理:

void CWebEngine::StartElementL(const TDesC8& aNsUri,    const TDesC8& aLocalName,   const TDesC8& aQName, const Xml::RAttributeArray& aAttrs)

{

RDebug::Printf("================StartElement");	 



_LIT(KFmt,"StartElement (%s)");

LOG_FORMAT((KFmt,aLocalName));

		 	

if(aLocalName==KQueryResponseLocalName){

		 		

delegate = CHelloWorldResult::NewL(aNsUri,aLocalName,aQName);

CleanupStack::PushL(delegate);

DelegateParsingL(*delegate);

CleanupStack::Pop(delegate);

}

 }

void CWebEngine::EndElementL(const TDesC8& aNsUri,  const TDesC8& aLocalName, const TDesC8& aQName)

 {

RDebug::Printf("==================EndElement");

_LIT(KFmt,"EndElement (%s)");

LOG_FORMAT((KFmt,aLocalName));

		 	

CSenBaseFragment::EndElementL(aNsUri, aLocalName, aQName);

 }

这个EndElement没啥好说的,就是调一下老子的EndElement罢了。倒是那个StartElement函数它在遇到HelloWorldResponse标签时会交给delegate去处理下级节点,就是说<HelloWorldResponse>以下的XML内容由CHelloWorldResult类的负责处理了。

阅读更多
换一批

没有更多推荐了,返回首页