在前一篇文章(在asp.net atlas中调用web service——创建mashup调用远端web service(基础知识以及简单示例))中,我介绍了一些atlas中对远程web service进行mashup的基础知识,并给出了一个最基础的没有丝毫用处例子。今天再回到这个话题上,我将给出一个更复杂点的,但有一些用处的例子——yahoo! weather。
废话到此为止,让我们先熟悉一下yahoo! weather服务:yahoo!在其网站上提供了天气预报服务(http://weather.yahoo.com/),并且它也提供了web service的接口(http://developer.yahoo.com/weather/)
从上面两个网页上面,我们可以知道yahoo!提供的天气service的url为http://xml.weather.yahoo.com/forecastrss,该服务还有两个参数:
p:要查询天气的地点代码(可以在http://weather.yahoo.com/查询到不同地方的这个代码)。
u:返回结果中温度的单位,f代表华氏度,c代表摄氏度。
看来这个yahoo! weather服务还挺简单的,让我们测试下好不好用。先到http://weather.yahoo.com/查出来上海的地点代码为chxx0116。然后在浏览器中输入http://xml.weather.yahoo.com/forecastrss?p=chxx0116&u=c,嗯,返回了如下的一段不是很复杂的xml:
yahoo weather service xml result
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#">
<channel>
<title>yahoo! weather - shanghai, ch</title> <link>http://us.rd.yahoo.com/dailynews/rss/weather/shanghai__ch/*http://xml.weather.yahoo.com/forecast/chxx0116_c.html</link>
<description>yahoo! weather for shanghai, ch</description>
<language>en-us</language>
<lastbuilddate>thu, 25 may 2006 11:00 am cst</lastbuilddate>
<ttl>60</ttl>
<yweather:location city="shanghai" region="" country="ch" />
<yweather:units temperature="c" distance="km" pressure="mb" speed="kph" />
<yweather:wind chill="21" direction="260" speed="14" />
<yweather:atmosphere humidity="78" visibility="299" pressure="0" rising="0" />
<yweather:astronomy sunrise="4:52 am" sunset="6:50 pm" />
<image>
<title>yahoo! weather</title>
<width>142</width>
<height>18</height>
<link>http://weather.yahoo.com/</link>
<url>/uploadpic/2007-7/200777192443790.gif</url>
</image>
<item>
<title>conditions for shanghai, ch at 11:00 am cst</title>
<geo:lat>31.17</geo:lat>
<geo:long>121.43</geo:long> <link>http://us.rd.yahoo.com/dailynews/rss/weather/shanghai__ch/*http://xml.weather.yahoo.com/forecast/chxx0116_c.html</link>
<pubdate>thu, 25 may 2006 11:00 am cst</pubdate>
<yweather:condition text="fog" code="20" temp="21" date="thu, 25 may 2006 11:00 am cst" />
<description>
<![cdata[
<img src="/uploadpic/2007-7/200777192443883.gif" /><br />
<b>current conditions:</b><br />
fog, 21 c<br /><br />
<b>forecast:</b><br />
thu - scattered thunderstorms. high: 25 low: 20<br />
fri - am showers. high: 26 low: 18<br />
<br />
<a href="http://us.rd.yahoo.com/dailynews/rss/weather/shanghai__ch/*http://xml.weather.yahoo.com/forecast/chxx0116_c.html">full forecast at yahoo! weather</a><br/>
(provided by the weather channel)<br/>
]]>
</description>
<yweather:forecast day="thu" date="25 may 2006" low="20" high="25" text="scattered thunderstorms" code="38" />
<yweather:forecast day="fri" date="26 may 2006" low="18" high="26" text="am showers" code="39" />
<guid ispermalink="false">chxx0116_2006_05_25_11_0_cst</guid>
</item>
</channel>
</rss>
<!-- p1.weather.scd.yahoo.com uncompressed/chunked thu may 25 20:49:07 pdt 2006 -->
我们可以看到,它提供的信息非常全面(连日出日落时间都有……),下面让我们书写asbx bridge页面来对这个service进行mashup。
首先,参考在asp.net atlas中调用web service——创建mashup调用远端web service(基础知识以及简单示例)这篇文章中的那个asbx的声明,我们可以写出如下一段:
<?xml version="1.0" encoding="utf-8" ?>
<bridge namespace="dflying" classname="yahooweatherservice">
<proxy type="microsoft.web.services.bridgerestproxy"
serviceurl="http://xml.weather.yahoo.com/forecastrss" />
<method name="getweather">
<input>
<parameter name="p" />
<parameter name="u" value="c" />
</input>
</method>
</bridge>
其中:<bridge>的namespace和classname属性以及<method>的name属性让我们在客户端javascript中可以通过dflying.yahooweatherservice.getweather()这样的方法签名来访问这个mashup。 <proxy>的serviceurl属性指定了yahoo! weather service的url。
getweather方法中定义了上面列出来的p和u两个参数,其中u参数我们指定了它的默认值为c(代表摄氏度),p参数将由调用者负责传过来。
写到这一步其实也够了,客户端将收到上面浏览器中看到的那一段xml string,并且可以在客户端进行处理并显示。但客户端对xml的处理并不是那么容易,也不是那么高效,同时通过网络传输太多不必要的信息也是一种浪费。所以这里我们利用asbx中内建的transformer对这段xml处理一下,提取出我们感兴趣的内容并以json的形式发给客户端。在<method>段中加入下面一段:
<transforms>
<transform type="microsoft.web.services.xpathbridgetransformer">
<data>
<attribute name="selector" value="channel" />
<dictionary name="namespacemapping">
<item name="yweather" value="http://xml.weather.yahoo.com/ns/rss/1.0" />
</dictionary>
<dictionary name="selectednodes">
<item name="title" value="title" />
<item name="description" value="item/description" />
<item name="currentcondition" value="item/yweather:condition/@text" />
</dictionary>
</data>
</transform>
</transforms>
其中<transforms>声明表示这个mashup方法的返回值将会被一些transformer改变一下,里面声明了一个类型为microsoft.web.services.xpathbridgetransformer的transformer,表示将用xpath表达式来转换。在这个xpathbridgetransformer中要声明如下部分:
name为selector的一个attribute段,其中指定的value属性为一个xpath表达式,将选取整个xpathbridgetransformer将用到的数据段。
name为namespacemapping的一个dictionary段,其中指定了这个xml文件中的namespace映射。如果在下面的选择节点过程中我们用到了某个namespace,那么这里就必须有它的声明。这里我们在其中添加一个对yweather的映射,因为下面要用到。
name为selectednodes的一个dictionary段,其中每一个item的value属性是一个xpath string,用来从xml中选择出相应的值,name属性用来指定相应的在javascript中的属性名称。这里作为示例,我只取得其中三段内容,您可以看到,其中currentcondition的xpath中用到了上面指定的namespacemapping。
关于xpath的知识,我就不多讲了,感兴趣或是不太熟悉的朋友可以自行google,网上资源很多。关于其他类型的transformer,我也不是很熟悉,今后如果遇到了我再讲讲。完成后的yahooweatherbridge.asbx文件如下:
<?xml version="1.0" encoding="utf-8" ?>
<bridge namespace="dflying" classname="yahooweatherservice">
<proxy type="microsoft.web.services.bridgerestproxy"
serviceurl="http://xml.weather.yahoo.com/forecastrss" />
<method name="getweather">
<input>
<parameter name="p" />
<parameter name="u" value="c" />
</input>
<transforms>
<transform type="microsoft.web.services.xpathbridgetransformer">
<data>
<attribute name="selector" value="channel" />
<dictionary name="namespacemapping">
<item name="yweather" value="http://xml.weather.yahoo.com/ns/rss/1.0" />
</dictionary>
<dictionary name="selectednodes">
<item name="title" value="title" />
<item name="description" value="item/description" />
<item name="currentcondition" value="item/yweather:condition/@text" />
</dictionary>
</data>
</transform>
</transforms>
</method>
</bridge>
现在创建一个asp.net page测试一下,首先依然是重复了一千遍的scriptmanager,还有对bridge的引用:
<atlas:scriptmanager id="sm" runat="server">
<services>
<atlas:servicereference path="yahooweatherbridge.asbx" />
</services>
</atlas:scriptmanager>
然后一个html select元素,里面列入了几个城市以及相应的城市代码:
<!-- place selector -->
<select id="place">
<option selected="selected" value="chxx0116">shanghai, ch</option>
<option value="usca0746">mountain view, ca</option>
<option value="chxx0008">beijing, ch</option>
</select>
一个html button,用来触发对service的调用:
<!-- invoke the service -->
<input id="getweather" type="button" value="get weather" />
一段html用来显示结果:
<!-- display result -->
<div id="result" >
<div >title</div>
<div id="title"></div>
<div >description</div>
<div id="description"></div>
</div>
然后是javascript,可以看到通过dflying.yahooweatherservice.getweather()调用了mashup,并在方法返回后把经过transform的值输出到了页面上:
function getweather_onclick() {
// new atlas 'select' control
var place = new sys.ui.select($('place'));
// invoke the bridge method
dflying.yahooweatherservice.getweather({'p': place.get_selectedvalue()}, ongetcomplete);
}
function ongetcomplete(result) {
$('result').style.display = "block";
$('title').innerhtml = result[0].title;
$('description').innerhtml = result[0].description;
}
新闻热点
疑难解答
图片精选