Před pár dny jsem se dostal do situace, kdy jsem potřeboval najít nějakou webovou službu, ze které bych získaval informace o aktuálním počasí. Webovou službu jsem bohužel nenašel a tak jsem se musel spokojit s RSS kanálem od yahoo weather. Tak jsem se pustil tedy do hraní s xml souborem a proto jsem neváhal využít LINQu ( konečně jsem se k němu aspoň trošku dostal :-) ). Díky LINQ jsem si potřebné data zjistil za chvilku a mohl přejít k závěrečné fázi, zobrazení aktuálního počasí na mapě. Nyní máte přehled o tom, s čím jsem si hrál a proto se na to už můžeme podívat detailněji:
Yahoo Weather:
základní URL adresa RSS kanálu je http://weather.yahooapis.com/forecastrss . K této adrese je možné připojit dva parametry:
- p pro specifikaci města
- u pro stupně (Fahrenheit(f) nebo Celsius(c) )
zašleme-li požadavek ve tvaru http://weather.yahooapis.com/forecastrss?p=EZX0009&u=c , odpovědí nám bude xml soubor ve kterém nalezneme potřebné informace o aktuálním počasí v Ostrava. Popíšu zde pouze elementy, které jsem využíbal. Ostatní informace naleznete na http://developer.yahoo.com/weather
- Channel elements
- yweather:location - obsahuje atributy které popisují danou oblast
- city - název města
- region - stát (v USA), oblast, region
- country - 2 znakový kód země
- yweather:astronomy - obsahuje atributy popisující východ a západ slunce
- sunrise - východ slunce
- sunset - západ slunce
- Item elements
- geo:lat - zeměpisná šířka
- geo:long - zeměpisná délka
- yweather:condition - obsahuje atributy popisující aktuální počasí
- text - textový popis počasí např. "jasno"
- code - číselný kód textové popisu počasí
- temp - aktuální teplota
- date - aktuální datum
- description - text + temp + url obrázku
Vytvořil jsem si tedy třídu City, která obsahuje pouze vlastnosti uchovávající požadované hodnoty o aktuálním počasí v daném městě
public class City
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string m_Description;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string m_Code;
public string Name { get; set; }
public string Region { get; set; }
public string Country { get; set; }
public string Sunrise { get; set; }
public string Sunset { get; set; }
public double Lat { get; set; }
public double Lon { get; set; }
public string ConditionText { get; set; }
public double Temp { get; set; }
public string Date { get; set; }
public string ImageSource { get; set; }
public string CurrentConditions { get; set; }
public string Code
{
get { return m_Code; }
set { m_Code = value; }
}
public string Description
{
set
{
m_Description = value;
string pom = m_Description.Remove(0, m_Description.IndexOf('"') + 1);
ImageSource = pom.Remove(pom.IndexOf('"'));
string currConditions = pom.Remove(0, m_Description.IndexOf("</b><br />"));
CurrentConditions = currConditions.Remove(currConditions.IndexOf("<BR />"));
}
}
}
a třídu Weather, ve které jsem využil již zmiňovaný LINQ to XML :-). Třída obsahuje "zatím" dvě metody
City GetWeatherByCity(string name)
Metodě předám url adresu konkrétního města (např. viz výše url pro Ostravu) a vytvořím si instanci třídy XDocument
XDocument xmlSource = XDocument.Load(name);
nesmím zapomenout na definici namespace, které xml využívá
XNamespace yweather = "http://xml.weather.yahoo.com/ns/rss/1.0";
XNamespace geo = "http://www.w3.org/2003/01/geo/wgs84_pos#";
nyní můžu provést dotaz na xml soubor a všechny potřebné hodnoty si držím v mém anonymním tyou, který jsem si vytvořil v konstrukci příkazu select
var elements = xmlSource.Descendants("channel").Select(delegate(XElement c)
{
return new
{
city = c.Element((XName) (yweather + "location")).Attribute("city").Value,
region = c.Element((XName) (yweather + "location")).Attribute("region").Value,
country = c.Element((XName) (yweather + "location")).Attribute("country").Value,
sunrise = c.Element((XName) (yweather + "astronomy")).Attribute("sunrise").Value,
sunset = c.Element((XName) (yweather + "astronomy")).Attribute("sunset").Value,
lat = c.Element("item").Element((XName) (geo + "lat")).Value,
lon = c.Element("item").Element((XName) (geo + "long")).Value,
conditionText =
c.Element("item").Element((XName) (yweather + "condition")).Attribute("text").Value,
code = c.Element("item").Element((XName) (yweather + "condition")).Attribute("code").Value,
temp = c.Element("item").Element((XName) (yweather + "condition")).Attribute("temp").Value,
date = c.Element("item").Element((XName) (yweather + "condition")).Attribute("date").Value,
description = new XCData(c.Element("item").Element("description").Value)
};
});
poté jednoduše projdu "elements", naplním vlastnosti třídy City a vrátím výsledek
foreach (var c in elements)
{
city = new City
{
Name = c.city,
Region = c.region,
Country = c.country,
Sunrise = c.sunrise,
Sunset = c.sunset,
Lat = c.lat,
Lon = c.lon,
ConditionText = c.conditionText,
Code = c.code,
Temp = c.temp,
Date = c.date,
Description = c.description
};
}
public List<City> GetWeatherInCities(Dictionary<string, string> cities)
{
List<City> list = new List<City>();
foreach (KeyValuePair<string, string> city in cities)
{
list.Add(this.GetWeatherByCity(city.Value));
}
return list;
}
Nyní si už stačí vytvořit pouze jednoduchou stránku, na které si aktuální počasí zobrazíme. Do hlavičky stránky přidáme tyto řádky
<script type="text/javascript" src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6"></script> - virtual earth
<script type="text/javascript" src="JScript.js"></script> - muj js
V metodě PageLoad, si vytvořím generický slovník, kde klíčem bude název města a hodnotou url adrea na yahoo weather. Takto vytvořený slovník předám jako parametr již známé metodě GetWeatherInCities. Výsledkem bude list, který si poté projdu v cyklu foreach a základní informace o počasí v daném městě zobrazím v "pomocném" listboxu
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
weather = new YahooWeatherRssLibrary.Weather();
cities = new Dictionary<string, string>();
cities.Add("Opava", @"http://weather.yahooapis.com/forecastrss?p=EZXX0008&u=c");
cities.Add("Ostrava", @"http://weather.yahooapis.com/forecastrss?p=EZXX0009&u=c");
cities.Add("Praha", @"http://weather.yahooapis.com/forecastrss?p=EZXX0012&u=c");
cities.Add("Brno", @"http://weather.yahooapis.com/forecastrss?p=EZXX0002&u=c");
cities.Add("Karvina", @"http://weather.yahooapis.com/forecastrss?p=EZXX0005&u=c");
cities.Add("Kladno", @"http://weather.yahooapis.com/forecastrss?p=EZXX0006&u=c");
cities.Add("Cheb", @"http://weather.yahooapis.com/forecastrss?p=EZXX0017&u=c");
cities.Add("Liberec", @"http://weather.yahooapis.com/forecastrss?p=EZXX0023&u=c");
cities.Add("Pribyslav", @"http://weather.yahooapis.com/forecastrss?p=EZXX0025&u=c");
cities.Add("Plzen", @"http://weather.yahooapis.com/forecastrss?p=EZXX0010&u=c");
cities.Add("Tabor", @"http://weather.yahooapis.com/forecastrss?p=EZXX0015&u=c");
foreach (City c in weather.GetWeatherInCities(cities))
{
this.ListBox1.Items.Add(string.Format("{0}|{1}|{2}|{3}|{4}",
c.Name, c.CurrentConditions, c.Lat, c.Lon, c.ImageSource));
}
}
}
V sekci Body, mám ovšem ještě definovanou JS funkci, která se provede rovněž při "onLoad" a vypadá následovně:
function GetMap()
{
map = new VEMap('myMap'); // vytvořím si instanci pojmenovanou myMap
map.LoadMap(new VELatLong(50.11001070896013, 14.567871093749987), 6 ,'h' ,false); // zavolám metodu LoadMap, které předám konkrétní parametry, nejdůležitější jsou souřadnice (VELatLon), které zobrazí ve středu mapy město Praha
map.SetMapStyle(VEMapStyle.Aerial); // styl mapy nastavím na letecký pohled
map.HideDashboard(); // a zneviditelním navigační panel
}
Na mé stránce se nachází ještě tlačítko "Show weather" s definovanou událostí onclick="Add('ListBox1')":
function Add(ListBox)
{
var lb = document.getElementById(ListBox);
var i = 0;
while(lb
!= null)
{
// v cyklu si projdu jednotlivé položky v listboxu a jejich textovou hodnotu rozdělím podle znaku " | ", poté zavolám metodu AddPushpin s příslušnými parametry
var pom = lb
.outerText.split('|');
AddPushpin(pom[0], pom[1], pom[2], pom[3], pom[4]);
i++;
}
}function AddPushpin(title, description, lat, lon, img)
{
var shape = new VEShape(VEShapeType.Pushpin, new VELatLong(lat, lon)); // vytvořím si nový tvar s parametrem pushpin (chci označit pouze jediné místo) a s parametry lat a lon, které jsou parametry metody
shape.SetTitle(title); // nastavím titul na název města
shape.SetDescription(description); // popisem bude aktuální počasí
shape.SetCustomIcon(img); // lze nastavit i vlastní ikonu, proto využiju tuto možnost a jako ikonu volím obrázek získaný z yahoo weather
map.AddShape(shape); // přidám nový tvar na mapu
}
Tak a to je vše, třeba se to někomu bude hodit :-) Nejsou to nějaké převratné věci, ale jak říkám, v dlouhých nudných večerech jsem si pouze hrál :-) Na to jak to funguje se můžete podívat zde http://lucas.aspone.cz/Weather.aspx