Customize uma Página de Resultados do Google Maps com Google Mapplets

Crie uma Solução do Lado do Servidor e Cliente Utilizando RSS, XSLT, PHP, KML e JavaScript

Um Google Mapplet é um aplicativo executado dentro de uma página de resultados do Google Maps e permite que você inclua suas próprias informações customizadas, além do comportamento da página e do mapa. Neste tutorial, você vai gravar um Google Mapplet que utiliza o RSS feed Yahoo Weather para exibir a previsão do tempo local no Google Maps. Para demonstrar diferentes técnicas durante o uso da API do Google Mapplets, você vai implementar duas soluções. A primeira é no lado do cliente e utiliza RSS e JavaScript. A segunda é no lado do servidor e utiliza XSLT, PHP, KML e JavaScript.

Jake Miles, Senior Developer, Conde Nast

Photo of Jacob MilesJake Miles é um oficial de ligação técnico senior na Twistage, Inc que trabalha atualmente com aplicativos Facebook, Myspace e OpenSocial utilizando Java, PHP, Adobe Flex e JavaScript. Ele trabalha como desenvolvedor profissional há 10 anos e é um estudante ávido e curioso desde os 10 anos. Ele também leciona como voluntário.



Dave Wegman, CTO, Twistage

David Wegman é CTO na Twistage, um provedor de vídeos on-line. Além de codificação e gravação técnica, ele gosta de estudos sobre a usabilidade dos sistemas de software e de refatoração de código. Ele vive e trabalha em São Francisco.



21/Out/2008

Antes de Iniciar

Este tutorial destina-se a desenvolvedores de aplicativo da Web interessados em incluir informações customizadas e comportamento em uma página de resultado do Google Maps. É recomendado estar familiarizado com PHP, JavaScript e XSLT.

Sobre Este Tutorial

Acrônimos Usados Frequentemente

  • Ajax: Asynchronous JavaScript + XML
  • API: interface de programação de aplicativos
  • DOM: Document Object Model
  • HTML: Linguagem de Marcação de Hipertexto
  • HTTP: Hyper Text Transfer Protocol
  • KML: Keyhole Markup Language
  • PHP: PHP Hypertext Preprocessor
  • RSS: Really Simple Syndication
  • URL: Localizador Uniforme de Recursos
  • W3C: World Wide Web Consortium
  • XHTML: Extensible Hypertext Markup Language
  • XML: Linguagem de Marcação Extensível
  • XSL: Extensible Stylesheet Language
  • XSLT: Transformações XSL

Neste tutorial, você vai construir um Google Mapplet que exiba a previsão do tempo local utilizando RSS feed Yahoo Weather. Você vai chamar um serviço geocodificador reverso (consulte Pré-requisitos para obter um link) utilizando um pedido Ajax dentro da API do Google Mapplets, que converte as coordenadas atuais do Google Map em um CEP.

Você vai implementar duas soluções: uma que chama o serviço de estações do Yahoo do JavaScript e exibe a previsão do tempo na barra lateral, e outra que chama seu próprio servidor da Web remoto para uma sobreposição de KML a ser colocada no mapa. Seu servidor da Web remoto, executando PHP 5.2, vai utilizar o módulo XSL para aplicar folhas de estilo XSLT no RSS XML retornado do Yahoo. Você implementará duas folhas de estilo: uma que converta os dados de RSS do Yahoo em uma estrutura de dados mais simples, para demonstrar o isolamento de sua camada de apresentação (KML) da estrutura de dados externa, e outra para converter a estrutura de dados local mais simples em uma sobreposição de KML. Por fim, você vai aplicar a sobreposição no Google Map.

Pré-requisitos

Você vai precisar das seguintes ferramentas para prosseguir com este tutorial:

  • O desenvolvimento de um Google Mapplet requer que você o mantenha em um servidor da Web público para que o Google possa ler o Mapplet em seu cache para renderizar a página de resultados do Google Maps. Além disso, você precisa acessar um servidor da Web público para este tutorial. Apache Web Server Versão 2.2 é um servidor da Web que vai funcionar. Consulte Recursos para obter informações sobre definição e configuração.
  • PHP Versão 5.2.6.
  • O serviço geocodificador reverso de geonames.org.
  • Um navegador da Web com JavaScript ativado.
  • Seu editor de linguagem de programação favorito.

Compondo o Mapplet no PHP

Primeiro você vai criar o Google Mapplet em si, compondo-o com PHP e incluindo-o na conta do Google para poder desenvolvê-lo e visualizar o comportamento em seu navegador. Um Google Mapplet é uma especificação de gadget do Google especializada, portanto, a primeira etapa é gerar esse gadget do Google. Nesta seção, você vai compor o gadget utilizando PHP, separar o gadget XML e sua seção CDATA em arquivos diferentes e dividir a seção CDATA em um arquivo HTML e em um arquivo JavaScript para manter as linguagens separadas para facilitar a edição.

Criando o Arquivo weather-mapplet.php em um Servidor Público

Para começar, crie o arquivo weather-mapplet.php na Listagem 1.

Listagem 1. weather-mapplet.php
<? echo('<?xml version="1.0" encoding="UTF-8"?>'); ?>
<Module>
  <ModulePrefs title="Local Weather Mapplet"
               description="Displays local weather on the map."
               author="Jake Miles"
               author_email="jake@jakemiles.com"
               height="150">
    <Require feature="sharedmap"/>
  </ModulePrefs>
  <Content type="html"><![CDATA[

   <? include ('weather-mapplet-content.php'); ?>

]]></Content>

</Module>

A Listagem 1 cria uma especificação de gadget do mapplet (um Módulo) e especifica o título, a descrição, o autor, o endereço de e-mail do autor e a altura do mapplet. A tag <Require feature="sharedmap"> é necessária para uma especificação de mapplet. Isso requer que um mapa compartilhado (o Google Map) esteja disponível na página.

Refatorando HTML em um Arquivo PHP Diferente

O próximo elemento na Listagem 1, Conteúdo, especifica o conteúdo do mapplet dentro de um elemento CDATA. Em vez de tentar codificar o mapplet dentro de um elemento CDATA, o que é complicado na maioria dos editores, você pode refatorar o conteúdo HTML no weather-mapplet-content.php, como na Listagem 2.

Listagem 2. weather-mapplet-content.php
Ladies and jellyspoons, a previsão do tempo local...

<div>
  Units:
  <input id="units-english" type="radio" name="weather-units" checked> English
  <input id="units-metric" type="radio" name="weather-units"> Metric
</div>

<div>
  Result behavior: <br/>
  <input id="results-simple" type="radio" name="result-type" checked>
Client-side  <br/>
  <input id="results-server-xslt" type="radio" name="result-type">
Server-side XSLT
</div>

<div id="message">

</div>

<script>
   <? include ('weather-mapplet-content.js'); ?>
   runMapplet();
</script>

Listagem 2 especifica o HTML que será carregando à esquerda da página de resultados do Google Maps (consulte Figura 1). Isso inclui um par de botões de opções para você selecionar o idioma inglês ou medida métricas nas informações sobre previsão do tempo, além de outro conjunto de botões de opções para você selecionar um caminho de implementação, já que neste tutorial você vai implementar duas soluções. A mensagem div da Listagem 2 será útil como um console de saída quando você depurar o código JavaScript e você vai utilizá-la para exibir o resumo da previsão do tempo no feed Yahoo Weather.

Figura 1. O Mapplet de Previsão do Tempo Local Final
The final local weather mapplet

Incluindo o JavaScript

O JavaScript em si é refatorado em um arquivo weather-mapplet-content.js para facilitar a edição e para manter diferentes tipos de códigos separados. O weather-mapplet-content.php inclui o arquivo JavaScript para que ele se torne um conteúdo sequencial quando renderizado (para manter a especificação do Google Gadget junto em uma URL que pode ser chamada), mas você ainda pode editar seu próprio arquivo.

Quando carregado, esse snippet HTML chama uma função Javascript runMapplet() (definida posteriormente em Desenvolvendo o Javascript) para iniciar a funcionalidade do mapplet. RunMapplet() existirá no weather-mapplet-content.js. O arquivo JavaScript inteiro é relativamente longo e você vai encontrá-lo no pacote de código de origem fornecido neste tutorial. A Listagem 3 mostra o início do arquivo JavaScript, incluído aqui para que você tenha todas as partes da string de inclusão do PHP para começar (você vai explorar esse arquivo, linha por linha, mais tarde neste tutorial).

Listagem 3. weather-mapplet-content.js
var map = new GMap2();
var mapCenter;

function runMapplet () {  .......

Agora você está pronto para incluir a URL do mapplet na página do Google Maps e visualizá-la neste formato nascente antes de prosseguir para codificar a funcionalidade. Isso permitirá que você construa a funcionalidade e depure-a na página.

A parte superior do weather-mapplet-content.js declara duas variáveis públicas, map e mapCenter, configurando map como uma nova instância de Gmap2. Gmap2 representa o Google Map na página. mapCenter armazenará as coordenadas do centro do mapa para uso posterior.


Incluindo o Mapplet no Google Maps

Neste ponto, você pode incluir seu mapplet na página do Google Maps e confirmar sua execução. Antes de fazer isso, você precisa instalar o Google Mapplets Developer Mapplet. Isso é necessário porque normalmente o Google armazena em cache o código do mapplet, o que significa que quaisquer mudanças feitas durante o desenvolvimento não aparecerão no mapplet se você apenas recarregar a página. O Developer Mapplet inclui um link de recarregamento em seu mapplet, permitindo que você limpe o cache do mapplet e o recarregue.

Instalando o Developer Mapplet

A próxima etapa é incluir o mapplet em sua conta do Google para poder vê-lo trabalhando conforme você o desenvolve. Para confirmar que quer incluí-lo (consulte Figura 2), acesse :

http://maps.google.com/ig/add?synd=mpl&pid=mpl&moduleurl=
http://www.google.com/ig/modules/geodeveloper.xml

Nota: Apenas para fins de formatação, a URL acima aparece em várias linhas. Quando você copiá-la em seu navegador, copie-a como uma única string de caracteres.

Figura 2. Incluindo o Google Mapplet Developer Mapplet
Adding the Google Mapplet Developer Mapplet

Clique em Incluir em Mapas para incluí-lo em sua conta.

Incluindo o Mapplet no Google Maps

Em seguida, você quer incluir o mapplet em sua conta do Google Maps. Acesse o diretório do Google Maps:

http://maps.google.com/ig/directory?synd=mpl&pid=mpl&features=
sharedmap,geofeed&backlink=http%3A%2F%2Fmaps.google.com%2Fmaps%2Fmm

Nota: Apenas para fins de formatação, a URL acima aparece em várias linhas. Quando você copiá-la em seu navegador, copie-a como uma única string de caracteres.

Clique em Incluir por URL (consulte Figura 3).

Figura 3. O Link Incluir por URL do Diretório do Google Maps
The Google Maps Directory's Add By URL link

Quando você clicar em Incluir por URL, você verá um prompt para a URL do mapplet que deseja incluir. Especifique a URL do weather-mapplet.php no servidor da Web público e clique em Incluir (consulte Figura 4).

Figura 4. Especificando a URL do Mapplet
Specifying your mapplet's URL

O Google avisará que você está incluindo um recurso na página do Google Maps que não foi criado pelo Google (consulte Figura 5).

Figura 5. Aviso do Google Quando Você Inclui um Mapplet de Terceiros
Google's warning when adding a third-party mapplet

Clique em OK para incluir o mapplet e clique em Retornar ao Google Maps no canto superior esquerdo da página para retornar à página do Google Maps. Se você procurar um endereço e depois clicar em Meus Mapas nos resultados da procura, você verá o mapplet Mapplet Developer e o mapplet Local Weather à esquerda na lista de mapas (consulte Figura 6).

Figura 6. O Developer Mapplet e Seu Mapplet em Execução no Google Maps
The Developer Mapplet and your mapplet running in Google Maps

Desenvolvendo o JavaScript

A essência do mapplet será composta pelo JavaScript. Nesta seção, você vai iniciar o JavaScript para ter uma string de inclusão de PHP completa—a string de arquivos incluída para compor o resultado da URL. Um é a especificação do mapplet, o que está dentro dela é o HTML do mapplet e o que está dentro dela é o arquivo JavaScript. Após essas três partes estarem no lugar certo, você estará pronto para iniciar o desenvolvimento da funcionalidade do aplicativo.

Incluindo o runMapplet() de Função

Com o mapplet de estrutura sendo exibido na página de resultados do Google Maps, você pode continuar desenvolvendo o JavaScript para que ele faça algo de útil. Inclua a função runMapplet() no weather-mapplet-content.js, como na Listagem 4.

Listagem 4. runMapplet() (weather-mapplet-content.js)
function runMapplet () {
  GEvent.addListener(map, "moveend", function() {
    map.getCenterAsync (onGetCenter);
  });
}

Essa é a função chamada na tag <script> do conteúdo HTML do mapplet, o que significa que ela será chamada quando a página for carregada. RunMapplet() configura o mapplet para responder a eventos de mudança de local no mapa da página.

RunMapplet() não faz muita coisa diretamente com o mapa. Ela inclui um listener para o evento de mapa moveend, fornecendo um objeto de função que será chamado sempre que o mapa terminar de alterar seu local (por exemplo, quando o usuário arrastar o mapa com o mouse). Isso configura o evento que direcionará o restante do comportamento do mapplet. Muitas funções que você pode chamar na API do Google Maps têm que ser substituídas por chamadas para contrapartes assíncronas na API de Mapplets.

Chamando a Função getCenter()

A função de retorno de chamada em si obtém as coordenadas centrais do mapa como um objeto GLatLng que representa um par de latitude/longitude. A função de retorno de chamada é diferente do que seria em um componente de API do Google Maps direto. Uma chamada para getCenterAsync() na API de mapplets substitui aquilo que é uma chamada para getCenter() na API do Google Maps. A chamada para getCenterAsync() requer a função de retorno de chamada onGetCenter. A função onGetCenter() é chamada com as coordenadas centrais do mapa, ao contrário de uma chamada para getCenter(), que retorna as coordenadas diretamente.

Portanto, runMapplet() configura um listener para a movimentação do mapa, e sempre que o mapa terminar a movimentação, o listener perguntará ao mapa sobre seu par de latitude/longitude central, fornecendo onGetCenter como o retorno de chamada. onGetCenter (consulte Listagem 5) será chamada, portanto, com o novo centro do mapa sempre que o local central do mapa mudar.

Listagem 5. A Função onGetCenter()
function onGetCenter (center) {
  mapCenter = center;
  var reverseGeocoderUrl = createReverseGeocoderUrl (center);
  document.getElementById("message").innerHTML = 'Looking up zipcode from ' +
reverseGeocoderUrl;
  _IG_FetchXmlContent (reverseGeocoderUrl, onReverseGeocoderResult);
}

function createReverseGeocoderUrl(gLatLng) {
    return 'http://ws.geonames.org/findNearbyPostalCodes?lat=' + gLatLng.lat() +
'&lng=' + gLatLng.lng();
}

onGetCenter() é chamada com o objeto central GLatLng do mapa, representando suas coordenadas de latitude/longitude. Ela armazena o objeto GLatLng na variável global mapCenter, principalmente para evitar a repetição dessa chamada assíncrona se você precisar do centro do mapa mais tarde no JavaScript. Ela também configura o texto da mensagem div no mapplet para uma mensagem de status, demonstrando que você pode acessar os elementos HTML do mapplet a partir do JavaScript sem nenhum truque, mesmo que o mapplet seja executado dentro da página do Google Maps.

Convertendo o Centro do Mapa em um CEP

Embora o Google Map possa fornecer suas coordenadas centrais, o feed RSS Yahoo Weather requer um CEP, e o Google Map não fornece o CEP correspondente das coordenadas centrais. Portanto, para mapear de um para outro, você utilizará um serviço Geocodificador Reverso gratuito (consulte Pré-requisitos para obter um link), que aceita uma latitude e uma longitude e retorna o XML que descreve alguns CEPs próximos.

Após configurar a variável global mapCenter, onGetCenter() produz a URL do geocodificador reverso com a chamada para createReverseGeocoderUrl(), utilizando o objeto central GLatLng do mapa.

Para chamar essa URL, utilize a função de API do Google Maps _IG_FetchXmlContent, que carrega o conteúdo de uma URL e o analisa como XML, para produzir um objeto DOM. A chamada é assíncrona, portanto, você fornece uma função de retorno de chamada como com getCenterAsync(). Nesse caso, a função de retorno de chamada é onReverseGeocoderResult, como na Listagem 6.

Listagem 6. onReverseGeocoderResult
function onReverseGeocoderResult (data) {
    var zipcodes = data.getElementsByTagName("code");
    if (zipcodes.length == 0) {
      document.getElementById("message").innerHTML =
'No zipcode information available for the current map location.';
    } else {
      var firstCode = zipcodes[0];
      var postalCodeDom = firstCode.getElementsByTagName('postalcode')[0];
      var zipcode = postalCodeDom.textContent;
      onZipcodeObtained (zipcode);
    }
}

onReverseGeocoderResult é chamada com um objeto DOM representando os resultados de XML da chamada para o serviço geocodificador reverso. Você pode visualizar os resultados chamando o geocodificador reverso em seu navegador. Por exemplo, a chamada do geocodificador reverso,

http://ws.geonames.org/findNearbyPostalCodes?
lat=40.746135271984336&lng=-73.97892951965332

vai produzir o XML na Listagem 7 (abreviado aqui).

Nota: Apenas para fins de formatação, a URL acima aparece em várias linhas. Quando você copiá-la em seu navegador, copie-a como uma única string de caracteres.

Listagem 7. Um Exemplo do XML Retornado do Serviço Geocodificador Reverso Geonames.org
<geonames>
 <code>
   <postalcode>10016</postalcode>
   <name>NewYork</name>
   <countryCode>US</countryCode>
   <lat>40.746135271984336</lat>
   <lng>-73.97892951965332</lng>
   <adminCode1>NY</adminCode1>
   <adminName1>NewYork</adminName1>
   <adminCode2>061</adminCode2>
   <adminName2>NewYork</adminName2>
   <adminCode3/>
   <adminName3/>
   <distance>0.0</distance>
 </code>
 <code>
   <postalcode>10158</postalcode>
   <name>NewYork</name>
   <countryCode>US</countryCode>
   <lat>40.749435</lat>
   <lng>-73.9758</lng>

 ...

</geonames>

O XML contém informações de endereço estruturadas sobre CEPs próximos do par de latitude/longitude fornecido.

onReverseGeocoderResult recebe informações de resultado como um elemento DOM, por isso chama getTagsByElementName() nele, buscando todos os códigos nomeados por tags. Se o serviço não retornou nenhum CEP para o par de coordenadas, onReverseGeocoderResult() reportará isso na mensagem div do mapplet. Caso contrário, nesse caso, você será o único interessado em um CEP, e não em CEPs vizinhos, portanto, onReverseGeocoderResult() utilizará o primeiro elemento <code> no documento para consultar o elemento postalcode e obter seu valor textContent para ter o CEP como uma string. Ela então chama onZipcodeObtained() (consulte Listagem 8) com o CEP.

Listagem 8. onZipcodeObtained()
function onZipcodeObtained(zipcode) {
  var unitsEnglishRadio = document.getElementById('units-english');
  var units = unitsEnglishRadio.checked ? 'f' : 'c';
  var serverXsltRadio = document.getElementById('results-server-xslt');
  if (serverXsltRadio.checked) {
    fetchServerXsltResults(zipcode, units);
  } else {
    fetchYahooRss (zipcode, units);
  }
}

onZipcodeObtained() é chamada com o CEP correspondente ao centro do mapa. Ela vê qual botão de opções de unidade de medida é selecionado e qual caminho de funcionalidade é selecionado: XSLT do lado do cliente ou do lado do servidor. Se o caminho do lado do servidor for selecionado, ela chamará fetchServerXsltResults(); caso contrário, ela chamará fetchYahooRss(), passando o CEP e as unidades (f para Fahrenheit ou c para centígrado). fetchServerXsltResult() iniciará o caminho do lado do servidor, chamando o script PHP para uma sobreposição de KML, enquanto fetchYahooRss() chamará o RSS feed do Yahoo diretamente do JavaScript e exibirá seu resumo.


O Caminho do Lado do Cliente

No exemplo do Mapplet Local Weather, os dois botões de opções determinam qual caminho do comportamento executar: um que ocorra inteiramente no cliente e outro que ocorra principalmente no servidor. Nesta seção, você vai implementar o caminho do lado do cliente, que busca o RSS do Yahoo Weather e o exibe completamente no JavaScript.

Chamando o Serviço RSS do Yahoo Weather

A primeira etapa no caminho do lado do cliente é chamar o serviço RSS do Yahoo Weather através da chamada para fetchYahooRss(), cujo conteúdo aparece na Listagem 9.

Listagem 9. fetchYahooRss()
function fetchYahooRss(zipcode, units) {
  var yahooWeatherRssUrl = createYahooRssUrl(zipcode, units);
  _IG_FetchXmlContent (yahooWeatherRssUrl, onYahooWeatherRssResult);
}

function createYahooRssUrl(zipcode, units) {
    return 'http://weather.yahooapis.com/forecastrss?p=' + zipcode + '&u='
+ units;
}

fetchYahooRss() chama createYahooRssUrl, passando o CEP e o significador de unidades para criar a URL do RSS feed do Yahoo! Weather. Ela então utiliza a função do Google Maps _IG_FetchXmlContent para buscar assincronamente os resultados dessa URL, fornecendo onYahooWeatherRssResult como a função de retorno de chamada.

Para ver um resultado de amostra do RSS feed do Yahoo! Weather, acesse http://weather.yahooapis.com/forecastrss?p=10016&u=f em seu navegador e visualize a origem da página que conterá o XML com estrutura semelhante à Listagem 10.

Listagem 10. Resultado de Amostra do feed RSS do Yahoo! Weather
<?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 - New York, NY</title>
<link>http://us.rd.yahoo.com/dailynews/rss/weather/New_York__
   NY/*http://weather.yahoo.com/forecast/10016_f.html</link>
<description>Yahoo! Weather for New York, NY</description>
<language>en-us</language>
<lastBuildDate>Sun, 05 Oct 2008 7:51 pm EDT</lastBuildDate>
<ttl>60</ttl>
<yweather:location city="New York" region="NY"   country="US"/>

<yweather:units temperature="F" distance="mi" pressure="in" speed="mph"/>
<yweather:wind chill="56"   direction="60"   speed="3" />
<yweather:atmosphere humidity="90"  visibility="6"  pressure="30.28"
rising="1" />
<yweather:astronomy sunrise="6:57 am"   sunset="6:31 pm"/>
<image>
<title>Yahoo! Weather</title>
<width>142</width>
<height>18</height>
<link>http://weather.yahoo.com</link>
<url>http://l.yimg.com/us.yimg.com/i/us/nws/th/main_142b.gif</url>
</image>
<item>

<title>Conditions for New York, NY at 7:51 pm EDT</title>
<geo:lat>40.67</geo:lat>
<geo:long>-73.94</geo:long>
<link>http://us.rd.yahoo.com/dailynews/rss/weather/New_York__
NY/*http://weather.yahoo.com/forecast/10016_f.html</link>
<pubDate>Sun, 05 Oct 2008 7:51 pm EDT</pubDate>
<yweather:condition  text="Fair"  code="33"  temp="56"
date="Sun, 05 Oct 2008 7:51 pm EDT" />
<description><![CDATA[
<img src="http://l.yimg.com/us.yimg.com/i/us/we/52/33.gif"/><br />
<b>Current Conditions:</b><br />
Fair, 56 F<BR />
<BR /><b>Forecast:</b><BR />
Sun - Partly Cloudy. High: 64 Low: 51<br />
Mon - Partly Cloudy. High: 57 Low: 43<br />
<br />
<a href="http://us.rd.yahoo.com/dailynews/rss/weather/New_York__
NY/*http://weather.yahoo.com/forecast/USNY0996_f.html">Full Forecast at Yahoo!
Weather</a><BR/>
(provided by The Weather Channel)<br/>
]]></description>
<yweather:forecast day="Sun" date="5 Oct 2008" low="51" high="64"
    text="Partly Cloudy" code="29" />
<yweather:forecast day="Mon" date="6 Oct 2008" low="43" high="57"
   text="Partly Cloudy" code="30" />
<guid isPermaLink="false">10016_2008_10_05_19_51_EDT</guid>
</item>

</channel>
</rss><!-- api1.weather.ac4.yahoo.com compressed/chunked Sun Oct
5 17:23:56 PDT 2008 -->

A Listagem 10 contém informações, em formato RSS, contendo um elemento <channel> com um elemento <item> abaixo dele. Algumas das informações sobre a previsão do tempo local estão no nível <channel> e algumas estão no nível <item>. A estrutura dos dados se tornará mais importante quando você transformá-la utilizando XSLT posteriormente, mas por enquanto, os elementos importantes são <title> do elemento <channel> e <description> do elemento <item>.

Utilizando o Resultado do RSS do Yahoo

Quando a URL estiver completamente carregada, esse resultado de RSS será passado para a função de retorno de chamada onYahooWeatherRssResult como um objeto DOM, como na Listagem 11.

Listagem 11. onYahooWeatherRssResult()
function onYahooWeatherRssResult(xml) {
  var item = xml.getElementsByTagName('item')[0];
  var description = item.getElementsByTagName('description')[0];
  document.getElementById("message").innerHTML = description.textContent;
}

onYahooWeatherRssResult() localiza o elemento <item> no XML e localize seu elemento <description>. O elemento <description> é uma fácil renderização HTML de algumas das informações no feed de previsão do tempo e, por isso, agrupa seu conteúdo em um elemento CDATA, como na Listagem 12.

Listagem 12. O Elemento <description> no XML de Resultado do feed RSS do Yahoo! Weather
<description><![CDATA[
<img src="http://l.yimg.com/us.yimg.com/i/us/we/52/33.gif"/><br />
<b>Current Conditions:</b><br />
Fair, 56 F<BR />
<BR /><b>Forecast:</b><BR />
Sun - Partly Cloudy. High: 64 Low: 51<br />
Mon - Partly Cloudy. High: 57 Low: 43<br />
<br />
<a href="http://us.rd.yahoo.com/dailynews/rss/weather/New_York__
   NY/*http://weather.yahoo.com/forecast/USNY0996_f.html">Full Forecast at
   Yahoo! Weather</a><BR/>
(provided by The Weather Channel)<br/>
]]></description>

onYahooWeatherRssResult() configura o HTML interno da mensagem div para o conteúdo do elemento <description>, fornecendo um resumo rápido da previsão do tempo sob os controles do seu mapplet. Clique em Recarregar no mapplet para recarregar o mapplet no cache do Google. Depois arraste o mapa por alguns milímetros para disparar o evento moveend (que acionará o listener para configurar o mapplet em runMapplet() e acionará o mapplet para execução na sequência inteira novamente). Você verá o resumo da previsão do tempo do RSS feed exibido à esquerda do mapa, como na Figura 7.

Figura 7. Exibindo o Elemento <description> do feed RSS do Yahoo! Weather no Mapplet
Displaying the description element of the Yahoo! Weather RSS feed in the mapplet

Implementando o Caminho do Lado do Servidor

Agora que você explorou uma solução puramente do lado do cliente, na qual chamou o feed RSS do Yahoo, passou pelo DOM do XML resultante e exibiu o resumo do RSS no mapplet dentro do JavaScript, é hora de explorar uma solução do lado do servidor. Isso envolve o JavaScript chamando um script PHP em seu servidor da Web, que, por sua vez, chama um serviço do Yahoo e utiliza XSLT para converter o RSS em uma sobreposição de KML que o mapplet exibirá no mapa.

Criando o Script do PHP do Lado do Servidor

A funcionalidade do lado do servidor começa com um script do PHP chamado weather.php, que é responsável por retornar uma sobreposição de KML que representa a previsão do tempo atual. Primeiro crie weather.php, como na Listagem 13, e coloque-o em seu servidor da Web publicamente acessível.

Agora dirija sua atenção para o caminho de funcionalidade do lado do servidor, que é acionado quando você seleciona o botão de opções XSLT do Lado do Servidor no mapplet e altera o local do mapa. Isso chama fetchServerXsltResults(), como na Listagem 13.

Listagem 13. fetchServerXsltResults()
function fetchServerXsltResults(zipcode, units) {

  var kmlUrl = "http://YOUR-SERVER/weather.php?v=" + Math.round(Math.random()
* 10000000000);

  var kml = new GGeoXml(kmlUrl);
  map.addOverlay(kml);
}

O objetivo aqui é carregar um arquivo KML do servidor e fazer sua sobreposição no mapa. Portanto, primeiro essa função cria uma URL para chamar seu servidor para os dados do KML. O Google armazena em cache os arquivos KML, então, para garantir que o KML seja carregado do servidor todas as vezes, e não do cache do Google, fetchServerXsltResults() anexa um número aleatório entre 0 e 10000000000 à URL como um parâmetro de pedido simulado.

Ela cria um objeto GGeoXml com a URL. GGeoXML implementa a interface GOverlay, o que significa que você pode passá-la para Gmap2.addOverlay(). Ao contrário da API do Google Maps, a API de mapplets permite apenas o uso de classes GOverlay padrão, como GGeoXml, e não sua implementação GOverlay customizada. Para sobrepor os dados do KML no mapa, GGeoXml carrega um arquivo XML e chama addOverlay com ele.

Implementando a Funcionalidade do Lado do Servidor

Isso traz você para o lado do servidor da equação, onde você vai usar PHP e XSLT para transformar o feed RSS do Yahoo! Weather em um arquivo KML para sobreposição no Google Map. Continue criando weather.php, como na Listagem 14, e coloque-o em seu servidor da Web público.

Listagem 14. weather.php
<?php

require_once('yahoo-weather-rss.php');
require_once('XsltChainController.php');

if (! isset($_REQUEST['zipcode'])) {
  die ("zipcode request parameter required");
}

if (! isset($_REQUEST['units'])) {
  die ("units request parameter required - either c or f");
}

$weatherRss = readYahooWeatherRss ($_REQUEST['zipcode'], $_REQUEST['units']);

$controller = new XsltChainController
  (array ('yahoo-rss-to-simple-weather.xsl',
      'simple-weather-to-kml.xsl'),
   'CDATA_START', 'CDATA_END');

echo $controller->echoTransformedXml ($weatherRss, true, false);

?>

O arquivo weather.php produz um arquivo KML que o mapplet pode sobrepor no Google Map. Primeiro ele se certifica de que os parâmetros de pedido necessários estão presentes; você precisa de um CEP e de um significador de unidades (c ou f) para chamar o feed RSS do Yahoo. Depois ele chama readYahooWeatherRss(), passando esses parâmetros, e recebe de volta o XML do feed RSS do Yahoo Weather. Em seguida, ele cria uma instância de uma classe XsltChainController, especificando uma array de arquivos de folha de estilo XSLT para aplicar em sequência no documento XM. Ele também fornece XsltChainController com dois tokens, CDATA_START e CDATA_END. Esses tokens permitem que folhas de estilo produzam seções de CDATA, que folhas de estilo XSLT diferentes não podem produzir (você saberá mais sobre isso quando produzir as folhas de estilo XSLT). Por fim, o weather.php chama echoTransformedXml() de XsltChainController com o feed RSS e reproduz o XML resultante para a saída padrão.

Chamando o feed RSS do Yahoo Weather a partir do PHP

Agora que você tem um script de driver principal, crie yahoo-weather-rss.php como na Listagem 15.

Listagem 15. yahoo-weather-rss.php
<?php

require_once('readUrl.php');

define ('YAHOO_RSS_FEED', 'http://weather.yahooapis.com/forecastrss');

function readYahooWeatherRss ($zipcode, $units) {

  if ($zipcode == null) {
    throw new Exception ("No zipcode specified");
  }

  if ($units == null) {
    throw new Exception ("No units specified");
  }

  if (! (in_array($units, array('f', 'c')))) {
    throw new Exception ("Invalid units specified (can be 'c' or 'f'): $units");
  }

  return readUrl(YAHOO_RSS_FEED . "?p=$zipcode&u=$units");
}

?>

O arquivo yahoo-weather-rss.php é razoavelmente básico e fornece uma função única, readYahooWeatherRss(). readYahooWeatherRss() se certifica de que o CEP e os argumentos de unidades estejam corretos e, então, retorna o resultado da leitura do feed RSS do Yahoo Weather com esses argumentos. Para obter o resultado do feed RSS do Yahoo, chame uma função readUrl(), especificada na Listagem 16.

Listagem 16. readUrl.php
<?php

function readUrl($url) {
  if (ini_get('allow_url_fopen') == '1') {
    return readUrlWithFopen($url);
  }
  else if (function_exists('curl_init')) {
    return readUrlWithCurl($url);
  }
  else {
    throw new Exception ("readUrl: neither fopen url wrapppers nor
CURL support are enabled.");
  }
}

?>

O arquivo readUrl.php fornece uma função genérica que lê o conteúdo de uma URL, utilizando fopen ou CURL, dependendo de qual for possível na atual configuração do servidor. O método preferencial é utilizar fopen(). Se os wrappers HTTP fopen não estiverem ativados na instalação do PHP, que ele detecta verificando a configuração do arquivo ini 'allow_url_fopen' do PHP, eles tentarão ler utilizando CURL. Se CURL não estiver ativado também, que ele verifica checando a existência da função 'curl_init', a função emitirá uma Exceção porque não poderá continuar.

A Listagem 17 mostra a função readUrlWithFopen() que readUrl() chama se os wrappers HTTP fopen() estiverem ativados, então fopen() pode receber uma URL em vez de um caminho de arquivo local que ele lerá como um arquivo.

Listagem 17. readUrlWithFopen()
function readUrlWithFopen($url) {

  $contents = file_get_contents($url);

  if (! $contents) {
    throw new Exception ("readUrl: Couldn't read url: $url");
  }

  return $contents;
}

readUrlWithFopen() lê o conteúdo da URL utilizando a função file_get_contents(). Ela então se certifica de que a função realmente leu algo da URL e emite uma exceção, caso ainda não tenha feito isso. Se ela leu algo, ela retornará o conteúdo da URL.

A outra opção é readUrlWithCurl() na Listagem 18.

Listagem 18. readUrlWithCurl()
function readUrlWithCurl($url) {

  $ch = curl_init();
  try {

   curl_setopt($ch, CURLOPT_URL, $url);

   curl_setopt($ch, CURLOPT_HEADER, 0);

   curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

    $content = curl_exec($ch);
    curl_close($ch);
    return $content;

  } catch (Exception $e) {
    curl_close($ch);
    throw new Exception ("Couldn't read url using CURL: $e");
  }
}

readUrlWithCurl() cria um manipulador de CURL com curl_init(). Ela então configura a URL para a chamada, especifica o não retorno de cabeçalhos HTTP, e sim apenas do conteúdo da resposta, e especifica o retorno de conteúdo em vez de gravá-lo diretamente na saída padrão. Após as opções serem definidas, ela chama curl_exec() e curl_close() para ler e fecha o fluxo, conforme captura quaisquer exceções e se certifica de fechar o fluxo de CURL para evitar deixar recursos abertos.

A Mecânica da Conversão da Folha de Estilo XSLT Utilizando o Módulo XSL no PHP 5

Após o script recuperar o conteúdo do RSS feed do Yahoo Weather, ele pode convertê-lo em algo que possa ser usado prontamente. Para isso, ele criou uma instância de XsltChainController, introduzida na Listagem 19.

Listagem 19. XsltChainController
class XsltChainController {

  private $stylesheets;
  private $cdataStart;
  private $cdataEnd;

  public function __construct ($stylesheets, $cdataStart=null, $cdataEnd=null) {

    $this->stylesheets = $stylesheets;
    $this->cdataStart = $cdataStart;
    $this->cdataEnd = $cdataEnd;

    if ($cdataStart != null && $cdataEnd == null ||
    $cdataEnd != null && $cdataStart == null) {
      throw new Exception ("XsltChainController: if providing cdataStart or cdataEnd,
must provide both.  Only one provided.");
    }
  }

XsltChainController gerencia o aplicativo de uma sequência de folhas de estilo XSLT para um documento XML de origem. Seu construtor utiliza uma array dos caminhos de arquivo da folha de estilo e os argumentos $cdataStart e $cdataEnd opcionais. Eles especificam tokens que podem aparecer nas folhas de estilo para especificar onde seções de CDATA começam e terminam no XML resultante. Isso resolve o problema de que é impossível se incluir uma seção CDATA verdadeira (como em <![CDATA[...stuff...]]) na saída de uma folha de estilo XSLT se a folha de estilo tiver que produzir o corpo da seção CDATA através de transformações. Assim que o processador de XSLT vê a seção CDATA, ele escapa o conteúdo, ignorando os elementos XSLT na CDATA que devem produzir conteúdo transformado. A solução é inserir um token na folha de estilo XSLT onde a seção CDATA começa, e outro onde ela termina, e fazer o processador de fechamento substituir as verdadeiras tags inicial e final da CDATA após a conclusão do processamento do XSLT.

O construtor apenas configura o controlador. Em seguida, inclua uma função echoTransformedXml() para fazer o trabalho, como na Listagem 20.

Listagem 20. echoTransformedXml()
public function echoTransformedXml ($xml, $stripCdata=false) {

    if ($stripCdata) {
      $xml = $this->stripCdata($xml);
    }

    $transformedDom = $this->applyStylesheets ($xml);

    echo ($this->cdataStart
      ? $this->replaceCdataMarkers ($transformedDom->saveXML())
      : $transformedDom->saveXML());
  }

protected function stripCdata($xml) {
    return str_ireplace (array('<![CDATA[', ']]>'),
             array ('', ''),
             $xml);
  }

  protected function replaceCdataMarkers ($xml) {
    return str_ireplace (array ($this->cdataStart, $this->cdataEnd),
             array ('<![CDATA[', ']]>'),
             $xml);
  }

echoTransformedXml() utiliza o XML para transformar como uma string e um sinalizador especificando se você deve remover tags da CDATA no documento de origem. A razão para isso é que o documento de origem pode conter uma seção CDATA contendo XHTML que as folhas de estilo precisam acessar. No caso do feed RSS do Yahoo, o <description> do elemento <item>, a seção CDATA contendo um resumo em HTML da previsão do tempo, contém um ícone útil para as atuais condições da previsão do tempo. A folha de estilo não pode utilizar esse ícone se ela permanecer presa em um elemento da CDATA. Portanto, a primeira coisa que essa função faz é remover quaisquer marcadores <!CDATA[[ and ]] do documento de origem antes de aplicar a string de folhas de estilo chamando stripCdata(). Analogamente, se o construtor recebeu os tokens $cdataStart e $cdataEnd, echoTransformedXml() substituirá os marcadores inicial e final reais da CDATA após processar as folhas de estilo para permitir que as folhas de estilo produzam seções da CDATA próprias. Entre as duas etapas de manipulação de CDATA está a chamada para applyStylesheets, que transforma o XML, como na Listagem 21.

Listagem 21. XsltChainController.applyStylesheets()
protected function applyStylesheets ($xml) {
    $xmlDOM = DOMDocument::loadXML ($xml);
    foreach ($this->stylesheets as $stylesheet) {
      $xmlDOM = $this->applyStylesheet ($xmlDOM, $stylesheet);
    }
    return $xmlDOM;
  }

Primeiro, applyStylesheets() cria um objeto DOMDocument a partir da string do XML. Depois ela faz o loop da array dos caminhos de arquivo de folha de estilo fornecidos, chamando applyStylesheet() com cada um, passando no XML de origem ou no resultado da chamada anterior para applyStylesheet(), até que todas as folhas de estilo tenham sido aplicadas em sequência. A Listagem 22 mostra applyStylesheet(), que aplica uma única folha de estilo XSLT no objeto DOMDocument.

Listagem 22. XsltChainController.applyStylesheet()
protected function applyStylesheet ($xmlDOM, $xslFile) {

    $processor = new XSLTProcessor();

    $xslDOM = DOMDocument::load ($xslFile);

    $processor->importStyleSheet($xslDOM);

    return $processor->transformToDoc($xmlDOM);
  }

applyStylesheet() utiliza DOMDocument contendo o XML para transformar e o caminho de arquivo da folha de estilo XSLT para aplicar nele. Ela utiliza o módulo XSL no PHP 5 para executar a transformação. applyStylesheet() cria uma XSLTProcessor, cria uma DOMDocument a partir do caminho de arquivo da folha de estilo XSLT, importa DOMDocument da folha de estilo na XSLTProcessor e chama seu método transformToDoc(), transformando a origem DOMDocument em um objeto DOMDocument transformado, que é retornado.


Criando as Folhas de Estilo XSLT

Agora você tem a mecânica para aplicar folhas de estilo XSLT em documentos XML e você pode criar as folhas de estilo para transformar o RSS do Yahoo em KML para o Google Mapplet. Você vai aplicar duas folhas de estilo na sequência para o RSS do Yahoo. A primeira o transforma em uma estrutura de dados mais gerenciável e a segunda transforma essa estrutura de dados mais simples em KML final.

Utilizando XSLT para Simplificar a Estrutura de Dados

Como você viu na A Listagem 10, o feed RSS do Yahoo contém várias informações, e a estrutura é um pouco complexa para seus propósitos. Além disso, como ele vem de uma organização externa, o que pode alterar a estrutura dos dados a qualquer momento, sua conversão em uma estrutura de dados local mais simples o isola dessas mudanças. Você pode projetar o KML final sem levar em consideração a estrutura de dados do Yahoo, desde que tenha uma folha de estilo XSLT intermediária que possa converter o formato do Yahoo no formato local. Crie o início desta folha de estilo intermediária, yahoo-rss-to-simple-weather.xsl, como na Listagem 23.

Listagem 23. yahoo-rss-to-simple-weather.xsl
<xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
        xmlns:yweather="http://weather.yahooapis.com/ns/rss/1.0">

</xsl:stylesheet>

Isso cria o esqueleto da folha de estilo, especificando o espaço para nome XML para o XSLT com a linha xmlns:xsl, um namespace geo que ocorre no RSS feed do Yahoo e um namespace yweather que também ocorre no feed RSS. Sem os espaços de nomes definidos aqui, a folha de estilo não vai reconhecer os elementos nesses espaços de nomes.

Em seguida, inclua um modelo para correspondência no elemento <channel> do feed RSS como na Listagem 24.

Listagem 24. Modelo XSLT Correspondente a /rss/channel
<xsl:template match="/rss/channel">
    <weather>

      <data-source>
    <link><xsl:value-of select="link"/></link>
    <icon><xsl:value-of select="image/url"/></icon>
      </data-source>

      <xsl:apply-templates select="item/title"/>

      <xsl:apply-templates mode="coordinates"
               select="item"/>

      <xsl:apply-templates mode="condition-icon"
               select="item/description/img"/>

      <xsl:apply-templates mode="units"
               select="*[local-name()='units']"/>

      <xsl:apply-templates mode="condition"
               select="item/*[local-name()='condition']"/>

      <xsl:apply-templates mode="wind"
               select="*[local-name()='wind']"/>

      <xsl:apply-templates mode="atmosphere"
               select="*[local-name()='atmosphere']"/>

      <xsl:apply-templates mode="astronomy"
               select="*[local-name()='astronomy']"/>

    </weather>
  </xsl:template>

Esse modelo corresponde ao elemento /rss/channel e produz um elemento <weather> de nível superior no documento resultante. Ele cria um elemento <data-source> especificando a fonte de informações. O elemento <data-source> contém um <link> que especifica a URL da origem, cujo valor vem do elemento /rss/channel/link do documento de origem (um link para Yahoo Weather), e um elemento <icon>, que obtém seu valor do elemento /rss/channel/image/url, que contém um ícone para o Yahoo Weather. Depois ele aplica os modelos para inúmeros XPaths no documento de origem—primeiro o elemento /rss/channel/item/title e depois vários outros elementos de dados.

A diferença nesses outros aplicativos de modelo é que todos eles especificam um atributo mode. <xsl:apply-templates> utiliza um atributo select especificando o XPath dos nós para passar como argumentos no modelo e um atributo mode opcional. O atributo mode permite que você mude seu pensamento sobre modelos XSLT. Em vez de fornecer um atributo match específico para os modelos para especificar com o que eles correspondem, os modos permitem que você os trate mais como chamadas de função, pois um modo corresponderá melhor a um aplicativo modelo do que um sem um modo. Para manter simples as especificações de modelo, aqui cada chamada <xsl:apply-templates> especifica ambos os nós para passar para o modelo e o um modo. Se cada modelo na folha de estilo receber depois seu próprio modo, ele não terá que especificar também ao que corresponde —ele pode corresponder a um caractere asterisco (*). Por exemplo, a Listagem 25 mostra o modelo para o modo de coordenadas.

Listagem 25. Modelo para Modo de "Coordenadas"
<xsl:template mode="coordinates" match="*">
    <coordinates>
      <latitude><xsl:value-of select="geo:lat"/></latitude>
      <longitude><xsl:value-of select="geo:long"/></longitude>
    </coordinates>
  </xsl:template>

Como esse modelo especifica um modo, e corresponde a um asterisco (*), significando qualquer nó, se você chamar <xsl:apply-templates> com o modo desse modelo, corresponderá a esse modelo. Isso o transforma em uma chamada de função mais convencional e elimina a necessidade de especificar a expressão XPath à qual o modelo se aplica. Agora fica a critério do responsável pela chamada chamá-la com a expressão XPath correta (o que deve ser feito de qualquer maneira). Essa técnica simplifica a especificação de modelo e transforma modelos em funções. Ela também permite que você crie dois modelos que devem agir no mesmo tipo de nó, mas produzindo resultados diferentes. Por exemplo, o modelo de coordenadas aqui é chamado com o elemento <item> e produz um elemento <coordinates> a partir dos elementos <geo:lat> e <geo:long> do <item>. Você também pode definir outro modelo que seja chamado com o elemento <item>, mas que extraia informações diferentes dele.

Revendo a Listagem 24 para o modelo /rss/channel, você pode ver porque foi necessário remover os marcadores do elemento da CDATA do documento de origem. Um dos aplicativos de modelo é <xsl:apply-templates mode="condition-icon" select="item/description/img"/>. Isso chama o modelo condition-icon (o modelo com esse modo) com a tag <img> do <description> no RSS feed, que estava preso originalmente em um elemento da CDATA porque deveria ser literalmente uma saída. Ao remover os marcadores da CDATA, agora esse modelo pode acessar o elemento <img> como qualquer outro elemento XML no documento de origem.

Outro item de interesse na Listagem 24 é a chamada de modelo <xsl:apply-templates mode="units" select="*[local-name()='units']"/>. Ela chama o modelo com um modo de unidades, passando todos os nós cujo nome local, significando seu nome sem prefixo de namespace, são unidades. Essa é uma técnica para selecionar nós de outros espaços de nomes. No RSS feed do Yahoo, o elemento de unidades é realmente um elemento <yweather:units>. A função XPath local-name() retorna o nome do namespace do elemento sans de modo que você possa lidar com ele de forma mais simples. Essa técnica é repetida para os elementos de condição, atmosfera e astronomia no namespace yweather.

Os modelos para os modos unidades, condição, astronomia e atmosfera parecem os mesmos, criando um elemento no documento resultante e copiando os atributos do elemento de origem sobre ele, como no modelo para o modo de unidades (consulte Listagem 26).

Listagem 26. O Modelo para o Modo de Unidades
<xsl:template mode="units" match="*">
    <units>
      <xsl:copy-of select="@*"/>
    </units>
  </xsl:template>

Isso é chamado com o elemento <yweather:units>, produzindo um elemento <units> no documento resultante que contém todos os atributos do elemento de origem (consulte código de origem anexado para as outras definições de modelo semelhantes).

Convertendo a Estrutura de Dados Mais Simples em uma Sobreposição de KML

A primeira folha de estilo converteu o documento de RSS do Yahoo em uma estrutura de dados dominadora sobre a qual você tem controle. Após ser convertido para esse formato, o XML pode ser convertido em um documento KML. Para isso, crie uma folha de estilo chamada simple-weather-to-kml.xsl, como na Listagem 27.

Listagem 27. simple-weather-to-kml.xsl
<xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="/weather">
    <kml xmlns="http://earth.google.com/kml/2.2">
      <Document>
    <name><xsl:value-of  select="title"/></name>
    <description>Local Weather from Yahoo!</description>
    <Placemark>
      <name>Local Weather</name>
      <description>
        CDATA_START
        <xsl:apply-templates mode="placemark-description"
                 select="."/>
        CDATA_END
      </description>
      <xsl:apply-templates select="coordinates"/>
    </Placemark>
      </Document>
    </kml>
  </xsl:template>

</xsl:stylesheet>

Isso define o modelo correspondente ao elemento <weather> de nível-raiz, produzindo um elemento <kml> de nível-raiz. KML é um dialeto do XML que especifica informações geográficas, e que também pode especificar informações de sobreposição gráfica, como pontos, linhas e texto ou HTML para exibição no mapa. Você o utiliza aqui para criar uma sobreposição de informações de previsão do tempo para exibir na página de resultados do Google Maps. Um documento KML contém um elemento <Document>, que contém um <name>, <description> e, nesse caso, um ou mais elementos <Placemark>, sendo que cada um se torna um marcador que pode ser clicado no mapa. O documento também pode conter linhas para sobreposição no mapa, para desenhar polígonos preenchidos ou não.

Aqui você vê os tokens CDATA_START e CDATA_END que especificou na chamada para o construtor de XsltChainController. Eles denotam o início e o final de uma seção CDATA no documento resultante, mas essa folha de estilo não pode incluir os marcadores de CDATA em si, ou o processador XSLT vai ignorar o elemento <xsl:apply-templates> dentro da seção CDATA. A seção CDATA tem o conteúdo HTML que será exibido no balão pop-up da Marca do Local, criado no modelo com o modo placemark-description: na Listagem 28.

Listagem 28. O Modelo "placemark-description"
<xsl:template mode="placemark-description" match="*">
    <div>
      <div>
    <xsl:value-of select="condition/@text"/>,
    <xsl:value-of select="condition/@temp"/>
<xsl:value-of select="units/@temperature"/>
      </div>
      <div>
    Wind chill: <xsl:value-of select="wind/@chill"/>
<xsl:value-of select="units/@temperature"/> <br/>
    Wind speed:
    <xsl:value-of select="wind/@speed"/>
    <xsl:value-of select="units/@speed"/>
      </div>
      <div>
    Humidity: <xsl:value-of select="atmosphere/@humidity"/>%
      </div>
      <div>
    Sunrise: <xsl:value-of select="astronomy/@sunrise"/> <br/>
    Sunset: <xsl:value-of select="astronomy/@sunset"/>
      </div>
    </div>
  </xsl:template>

Esse modelo cria o HTML para exibição no balão pop-up do marcador de mapa, listando vários aspectos da previsão do tempo local. Observe como acessar um atributo, como em <xsl:value-of select="condition/@text"/>, que emite o valor do atributo text do elemento filho <condition>. Esse modelo também faz uso do elemento <units>, incluindo as unidades de cada medida junto com seus valores.

O elemento <weather> de nível-raiz na Listagem 27 também aplica um modelo ao elemento <coordinates> no documento de origem (<xsl:apply-templates select="coordinates"/>) para produzir as coordenadas da marca do local, como na Listagem 29.

Listagem 29. Modelo Correspondente ao Elemento <coordinates>
<xsl:template match="coordinates">
    <Point>
      <coordinates>
    <xsl:value-of select="longitude"/>,<xsl:value-of select="latitude"/>
      </coordinates>
    </Point>
  </xsl:template>

Isso produz um elemento <Point> no documento resultante e especifica o par de longitude e latitude da marca do local—sua posição no Google Map.

Para ver o resultado da aplicação de folhas de estilo, em seu navegador, acesse http://YOUR-SERVER/weather.php?zipcode=10010&units=f e visualize a origem da página, o que lembrará a Listagem 30.

Listagem 30. A Sobreposição Final de KML
<?xml version="1.0"?>
<kml xmlns="http://earth.google.com/kml/2.2">
  <Document>
    <name>Conditions for Maspeth, NY at 12:18 am EDT</name>
    <description>Local Weather from Yahoo!</description>
    <Placemark>
      <name>Local Weather</name>
      <description><![CDATA[
            <div>Mostly Cloudy,  57F</div>
            <div>
      Wind chill: 57F<br/>
      Wind speed: 7mph
            </div>
            <div>
      Humidity: 88%
            </div>
            <div>
      Sunrise: 6:57 am<br/>
      Sunset: 6:30 pm
            </div>
        ]]></description>
           <Point>
             <coordinates>-73.91,40.72</coordinates>
           </Point>
     </Placemark>
  </Document>
</kml>

Observe que as coordenadas têm muito menos precisão aqui do que nas coordenadas do Google Maps, o que significa que a marca do local pode ser realmente colocada fora da janela visível no mapa. Para corrigir isso, diminua o zoom do mapa para se certificar de que a marca de local esteja visível.

O KML em Ação

Agora que sua string XSLT inteira funciona, você pode experimentá-la no Google mapplet. Clique em Recarregar para recarregar o cache do Google do mapplet, selecione o botão de opções XSLT do Lado do Servidor e mova o mapa ou altere seu zoom. A marca de local vai aparecer no mapa. Clique nela para revelar o relatório de previsão do tempo HTML criado com as conversões XSLT, como na Figura 8.

Figura 8. O Balão da Marca de Local da Previsão do Tempo Local em Exibição no Google Maps
The local weather Placemark balloon displaying in Google Maps

Resumo

Conclusão

Neste tutorial, você viu como criar um Google Mapplet, e como utilizar a API do Google Mapplet para atender a eventos de mapas e buscar conteúdo XML. Você também utilizou um serviço geocodificador reverso para converter um par de latitude/longitude em um CEP, utilizando o RSS feed do Yahoo Weather, e utilizou o PHP para separar as diferentes partes de uma especificação de componente do Google Mapplet com o módulo XSL no PHP 5 e XSLT. Isso permitiu que você separasse a camada de apresentação da origem de dados (conversão da estrutura de dados do Yahoo em uma estrutura de dados a local) e convertesse o KML de dados de previsão do tempo para sobreposição no Google Maps.

Agora você pode criar suas próprias idéias no Google Mapplet, consultar a documentação da API do Google Mapplet e se divertir conforme reproduz e aprende.


Download

DescriçãoNomeTamanho
Tutorial source codemapplet-tutorial-source.tar80KB

Recursos

Aprender

  • API do Google Mapplets: Visite a página inicial para obter informações sobre esses mini aplicativos que são executados no Google Maps e para incluir novos recursos ou sobrepor seus dados no Google Maps.
  • API do Google Maps: Integre o Google Maps em suas páginas da Web com JavaScript conforme cria aplicativos de mapa robustos para manipular mapas e incluir conteúdo no mapa através de uma variedade de serviços.
  • Tutorial KML: KML é um formato de arquivo utilizado para exibir dados geográficos em um navegador Earth como Google Earth, Google Maps e Google Maps para remoto. Comece bem com este tutorial do Google.
  • Inscrição para API do Google Maps: Inscreva-se para a chave da API do Google Maps.
  • Introducing Google's Geocoding Service (Jason Gilmore, developer.com): Conheça a mais nova inclusão na API do Google Maps que permite mapear locais sem o uso de soluções de terceiros para converter endereços de correspondência em coordenadas de endereço.
  • Google Maps API Reference: Localize os códigos de erro para a resposta do serviço Geocoder.
  • Hosting PHP apps on the IBM HTTP Server (Graham Charters entre outros, developerWorks, março de 2005): Descubra as diferenças entre o servidor da Web Apache de software livre e a versão da IBM e visualize demonstrações da versão da IBM executando um aplicativo PHP bastante conhecido.
  • Apache 2 and PHP Installation (Dan Anderson): Leia um artigo que descreve como fazer o Apache 2 e PHP 4.x (você também pode utilizar PHP 5.x) trabalharem juntos no Linux™.
  • Connecting PHP Applications to Apache Derby (Moira Casey, developerWorks, setembro de 2004): Neste artigo, aprenda a instalar e a configurar PHP no Windows (algumas etapas são aplicáveis ao Linux).
  • Learning PHP, Part 1 (Tyler Anderson e Nicholas Chase, developerWorks, junho de 2005): Aprenda os princípios básicos do PHP.
  • Learning PHP, Part 2 (Tyler Anderson e Nicholas Chase, developerWorks, junho de 2005): Aprenda com fazer upload de arquivos para locais não acessíveis da Web utilizando DOM e SAX.
  • Learning PHP, Part 3 (Tyler Anderson e Nicholas Chase, developerWorks, julho de 2005): Conclua o aplicativo de fluxo de trabalho das Partes 1 e 2. Saiba sobre autenticação HTTP, arquivos de fluxo e como criar objetos e exceções.
  • PHP Manual: Saiba mais sobre objetos de dados PHP e suas capacidades.
  • O Manual On-line do PHP: Explore informações de referência sobre APIs do SOAP no PHP 5.
  • A (Re)-Introduction to JavaScript (Simon Willison, ETech, março de 2006): Aumente seus conhecimentos sobre JavaScript, uma linguagem simples, mas poderosa.
  • Tutorial: Introduction to JavaScript and Introduction to JavaScript: Verifique o potencial para páginas da Web mais interativas em w3schools.com.
  • IBM XML certification: Descubra como você pode se tornar um Desenvolvedor IBM Certificado em XML e em tecnologias relacionadas.
  • XML technical library: Consulte a Zona de XML do developerWorks para obter uma ampla gama de artigos técnicos e dicas, tutoriais, padrões e IBM Redbooks.
  • Eventos Técnicos e Webcasts do developerWorks: Mantenha-se atualizado com a tecnologia nestas sessões.
  • A livraria tecnológica: Procure livros sobre esses e outros tópicos técnicos.
  • podcasts do developerWorks: Ouça entrevistas e discussões interessantes para desenvolvedores de software.

Obter produtos e tecnologias

  • Software de teste IBM para avaliação do produto: Construa seu próximo projeto com o software de teste disponível para download diretamente no developerWorks, incluindo ferramentas de desenvolvimento de aplicativos e produtos de middleware do DB2®, Lotus®, Rational®, Tivoli®e WebSphere®.

Discutir

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Software livre
ArticleID=387086
ArticleTitle=Customize uma Página de Resultados do Google Maps com Google Mapplets
publish-date=10212008