<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tall Eye &#187; cipriani</title>
	<atom:link href="http://blog.talleye.com/author/admin/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.talleye.com</link>
	<description></description>
	<lastBuildDate>Fri, 16 Apr 2010 13:04:18 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Extração de dados públicos com YQL e Y!Pipes, parte 2</title>
		<link>http://blog.talleye.com/2010/04/16/extracao-dados-publicos-com-yql-e-pipes-2/</link>
		<comments>http://blog.talleye.com/2010/04/16/extracao-dados-publicos-com-yql-e-pipes-2/#comments</comments>
		<pubDate>Fri, 16 Apr 2010 13:04:18 +0000</pubDate>
		<dc:creator>cipriani</dc:creator>
				<category><![CDATA[api]]></category>
		<category><![CDATA[yahoo developer]]></category>
		<category><![CDATA[dados publicos]]></category>
		<category><![CDATA[extracao]]></category>
		<category><![CDATA[mining]]></category>
		<category><![CDATA[pipes]]></category>
		<category><![CDATA[sao paulo]]></category>
		<category><![CDATA[yahoo]]></category>
		<category><![CDATA[yql]]></category>

		<guid isPermaLink="false">http://blog.talleye.com/?p=15</guid>
		<description><![CDATA[ 
Na primeira parte dessa série, expliquei os problemas que o desenvolvedor enfrentam ao tentar extrair dados públicos e iniciamos um exemplo com a motivação de se tentar plotar num mapa os endereços de feiras livres de São Paulo, no dia da semana e zona da cidade que o usuário escolhesse. O principal resultado que [...]]]></description>
			<content:encoded><![CDATA[<p><em> </em></p>
<p>Na <a href="http://blog.talleye.com/2010/04/13/extracao-dados-publicos-com-yql-e-pipes-1/" target="_self">primeira parte dessa série</a>, expliquei os problemas que o desenvolvedor enfrentam ao tentar extrair dados públicos e iniciamos um exemplo com a motivação de se tentar plotar num mapa os endereços de feiras livres de São Paulo, no dia da semana e zona da cidade que o usuário escolhesse. O principal resultado que obtivemos até esse ponto foi uma Open Table da Yahoo Query Language que nos permite realizar a pesquisa para obter os endereços. Sucintamente, ao executar a seguinte query:</p>
<pre>
<div class="codecolorer-container sql twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">USE</span> <span style="color: #ff0000;">&quot;http://github.com/lfcipriani/yql-feira-livre-sp/raw/master/yql-feira-livre-sp.xml&quot;</span> <span style="color: #993333; font-weight: bold;">AS</span> feiras;<br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> feiras <span style="color: #993333; font-weight: bold;">WHERE</span> zone <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'SUL'</span> <span style="color: #993333; font-weight: bold;">AND</span> dayOfTheWeek <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'DOMINGO'</span>;</div></div>
</pre>
<p>Obtemos o resultado:</p>
<pre>
<div class="codecolorer-container xml twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;markets<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;market<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dayOfTheWeek<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>DOMINGO<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dayOfTheWeek<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;address<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>RUA  CONDE DE PORTO ALEGRE, Sao Paulo, Brazil<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/address<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/market<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;market<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dayOfTheWeek<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>DOMINGO<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dayOfTheWeek<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;address<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>AV   AMADEU DA SILVA SAMELLO, Sao Paulo, Brazil<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/address<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/market<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp;...<br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/markets<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
</pre>
<p>Você pode relembrar como funciona o YQL <a href="http://developer.yahoo.com/yql/console/#h=use%20%22http%3A//github.com/lfcipriani/yql-feira-livre-sp/raw/master/yql-feira-livre-sp.xml%22%20as%20feiras%3B%0Aselect%20*%20from%20feiras%20where%20zone%20%3D%20%27SUL%27%20and%20dayOfTheWeek%20%3D%20%27DOMINGO%27" target="_blank">executando esse exemplo diretamente no YQL Console</a>.</p>
<p>A proposta dessa segunda parte é utilizar esse resultado, a conversão do HTML em uma estrutura XML fácil de ser lida por um software, no <a href="http://pipes.yahoo.com/pipes/" target="_blank">Yahoo Pipes</a> e plotar o mapa. Dessa forma o usuário pode facilmente saber se tem uma feira livre perto da casa dele, uma vez que agora a informação está num formato mais apropriado.</p>
<h2>Yahoo Pipes</h2>
<p><img class="alignleft size-full wp-image-16" title="Yahoo Pipes" src="http://blog.talleye.com/wp-content/uploads/2010/04/Picture-4.png" alt="" width="185" height="180" />Da própria definição no site: <em>&#8220;Pipes é uma ferramenta poderosa de composição para agregar, manipular e misturar conteúdo (feeds, RSS, Atom, etc) da Web&#8221;</em>.</p>
<p>O legal do Yahoo Pipes é que o usuário não precisa ter conhecimentos avançados de programação ou de como manipular vários formatos, pois a interface é bem fácil de usar. Basta criar conexões entre vários módulos (daí o nome Pipes), sendo que cada módulo faz alguma ação sobre o conteúdo que está passando por ele. A idéia é combinar vários desses módulos para no fim obter um novo fluxo de informações, ou um fluxo enriquecido, modificado.</p>
<p>Nosso objetivo é enriquecer o conteúdo, pois queremos pegar meros endereços e representá-los como pontos em um mapa. Então vamos direto ao ponto!</p>
<h2>O mashup de feira livre</h2>
<p>O Pipes que vamos criar deve fazer o seguinte:</p>
<ul>
<li>Receber do usuário o dia da semana e o zona da cidade;</li>
<li>Executar a query YQL para obter os endereços de cada feira livre;</li>
<li>Para cada endereço, realizar um geocoding para obter as coordenadas geográficas;</li>
<li>Plotar essas coordenadas em um mapa.</li>
</ul>
<p>Para ajudar no entendimento, você pode <a href="http://pipes.yahoo.com/lfcipriani/feiraslivressp" target="_blank">visualizar o Pipes de Feira Livre</a> enquanto lê cada passo abaixo (para ver o &#8220;código-fonte&#8221; do Pipes você precisa estar logado com algum id do Yahoo). Se tiver dúvida no comportamento de um módulo, clique nele e observe a barra inferior apresentando o resultado parcial do mashup.</p>
<h3>Recebendo do usuário o dia da semana e zona da cidade</h3>
<p>As entradas de usuários podem ser feitas utilizando o <a href="http://pipes.yahoo.com/pipes/docs?doc=user_inputs#Text" target="_blank">Text Input Module</a>, veja a figura abaixo apresentando como configuramos este módulo para as duas entradas necessárias no Pipes de feira livre.</p>
<p><a href="http://blog.talleye.com/wp-content/uploads/2010/04/pipes_input.png"><img class="alignnone size-full wp-image-17" title="pipes_input" src="http://blog.talleye.com/wp-content/uploads/2010/04/pipes_input.png" alt="" width="599" height="432" /></a></p>
<p>Como se pode ver, com o Text Input, basta configurar o nome da variável, o texto que aparecerá para o usuário (prompt), um opcional valor default e por fim um valor de debug, utilizado quando o criador do Pipes está testando os resultados. Cada entrada dessa é jogada para um <a href="http://pipes.yahoo.com/pipes/docs?doc=string#StringBuilder" target="_blank">String Builder Module</a>, cujo objetivo é bem simples, concatenar strings. Veja que é bem simples, no nosso caso, bastou conectar a saída do Text Input na parte da string que eu quero gerar. A string final obtida com esse módulo será a query YQL que eu vou executar. Aonde? No <a href="http://pipes.yahoo.com/pipes/docs?doc=sources#YQL" target="_blank">YQL Module</a>, é claro. Vamos dar uma olhada como fica essa segunda parte do Pipes de feira livre.</p>
<h3>Executando a query YQL na Open Table de feira livre</h3>
<p><img class="alignnone size-full wp-image-18" title="pipes_yql" src="http://blog.talleye.com/wp-content/uploads/2010/04/pipes_yql.png" alt="" width="739" height="329" /></p>
<p>A saída do String Builder é plugada no módulo que executa YQL&#8217;s, como mostra a figura acima. O resultado da execução da YQL é uma estrutura de árvore, hierárquica, ou seja, nesta situação, há vários níveis entre a raiz da árvore e a informação que nos interessa (a estrutura XML apresentada no início desse artigo), portanto, temos que usar um <a href="http://pipes.yahoo.com/pipes/docs?doc=operators#SubElement" target="_blank">Sub-element Module</a>.</p>
<p>O Sub-Element apresentado na figura irá pegar a árvore de resultado retornada pela YQL query e vai retornar apenas a sub-árvore indicada no campo dele, isto é, queremos apenas a sub-árvore que no fim será representada por uma lista de mercados (item.market), que por sua vez contêm dia da semana e endereço de uma feira livre. Nesse ponto o Pipes mostra a sua eficiência, quando focamos o campo do módulo Sub-Element, o Pipes abre um dropdown menu contendo todos os nós dessa árvore retornada pela query, facilitando muito a vida do criador do mashup.</p>
<p>Por fim, temos um <a href="http://pipes.yahoo.com/pipes/docs?doc=operators#Rename" target="_blank">Rename Module</a>, e o objetivo dele é renomear atributos de um feed. Esse passo é importantíssimo para a criação desse mashup, pois o Yahoo Pipes, assim como a própria definição dele diz, é um agregador de feeds (RSS, Atom, etc). Portanto, o módulo Rename está sendo usado justamente para esta causa, que é criar o menor feed possível que o Pipes entenda, com título da entrada e descrição.</p>
<p>Se não realizássemos essa renomeação, o Pipes (e outros consumidores desse Pipes de feira livre) não saberia como consumir os dados. Então guarde essa dica: mesmo com a capacidade de trabalhar com várias formatações de dados, todo Pipes deve &#8220;cuspir&#8221; feeds, dessa maneira você facilita até que outros criadores de Pipes reutilize o seu mashup. Só existe uma exceção para essa regra e vamos apresentá-la na próxima etapa.</p>
<h3>Realizando o geocoding para obter as coordenadas geográficas</h3>
<p><img class="alignnone size-full wp-image-20" title="pipes_geo" src="http://blog.talleye.com/wp-content/uploads/2010/04/pipes_geo.png" alt="" width="780" height="319" /></p>
<p>Esta etapa foi a mais complicada. Inicialmente, colocamos um <a href="http://pipes.yahoo.com/pipes/docs?doc=operators#Loop" target="_blank">Loop Module</a>, cujo objetivo é iterar sobre os elementos do feed e realizar alguma operação neles. Essa operação pode ser qualquer outro módulo do Pipes. Olhando no Loop da figura acima, temos o Google Maps Location Extractor, que se você procurar nos módulos padrões disponíveis do yahoo Pipes você não vai encontrar. A explicação é simples, esse módulo é um outro Yahoo Pipes criado por mim. Esse eu não vou explicar como eu fiz, vou apenas passar a URL pra vocês e aí fica como &#8220;lição de casa&#8221; entender como ele funciona, OK? Aí vai: <a href="http://pipes.yahoo.com/lfcipriani/gmapslocationextractor" target="_blank">http://pipes.yahoo.com/lfcipriani/gmapslocationextractor</a>.</p>
<p>O único detalhe importante que vale o comentário é que esse Pipes não retorna um feed válido, mas apenas uma estrutura contendo o resultado da geolocalização, e assim, fugindo da regra citada na etapa anterior. Fiz isso porque o objetivo principal desse Pipes de geolocalização é ser reutilizado somente dentro de outro Pipes, e com restrição na forma de utilizar o seu resultado.</p>
<p>Mas aí vocês podem se perguntar: peraí, o Yahoo Pipes já não tem um módulo de extração de geolocalização? Sim, ele tem, e se chama <a href="http://pipes.yahoo.com/pipes/docs?doc=operators#LocationExtractor" target="_blank">Location Extractor Module</a>, e para utilizá-lo basta plugá-lo em qualquer saída de feed que ele irá pesquisar por coordenadas geográficas nos campos do feed que são endereços. Se usássemos ele não precisaríamos criar esse Loop, pois ele itera automaticamente nos feeds, mas então porque não usamos?</p>
<p>A resposta é simples, após alguns testes com esse Location Extractor eu percebi que as coordenadas que ele encontrava não era do endereço correto, ou seja, o geolocation não era confiável para os endereços de feiras de São Paulo, talvez ele seja mais eficiente para outras situações. Eu testei alguns endereços no <a href="http://code.google.com/apis/maps/documentation/geocoding/" target="_blank">Google Maps Geocoding Webservice</a> e ele foi capaz de acertar mais, mas ainda assim comete alguns erros de vez em quando (vocês podem ver ao executar o Pipes que alguns endereços caem em outras cidades, mas não deveria porque as feiras são todas na cidade de São Paulo). Enfim, como o Google Maps se comportou melhor, não me prendi ao Location Extractor que está disponível no Yahoo Pipes e decidi criar um outro usando um geocoding melhor para a minha necessidade.</p>
<h3>Plotando no mapa</h3>
<p>O Yahoo Pipes possui uma convenção para coordenadas geográficas, dessa forma, feeds que possuem os campos nesse padrão são automaticamente mapeados quando o Pipes é executado (e você achando que ia ter que aprender a API do Yahoo Maps, hein! <img src='http://blog.talleye.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> ).</p>
<p>O jeito mais simples de utilizar esse padrão é criar o nó <strong>y:location</strong> e colocar dentro dele os atributos <strong>y:location.lat</strong> e <strong>y:location.lon</strong> (você também pode <a href="http://pipes.yahoo.com/pipes/docs?doc=operators#LocationExtractor" target="_blank">incluir outras informações</a>). Como o webservice de geocoding do Google Maps não me retorna esses campos no formato que o Yahoo Pipes precisa, eu utilizo o Rename Module novamente para renomear a longitude para a forma correta e pronto! Jogo a saída disso tudo no Pipe Output e o Pipes está finalizado.</p>
<h2>O resultado final</h2>
<p>Se no modo de edição clicarmos no Pipe Output, poderemos ver na barra de debug inferior da interface do Yahoo Pipes a seguinte estrutura de resultados:</p>
<p><a href="http://blog.talleye.com/wp-content/uploads/2010/04/result.png"><img class="alignnone size-full wp-image-21" title="result" src="http://blog.talleye.com/wp-content/uploads/2010/04/result.png" alt="" width="390" height="120" /></a></p>
<p>Esse é o feed final que o usuário vai obter ao executar o Pipes, que pode ser utilizado assim como qualquer outro feed na Web: assinar em um feed Reader, consumir com outro Pipes (ou software), manipular as entradas, plotar em outro tipo de mapa, Google Earth, [coloque o que quiser aqui].</p>
<p>Você também pode acessar o Pipes de Feiras Livres de São Paulo <a href="http://pipes.yahoo.com/lfcipriani/feiraslivressp" target="_blank">pelo próprio site dele</a>, e aí obterá um resultado parecido com esse:</p>
<p><a href="http://blog.talleye.com/wp-content/uploads/2010/04/pipes_result1.png"><img class="alignnone size-full wp-image-23" title="pipes_result" src="http://blog.talleye.com/wp-content/uploads/2010/04/pipes_result1.png" alt="" width="692" height="622" /></a></p>
<p><em>Obs.: Lembro vocês que o serviço da prefeitura que serve os endereços é bem instável. Eu tive problemas para acessar principalmente após a meia-noite nos dias da semana e durante o dia todo no fim de semana.</em></p>
<h2>Recapitulando</h2>
<p>Na <a href="http://blog.talleye.com/2010/04/13/extracao-dados-publicos-com-yql-e-pipes-1/" target="_blank">primeira parte desse artigo</a>, focamos em como usar a Yahoo Query Language para oferecer uma linguagem parecida com a SQL para transformar representações, no caso, um HTML desestruturado para um XML conciso e estruturado de forma melhor para ser processada por um software.</p>
<p>Já nesta segunda parte, utilizamos o resultado dessa query YQL para plotar os endereços das feiras livres de São Paulo. O interessante é que isso foi feito inteiramente dentro do Yahoo Pipes, sem a necessidade de escrever uma linha de código.</p>
<p>A minha recomendação de uso para esses serviços é a seguinte: claro que se formos construir uma aplicação mais robusta, processando muito mais dados e que terá uma alta carga num servidor, o Yahoo Pipes e talvez até o YQL não sejam as maneiras apropriadas de se fazer os mashups. Porém, como no caso do exemplo desse artigo (localização de feiras livres), a proposta for apenas de criar um mashup rápido para se ter um ganho no entendimento e visualização de uma informação, que não vai ser utilizada para fins muito críticos, aí sim, esses tipos de serviços são excelentes, pois os resultados vêm rapidamente.</p>
<p>Enfim, sugiro dar uma olhada nos Pipes existentes, tem sempre uma idéia interessante pra ser observada e é muito fácil ver como ela foi implementada, graças a interface que o Yahoo criou para isso. E se você criar ou já criou um Pipes, coloque num comentário desse artigo para que os leitores possam acessar também.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.talleye.com/2010/04/16/extracao-dados-publicos-com-yql-e-pipes-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Extração de dados públicos com YQL e Y!Pipes, parte 1</title>
		<link>http://blog.talleye.com/2010/04/13/extracao-dados-publicos-com-yql-e-pipes-1/</link>
		<comments>http://blog.talleye.com/2010/04/13/extracao-dados-publicos-com-yql-e-pipes-1/#comments</comments>
		<pubDate>Tue, 13 Apr 2010 03:28:33 +0000</pubDate>
		<dc:creator>cipriani</dc:creator>
				<category><![CDATA[api]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[yahoo developer]]></category>
		<category><![CDATA[dados publicos]]></category>
		<category><![CDATA[extracao]]></category>
		<category><![CDATA[mining]]></category>
		<category><![CDATA[pipes]]></category>
		<category><![CDATA[yahoo]]></category>
		<category><![CDATA[yql]]></category>

		<guid isPermaLink="false">http://blog.talleye.com/?p=12</guid>
		<description><![CDATA[Não dá mais para acessar a Web sem esbarrar nos famosos mashups, que são aplicações web, complexas ou simples, que misturam fontes de dados de várias origens com o objetivo de fornecer um novo ponto de vista, uma nova maneira de se divertir ou mais conhecimento sobre um determinado assunto.
Menos comum mas muito importantes, mashups [...]]]></description>
			<content:encoded><![CDATA[<p>Não dá mais para acessar a Web sem esbarrar nos famosos <em>mashups</em>, que são aplicações web, complexas ou simples, que misturam fontes de dados de várias origens com o objetivo de fornecer um novo ponto de vista, uma nova maneira de se divertir ou mais conhecimento sobre um determinado assunto.</p>
<p>Menos comum mas muito importantes, mashups que utilizam dados públicos (aqueles que se utilizam de dados de órgãos públicos ou outras instituições com esse mesmo caráter) também são criados, porém os desenvolvedores enfrentam muitas dificuldades, por exemplo:</p>
<ul>
<li>Falta de interesse da população e dos usuários da Web;</li>
<li>Nem todos os dados necessários estão publicados ou disponíveis para acesso;</li>
<li>Algumas vezes os dados podem não estar atualizados ou serem pouco confiáveis;</li>
<li>Servidores dos dados podem ser mal administrados e os dados podem ficar indisponíveis temporariamente;</li>
<li>A forma como os dados são disponibilizados pode ser &#8220;ilegível&#8221; ou &#8220;burocrática&#8221; para um software;</li>
</ul>
<p>Eliminar essas dificuldades depende de boa vontade desses órgãos públicos e dos cidadãos. Enquanto não temos uma solução, nós, como desenvolvedores, podemos utilizar ferramentas e nossa criatividade para extrair esses dados, certo? Sendo assim, vamos implementar uma simples extração de dados utilizando 2 ferramentas que facilitam a nossa vida: a <strong>Yahoo Query Language (YQL)</strong> e o <strong>Yahoo Pipes (Y!Pipes)</strong>.</p>
<p>Nessa primeira parte, o foco será apenas no YQL, mas eu pretendo publicar a parte do Y!Pipes em 1 dia ou 2.</p>
<h2>A motivação</h2>
<div id="attachment_13" class="wp-caption alignleft" style="width: 250px"><a href="http://www.flickr.com/photos/franciscoferreira/1434200890/"><img class="size-full wp-image-13 " title="chico_ferreira_foto_feira" src="http://blog.talleye.com/wp-content/uploads/2010/04/chico_ferreira_foto_feira.jpg" alt="http://www.flickr.com/photos/franciscoferreira/1434200890/" width="240" height="180" /></a><p class="wp-caption-text">foto por Chico Ferreira</p></div>
<p>Eu costumo ir sempre numa mesma feira livre, aqui em São paulo, nos sábados. Porém, sempre quis saber se existem feiras livres mais próximas de casa e os dias em que elas ocorrem. Tinha duas opções, ou saía de casa todo dia e andava pela redondeza procurando feiras ou dava uma &#8220;googlada&#8221; para ver se encontrava localização delas aqui em São Paulo. Acabei encontrando o seguinte site da prefeitura:</p>
<pre><a title="Acessar o site de pesquisa de feiras" href="http://www.prodam.sp.gov.br/semab/mercados/pesqt.htm" target="_blank"><strong>http://www.prodam.sp.gov.br/semab/mercados/pesqt.htm</strong></a></pre>
<p>Sensacional, funciona direitinho e escolhendo região e dia da semana eu obtenho uma lista com os endereços. Aí é que aparece mais um problema, eu reconheci poucas ruas e decidi procurar no Google Maps, mas isso não é muito produtivo, tinha que copiar rua por rua e isso se tornou uma tarefa tediosa. Então decidi colocar a mão na massa pra plotar todos esses endereços num mapa, utilizando o que a Web oferece.</p>
<h2>Os problemas dessa fonte de dados</h2>
<p>Não apenas o design da página, mas todo o código HTML parece que foi criado nos anos 90. Ele utiliza frames, tags &lt;center&gt;, &lt;font&gt;, &lt;table&gt;&#8217;s aninhadas, em resumo, uma tristeza para qualquer programador que precisar fazer um parsing. Vamos dar uma olhada na situação:</p>
<pre>
<div class="codecolorer-container html4strict twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/html.html"><span style="color: #000000; font-weight: bold;">HTML</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/head.html"><span style="color: #000000; font-weight: bold;">HEAD</span></a>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/head.html"><span style="color: #000000; font-weight: bold;">HEAD</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/body.html"><span style="color: #000000; font-weight: bold;">BODY</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/head.html"><span style="color: #000000; font-weight: bold;">HEAD</span></a>&gt;&lt;<a href="http://december.com/html/4/element/title.html"><span style="color: #000000; font-weight: bold;">TITLE</span></a>&gt;</span>ENDERECO DAS  FEIRAS POR DIA  <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/title.html"><span style="color: #000000; font-weight: bold;">TITLE</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/head.html"><span style="color: #000000; font-weight: bold;">HEAD</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;BODY  <span style="color: #000066;">bgcolor</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;f9cd8a&quot;</span>&gt;</span><br />
<span style="color: #808080; font-style: italic;">&lt;!--BODY background=&quot;/img_feiras/feiras.GIF&quot;--&gt;</span><span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/br.html"><span style="color: #000000; font-weight: bold;">br</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/center.html"><span style="color: #000000; font-weight: bold;">center</span></a>&gt;</span><br />
<span style="color: #808080; font-style: italic;">&lt;!--img src=&quot;/img_feiras/logo1.GIF&quot; border=0 align=top&gt;&lt;BR&gt;</span><br />
<span style="color: #808080; font-style: italic;">&lt;font color=#006666 size=5&gt;&lt;B&gt;&lt;I&gt;RELAÇÃO DE FEIRAS&lt;/I&gt;&lt;/B&gt;&lt;/FONT&gt;&lt;BR--&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/center.html"><span style="color: #000000; font-weight: bold;">CENTER</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/pre.html"><span style="color: #000000; font-weight: bold;">PRE</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/center.html"><span style="color: #000000; font-weight: bold;">center</span></a>&gt;&lt;<a href="http://december.com/html/4/element/table.html"><span style="color: #000000; font-weight: bold;">table</span></a> <span style="color: #000066;">border</span><span style="color: #66cc66;">=</span>0&gt;&lt;<a href="http://december.com/html/4/element/tr.html"><span style="color: #000000; font-weight: bold;">tr</span></a>&gt;&lt;<a href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">td</span></a>&gt;</span><br />
&nbsp;<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/center.html"><span style="color: #000000; font-weight: bold;">CENTER</span></a>&gt;&lt;<a href="http://december.com/html/4/element/table.html"><span style="color: #000000; font-weight: bold;">TABLE</span></a> <span style="color: #000066;">BORDER</span><span style="color: #66cc66;">=</span>1 <span style="color: #000066;">background</span><span style="color: #66cc66;">=</span>http:<span style="color: #66cc66;">//</span>www.prodam.sp.gov.br<span style="color: #66cc66;">/</span>semab<span style="color: #66cc66;">/</span>mercados<span style="color: #66cc66;">/</span>img_feiras<span style="color: #66cc66;">/</span>Gray.jpg&gt;&lt;<a href="http://december.com/html/4/element/tr.html"><span style="color: #000000; font-weight: bold;">TR</span></a>&gt;&lt;<a href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">TD</span></a> <span style="color: #000066;">ALIGN</span><span style="color: #66cc66;">=</span>CENTER <span style="color: #000066;">COLSPAN</span><span style="color: #66cc66;">=</span>4&gt;&lt;<a href="http://december.com/html/4/element/font.html"><span style="color: #000000; font-weight: bold;">FONT</span></a> <span style="color: #000066;">COLOR</span><span style="color: #66cc66;">=</span>#006666  <span style="color: #000066;">SIZE</span><span style="color: #66cc66;">=</span><span style="color: #cc66cc;">5</span>&gt;</span>ZONA CENTRAL<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/font.html"><span style="color: #000000; font-weight: bold;">FONT</span></a>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">TD</span></a>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/tr.html"><span style="color: #000000; font-weight: bold;">TR</span></a>&gt;&lt;<a href="http://december.com/html/4/element/tr.html"><span style="color: #000000; font-weight: bold;">TR</span></a>&gt;&lt;<a href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">TD</span></a> <span style="color: #000066;">ALIGN</span><span style="color: #66cc66;">=</span>CENTER&gt;&lt;<a href="http://december.com/html/4/element/font.html"><span style="color: #000000; font-weight: bold;">FONT</span></a> <span style="color: #000066;">COLOR</span><span style="color: #66cc66;">=</span>Black <span style="color: #000066;">Size</span><span style="color: #66cc66;">=</span>3&gt;&lt;<a href="http://december.com/html/4/element/b.html"><span style="color: #000000; font-weight: bold;">b</span></a>&gt;</span>DIA<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/b.html"><span style="color: #000000; font-weight: bold;">b</span></a>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">TD</span></a>&gt;</span><br />
&nbsp;<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">TD</span></a>&gt;&lt;<a href="http://december.com/html/4/element/font.html"><span style="color: #000000; font-weight: bold;">FONT</span></a> <span style="color: #000066;">COLOR</span><span style="color: #66cc66;">=</span>Black <span style="color: #000066;">Size</span><span style="color: #66cc66;">=</span>3&gt;&lt;<a href="http://december.com/html/4/element/b.html"><span style="color: #000000; font-weight: bold;">b</span></a>&gt;</span>ENDERECO<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/b.html"><span style="color: #000000; font-weight: bold;">b</span></a>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">TD</span></a>&gt;</span><br />
&nbsp;<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">TD</span></a> <span style="color: #000066;">ALIGN</span><span style="color: #66cc66;">=</span>CENTER&gt;&lt;<a href="http://december.com/html/4/element/font.html"><span style="color: #000000; font-weight: bold;">FONT</span></a> <span style="color: #000066;">COLOR</span><span style="color: #66cc66;">=</span>Black <span style="color: #000066;">Size</span><span style="color: #66cc66;">=</span>3&gt;&lt;<a href="http://december.com/html/4/element/b.html"><span style="color: #000000; font-weight: bold;">b</span></a>&gt;</span>NRO.<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/b.html"><span style="color: #000000; font-weight: bold;">b</span></a>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">TD</span></a>&gt;</span><br />
&nbsp;<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">TD</span></a> <span style="color: #000066;">ALIGN</span><span style="color: #66cc66;">=</span>CENTER&gt;&lt;<a href="http://december.com/html/4/element/font.html"><span style="color: #000000; font-weight: bold;">FONT</span></a> <span style="color: #000066;">COLOR</span><span style="color: #66cc66;">=</span>Black <span style="color: #000066;">Size</span><span style="color: #66cc66;">=</span>3&gt;&lt;<a href="http://december.com/html/4/element/b.html"><span style="color: #000000; font-weight: bold;">b</span></a>&gt;</span>BAIRRO<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/b.html"><span style="color: #000000; font-weight: bold;">b</span></a>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">TD</span></a>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/tr.html"><span style="color: #000000; font-weight: bold;">TR</span></a>&gt;</span><br />
&nbsp;<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/tr.html"><span style="color: #000000; font-weight: bold;">TR</span></a>&gt;</span><br />
&nbsp;<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">TD</span></a> <span style="color: #000066;">ALIGN</span><span style="color: #66cc66;">=</span>CENTER&gt;&lt;<a href="http://december.com/html/4/element/font.html"><span style="color: #000000; font-weight: bold;">FONT</span></a> <span style="color: #000066;">COLOR</span><span style="color: #66cc66;">=</span>Red <span style="color: #000066;">Size</span><span style="color: #66cc66;">=</span><span style="color: #cc66cc;">2</span>&gt;</span>DOMINGO<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">TD</span></a>&gt;</span><br />
&nbsp;<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">TD</span></a>&gt;&lt;<a href="http://december.com/html/4/element/font.html"><span style="color: #000000; font-weight: bold;">FONT</span></a> <span style="color: #000066;">COLOR</span><span style="color: #66cc66;">=</span>Red <span style="color: #000066;">Size</span><span style="color: #66cc66;">=</span><span style="color: #cc66cc;">2</span>&gt;</span>RUA  SANTO AMARO                  <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">TD</span></a>&gt;</span><br />
&nbsp;<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">TD</span></a> <span style="color: #000066;">ALIGN</span><span style="color: #66cc66;">=</span>CENTER&gt;&lt;<a href="http://december.com/html/4/element/font.html"><span style="color: #000000; font-weight: bold;">FONT</span></a> <span style="color: #000066;">COLOR</span><span style="color: #66cc66;">=</span>Red <span style="color: #000066;">Size</span><span style="color: #66cc66;">=</span><span style="color: #cc66cc;">2</span>&gt;</span>  S/N<span style="color: #ddbb00;">&amp;nbsp;</span><span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">TD</span></a>&gt;</span><br />
&nbsp;<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">TD</span></a> <span style="color: #000066;">ALIGN</span><span style="color: #66cc66;">=</span>CENTER&gt;&lt;<a href="http://december.com/html/4/element/font.html"><span style="color: #000000; font-weight: bold;">FONT</span></a> <span style="color: #000066;">COLOR</span><span style="color: #66cc66;">=</span>Red <span style="color: #000066;">Size</span><span style="color: #66cc66;">=</span><span style="color: #cc66cc;">2</span>&gt;</span>BELA VISTA          <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/td.html"><span style="color: #000000; font-weight: bold;">TD</span></a>&gt;</span><br />
&nbsp;<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/tr.html"><span style="color: #000000; font-weight: bold;">TR</span></a>&gt;</span><br />
&nbsp;... omiti de propósito algumas linhas que se repetem ...</div></div>
</pre>
<p>Além disso, o servidor nem sempre está disponível (percebi que de fim de semana a instabilidade aumenta) e o tempo de execução médio de requisições que eu enfrentei foi de 10 a 15 segundos. Solução para esse problema, só cacheando todos os dados em outro servidor (não, obrigado) ou quando eles realizarem melhorias na infraestrutura (mas convenhamos, isso não deve ser prioridade).</p>
<h2>O objetivo</h2>
<p>A tarefa parece simples:</p>
<ul>
<li>Executo uma requisição POST passando os parâmetros de zona e dia da semana (via wget, curl, API HTTP de qualquer linguagem);</li>
<li>Realizo um DOM parsing no HTML retornado, e recupero a tabela contendo os endereços (via navegação de DOM, XPATH);</li>
<li>Para cada endereço, faço um geocoding usando qualquer API disponível para obter as coordenadas geográficas (via Yahoo Maps, Google Maps, Geonames, etc);</li>
<li>Jogo essas coordenadas em qualquer serviço de mapas (via Yahoo Maps, Google Maps, etc).</li>
</ul>
<p>Tinha apenas uma <span style="text-decoration: line-through;">preguiça</span> premissa: não queria usar nenhum programa feito por mim nem por ninguém, mas sim apenas serviços na Web.</p>
<h2>Yahoo Query Language</h2>
<p>A <a title="Acessar site da Yahoo Query Language" href="http://developer.yahoo.com/yql/" target="_blank">Yahoo Query Language</a> ou apenas YQL, é uma linguagem parecida com a SQL, largamente utilizada nos bancos de dados, porém cujo objetivo é acessar fontes de dados na Internet. Por exemplo, uma query possível de se realizar com ela é:</p>
<pre>
<div class="codecolorer-container sql twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> <span style="color: #993333; font-weight: bold;">LOCAL</span><span style="color: #66cc66;">.</span>search <span style="color: #993333; font-weight: bold;">WHERE</span> query<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;sushi&quot;</span> <span style="color: #993333; font-weight: bold;">AND</span> location<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;san francisco, ca&quot;</span></div></div>
</pre>
<p>Bem simples, essa query vai pesquisar por restaurantes em San Francisco, California, que servem sushi. O interessante é que o serviço da YQL centraliza as fontes de dados e fornece uma interface única para todos eles, facilitando a vida do programador, pois fica muito mais fácil utilizar os resultados das queries e também de combinar vários serviços. Se você ainda não conhece, sugiro dar uma brincada com o <a title="Acessar o Console" href="http://developer.yahoo.com/yql/console/" target="_blank">YQL Console</a>, que possui inúmeros exemplos.</p>
<p>Para os serviços que não possuem tabelas disponíveis, o YQL nos dá duas opções. A primeira é simples, basta executar a seguinte query:</p>
<pre>
<div class="codecolorer-container sql twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> html <span style="color: #993333; font-weight: bold;">WHERE</span> url<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;[qualquer URL aqui]&quot;</span> <span style="color: #993333; font-weight: bold;">AND</span> xpath<span style="color: #66cc66;">=</span><span style="color: #ff0000;">'[uma query XPATH aqui]</span></div></div>
</pre>
<p>Com essa query obtemos o resultado da query <a href="http://www.w3schools.com/xpath/default.asp" target="_blank">XPATH</a> no código HTML no formato JSON ou XML. Contudo, essa opção não nos ajuda, pois precisamos realizar uma requisição POST e passar parâmetros para ela.</p>
<p>Nos resta a segunda opção, Open Tables!</p>
<h2>YQL Open Tables</h2>
<p>Mais interessante que a própria YQL, são as <a href="http://developer.yahoo.com/yql/guide/yql_dev_guide.html" target="_blank">YQL Open Tables</a>, que permitem expor qualquer serviço ou API na web como uma tabela na YQL. Basicamente, para isso, basta criar a especificação de sua Open Table com XML, que pode inclusive possuir código javascript para permitir uma manipulação mais flexível dos dados.</p>
<p>Vamos então ver como fica a nossa Open Table para o caso da nossa fonte de dados de feiras livres em São Paulo. Se você está ansioso, pode acessar o <a href="http://github.com/lfcipriani/yql-feira-livre-sp" target="_blank">código fonte</a> final no GitHub.</p>
<p>O primeiro passo é colocar a meta-informação da sua Open Table, para que os usuários dela possam saber a forma correta de utilizá-la. Todos as tags XML utilizadas estão detalhadas na <a href="http://developer.yahoo.com/yql/guide/yql-opentables-reference.html" target="_blank">documentação de Open Tables da YQL</a>, portanto, vou explicar somente aquelas mais relevantes para o entendimento deste artigo.</p>
<pre>
<div class="codecolorer-container xml twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;table</span> <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">&quot;http://query.yahooapis.com/v1/schema/table.xsd&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;meta<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;author<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Luis Cipriani (@lfcipriani)<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/author<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp;Busca por Feiras Livres em São Paulo, por dia da semana e zona da cidade.<br />
&nbsp;- As zonas possíveis são: CENTRAL, NORTE, SUL, LESTE e OESTE.<br />
&nbsp;- Os dias da semana possíveis são: DOMINGO, TERCA, QUARTA, QUINTA, SEXTA, SÁBADO.<br />
&nbsp;- Deixe o dia da semana em branco para pesquisar em todos os dias de uma vez só.<br />
&nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sampleQuery<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><span style="color: #339933;">&lt;![CDATA[ SELECT * FROM {table} WHERE zone = 'CENTRAL' ]]&gt;</span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sampleQuery<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sampleQuery<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><span style="color: #339933;">&lt;![CDATA[ SELECT * FROM {table} WHERE dayOfTheWeek = 'DOMINGO' AND zone = 'OESTE' ]]&gt;</span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sampleQuery<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;documentationURL<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/documentationURL<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/meta<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/table<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
</pre>
<p>Agora precisamos criar a parte da especificação que cria a estrutura da query que desejamos expor para os usuários:</p>
<pre>
<div class="codecolorer-container xml twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;table<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;meta<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>...<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/meta<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bindings<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;select</span> <span style="color: #000066;">itemPath</span>=<span style="color: #ff0000;">&quot;&quot;</span> <span style="color: #000066;">produces</span>=<span style="color: #ff0000;">&quot;JSON&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;urls<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;url<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>http://www3.prefeitura.sp.gov.br/feiras/feiras.asp<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/url<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/urls<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;inputs<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;dayOfTheWeek&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;xs:string&quot;</span> <span style="color: #000066;">paramType</span>=<span style="color: #ff0000;">&quot;variable&quot;</span> <span style="color: #000066;">default</span>=<span style="color: #ff0000;">&quot;todos&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;key</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;zone&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;xs:string&quot;</span> <span style="color: #000066;">paramType</span>=<span style="color: #ff0000;">&quot;variable&quot;</span> <span style="color: #000066;">required</span>=<span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/inputs<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;execute<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>...<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/execute<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/select<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bindings<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/table<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
</pre>
<p>Dentro da tag <em>&lt;bindings&gt;</em> podemos ter as tags <em>&lt;select&gt;, &lt;insert&gt;, &lt;update&gt; e &lt;delete&gt;</em>, dependendo do tipo de queries que queremos criar, no nosso caso, somente uma query SELECT. Deixamos o attributo <strong>itemPath</strong> porque não queremos colocar nenhum namespace precedendo a resposta retornada e escolhemoso JSON como format padrão no atributo <strong>produces</strong>.</p>
<p>Na tag <em>&lt;url&gt;</em> colocamos a URL do serviço que vamos acessar, no caso, essa é a URL que vamos fazer a requisição POST e passar os parâmetros necessários para obter a lista de endereços de feiras livres.</p>
<p>Só nos falta agora definir quais os parâmetros desejamos na query, o que é feito pela tag <em>&lt;key&gt;</em>. No exemplo acima, ao atribuir o tipo <em>variable</em> para as duas tags, eu estou informando que <em>dayOfTheWeek</em> e <em>zone</em> são duas variáveis que podem (ou devem) ser utilizadas como cláusulas no WHERE da query.</p>
<p>Munido de todas as configurações de nossa query, se o tipo de fonte de dados utilizado exigir, podemos ainda incluir um código javascript para permitir um manuseio mais flexível dos dados obtidos pela query. No nosso caso, nós precisaremos fazer isso, pois a forma como o HTML é entregue após essa requisição não é muito fácil de lidar. Além disso, desejamos que ao executar essa query, o desenvolvedor obtenha apenas os dados necessário, então seria interessante retornarmos os dados limpos e bem estruturados.</p>
<p>Queremos, a partir do código HTML da fonte de dados apresentado acima, obter o seguinte:</p>
<pre>
<div class="codecolorer-container xml twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;markets<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;market<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dayOfTheWeek<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>DOMINGO<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dayOfTheWeek<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;address<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>RUA  CONDE DE PORTO ALEGRE, Sao Paulo, Brazil<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/address<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/market<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;market<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dayOfTheWeek<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>DOMINGO<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dayOfTheWeek<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;address<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>AV   AMADEU DA SILVA SAMELLO, Sao Paulo, Brazil<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/address<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp;<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/market<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp;...<br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/markets<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
</pre>
<p>Vamos então analisar por partes o código javascript, que é incluído dentro da tag <em>&lt;execute&gt;</em>. Veja bem que vamos apenas focar nas partes mais importantes:</p>
<pre>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> postData <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;zona=&quot;</span><span style="color: #339933;">+</span> zone <span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;&amp;amp;dia=&quot;</span> <span style="color: #339933;">+</span> dayOfTheWeek<span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> data <span style="color: #339933;">=</span> request.<span style="color: #660066;">accept</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'text/html'</span><span style="color: #009900;">&#41;</span>.<br />
&nbsp; &nbsp; <span style="color: #660066;">contentType</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;application/x-www-form-urlencoded&quot;</span><span style="color: #009900;">&#41;</span>.<br />
&nbsp; &nbsp; <span style="color: #660066;">post</span><span style="color: #009900;">&#40;</span>postData<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">response</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> xdata <span style="color: #339933;">=</span> y.<span style="color: #660066;">xpath</span><span style="color: #009900;">&#40;</span>data<span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;//font[@color='Red']&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
</pre>
<p>Como a nossa requisição é do tipo POST e por padrão uma Open Table faz um GET, precisamos usar o objeto <em>request</em> fornecido pelo YQL para realizar a requisição manualmente. O objeto <em>request</em> possui a propriedade de chaining, então fica bem tranquilo realizar a requisição. Só lembrando que a URL utiliza é aquela especificada lá na tag URL.</p>
<p>Depois pegamos o resultado dessa requisição e realizamos uma query XPATH. Diante do HTML totalmente sem estrutura que recebemos da requisição, a query XPATH que busca os resultados que mais precisamos foi:</p>
<pre>
<div class="codecolorer-container xml twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">//font[@color='Red']</div></div>
</pre>
<p>Ou seja, todas as tags do tipo <em>&lt;font&gt;</em> que possuem o atributo color igual a &#8220;Red&#8221;. Se o HTML fosse semanticamente válido com certeza essa query seria diferente e até faria mais sentido, mas ao extrair dados públicos é bastante comum se deparar com esse tipo de estrutura. Mas é aí tá a diversão do negócio! <img src='http://blog.talleye.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Calma que ainda não acabou, agora temos que utilizar o resultado da query XPATH e recuperar dessa lista o dia da semana e estruturar o endereço de uma forma que seja ideal para o geocoding.</p>
<pre>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">default</span> xml <span style="color: #003366; font-weight: bold;">namespace</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span><br />
<span style="color: #000066; font-weight: bold;">for</span> each <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> <span style="color: #000066; font-weight: bold;">item</span> <span style="color: #000066; font-weight: bold;">in</span> xdata<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">==</span> 0<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; day <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">item</span>.<span style="color: #660066;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">==</span> 1<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; address <span style="color: #339933;">+=</span> <span style="color: #000066; font-weight: bold;">item</span>.<span style="color: #660066;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;, &quot;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">==</span> 2<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; number <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">item</span>.<span style="color: #660066;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>number <span style="color: #339933;">!=</span> <span style="color: #3366CC;">&quot;S/N&quot;</span> <span style="color: #339933;">&amp;</span>amp<span style="color: #339933;">;&amp;</span>amp<span style="color: #339933;">;</span> number.<span style="color: #660066;">length</span> <span style="color: #339933;">!=</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; address <span style="color: #339933;">+=</span> number <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;, &quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">==</span> <span style="color: #CC0000;">3</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; address <span style="color: #339933;">+=</span> <span style="color: #3366CC;">&quot;Sao Paulo, Brazil&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; marketList.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>day<span style="color: #339933;">:</span> day<span style="color: #339933;">,</span> address<span style="color: #339933;">:</span> address<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; address <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;&quot;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; i <span style="color: #339933;">=</span> <span style="color: #339933;">-</span><span style="color: #CC0000;">1</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; i<span style="color: #339933;">++;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
</pre>
<p>No código acima, nós iteramos sobre o resultado da query anterior. Para cada 4 items, o primeiro é o dia da semana, e do 2o. ao 4o. constitui o endereço, que incrementamos em uma variável <em>address</em> para no final, montarmos um JSON que possui os atributos relevantes: dia da semana e endereço. Um leitor atento vai perceber que tem código meio estranho nesse trecho acima, o fato é que o YQL aceita na tag <em>&lt;execute&gt;</em>, além do javascript, o <a href="http://www.w3schools.com/e4x/default.asp" target="_blank">E4X</a> (Ecmascript for XML), que adiciona suporte nativo ao manuseio de XML no javascript e é por isso que existe a declaração de namespace <code class="codecolorer javascript twitlight"><span class="javascript"><span style="color: #003366; font-weight: bold;">default</span> xml <span style="color: #003366; font-weight: bold;">namespace</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span></span></code>. Vamos dar uma olhada na última parte desse algoritmo para entender melhor como o E4X funciona.</p>
<pre>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">default</span> xml <span style="color: #003366; font-weight: bold;">namespace</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> result <span style="color: #339933;">=</span> <span style="color: #339933;">&lt;</span>markets <span style="color: #339933;">/&gt;</span><br />
<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> marketList.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; result.<span style="color: #660066;">markets</span> <span style="color: #339933;">+=</span> <span style="color: #339933;">&lt;</span>market<span style="color: #339933;">&gt;&lt;</span>dayOfTheWeek<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#123;</span>marketList<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">day</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">&lt;/</span>dayOfTheWeek<span style="color: #339933;">&gt;&lt;</span>address<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#123;</span>marketList<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">address</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">&lt;/</span>address<span style="color: #339933;">&gt;&lt;/</span>market<span style="color: #339933;">&gt;;</span><br />
<span style="color: #009900;">&#125;</span><br />
response.<span style="color: #660066;">object</span> <span style="color: #339933;">=</span> result<span style="color: #339933;">;</span></div></div>
</pre>
<p>A resposta da query YQL deve ser enviada para a variável <em>response.object</em> e deve ser criada com o E4X, e veja que isso é feito escrevendo XML diretamente no código javascript. Esse algoritmo foi necessário apenas para converter a estrutura HTML do site de pesquisa de feiras livres para um formato XML mais adequado para ser &#8220;lido&#8221; por um software.</p>
<p>Pronto! A Open Table está pronta, um exemplo de query que podemos fazer é:</p>
<pre>
<div class="codecolorer-container sql twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">USE</span> <span style="color: #ff0000;">&quot;http://github.com/lfcipriani/yql-feira-livre-sp/raw/master/yql-feira-livre-sp.xml&quot;</span> <span style="color: #993333; font-weight: bold;">AS</span> feiras;<br />
<span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> feiras <span style="color: #993333; font-weight: bold;">WHERE</span> zone <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'SUL'</span> <span style="color: #993333; font-weight: bold;">AND</span> dayOfTheWeek <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'DOMINGO'</span>;</div></div>
</pre>
<p><a href="http://developer.yahoo.com/yql/console/#h=use%20%22http%3A//github.com/lfcipriani/yql-feira-livre-sp/raw/master/yql-feira-livre-sp.xml%22%20as%20feiras%3B%0Aselect%20*%20from%20feiras%20where%20zone%20%3D%20%27SUL%27%20and%20dayOfTheWeek%20%3D%20%27DOMINGO%27" target="_blank">Veja o resultado no YQL Console</a>.</p>
<p>Ou acesse o <a href="http://github.com/lfcipriani/yql-feira-livre-sp" target="_blank">todo o código no Github</a>.</p>
<h2>Conclusão</h2>
<p>Enfim, apesar de todos os problemas com as fontes de dados públicos, é possível extraí-los e convertê-los para uma representação melhor. Vimos também que serviços na Web como o Yahoo Query Language (YQL) permitem expor esses dados com uma API tão fácil quanto realizar uma simples query SQL, por meio de uma interface padronizada e única. E só com a exposição desses dados, num formato apropriado para que possamos programar com eles, teremos vários mashups gerando novos conhecimentos, sejam eles de interesse público ou não.</p>
<p>Nesta primeira parte desse artigo, cobrimos somente a Yahoo Query Language, na próxima parte iremos criar um mashup com o <a href="http://pipes.yahoo.com/pipes/" target="_blank">Yahoo Pipes</a> que irá mapear todos os endereços de feiras livres da zona da cidade que o usuário escolher. Está curioso para saber o resultado? <a href="http://pipes.yahoo.com/lfcipriani/feiraslivressp" target="_blank">Não se aflija</a>. E não perca a segunda parte na qual explicaremos como criamos esse mashup.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.talleye.com/2010/04/13/extracao-dados-publicos-com-yql-e-pipes-1/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Brincando com APIs de XMPP</title>
		<link>http://blog.talleye.com/2010/02/03/brincando-com-apis-de-xmpp/</link>
		<comments>http://blog.talleye.com/2010/02/03/brincando-com-apis-de-xmpp/#comments</comments>
		<pubDate>Thu, 04 Feb 2010 01:53:49 +0000</pubDate>
		<dc:creator>cipriani</dc:creator>
				<category><![CDATA[api]]></category>
		<category><![CDATA[xmpp]]></category>
		<category><![CDATA[bosh]]></category>
		<category><![CDATA[collecta]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[pubsub]]></category>

		<guid isPermaLink="false">http://blog.talleye.com/?p=9</guid>
		<description><![CDATA[Primeiramente, antes de ler este artigo, se quiser saber o básico sobre XMPP, leia meu artigo anterior: Breve introdução ao XMPP.
Hoje em dia, todo indivíduo envolvido com Web já consumiu alguma API HTTP, isso já é parte do dia a dia de qualquer desenvolvimento de aplicação web. Porém, nos últimos meses, começaram a aparecer alguns [...]]]></description>
			<content:encoded><![CDATA[<p>Primeiramente, antes de ler este artigo, se quiser saber o básico sobre XMPP, leia meu artigo anterior: <a title="Leia artigo introdutório sobre XMPP" href="http://blog.talleye.com/2010/02/02/breve-introducao-ao-xmpp/">Breve introdução ao XMPP</a>.</p>
<p>Hoje em dia, todo indivíduo envolvido com Web já consumiu alguma API HTTP, isso já é parte do dia a dia de qualquer desenvolvimento de aplicação web. Porém, nos últimos meses, começaram a aparecer alguns websites oferecendo APIs em outros protocolos, entre eles, o XMPP. Consumir uma API com esse protocolo é um pouco mais complicado que uma versão HTTP, mas o escopo e os benefícios obtidos são bem diferentes, como demonstraremos neste artigo.</p>
<h2>XMPP em aplicações Web</h2>
<p>Enquanto não temos suporte completo aos <a title="Especificação de websockets na W3C" href="http://dev.w3.org/html5/websockets/">websockets</a> do HTML5, que seria uma maneira de criar conexões TCP a partir do browser, a alternativa é usar a extensão <a title="Especificação do BOSH" href="http://xmpp.org/extensions/xep-0124.html">BOSH</a> do XMPP, que especifica como um cliente deve usar o XMPP via uma conexão HTTP. Vamos olhar com mais detalhe nos componentes envolvidos nesse tipo de conexão no diagrama abaixo, roubado diretamente da especificação da extensão:</p>
<pre>    Servidor XMPP
        |
        |  [unwrapped data streams]
        |
    BOSH Connection Manager
        |
        |  [HTTP + &lt;body/&gt; wrapper]
        |
    Cliente (Browser)</pre>
<ul>
<li><strong>Entre o browser e o BOSH Connection Manager</strong>: por meio de long polling ou de qualquer outra técnica <a title="Veja os tipos de técnicas Comet" href="http://en.wikipedia.org/wiki/Comet_%28programming%29">Comet</a>, o browser envia requisições HTTP que respeitam a especificação BOSH (o HTTP + &lt;body&gt; wrapper no diagrama acima) para um gerenciador de conexões (BOSH connection manager), cuja responsabilidade é identificar a sessão XMPP e manter as informações dessa sessão.</li>
<li><strong>Entre o BOSH connection manager e o servidor XMPP</strong>: o connection manager deve criar e manter uma conexão TCP para cada sessão aberta com o servidor XMPP e é dessa forma que a tradução HTTP para TCP é feita.</li>
</ul>
<p>Esse BOSH connection manager pode ser tanto um componente da sua infra quanto implementado dentro do próprio servidor XMPP. Você pode encontrar mais informações sobre esses conectores em <a href="http://xmpp.org/tech/bosh.shtml">http://xmpp.org/tech/bosh.shtml</a>.</p>
<h3>Strophejs</h3>
<p>O <a title="Website do Strophejs" href="http://code.stanziq.com/strophe">Strophejs</a> é uma biblioteca que implementa um cliente de XMPP em javascript, logo, pode ser utilizado em aplicações web. Entre as funcionalidades que essa biblioteca implementa, podemos citar:</p>
<ul>
<li>está em conformidade com a especificacão BOSH e o XMPP;</li>
<li>é cross-browser;</li>
<li>possui builders e usa jQuery, o que facilita o manuseio de XML;</li>
<li>suporta vários métodos de autenticação;</li>
<li>faz long polling e permite requisições HTTP cross-domain por meio de um componente flash;</li>
</ul>
<h2>Mashup de comparação em tempo real</h2>
<p>O objetivo dessa aplicação é permitir que o usuário possa comparar dois assuntos (palavras-chave) de sua escolha em tempo real. Por exemplo, podemos disparar uma busca para comparar as linguagens Java e Ruby em tempo real.</p>
<p>Para que isto seja possível, iremos utilizar a API XMPP do <a title="Website do Collecta" href="http://www.collecta.com">Collecta</a>, um site de busca em tempo real. A API do Collecta utiliza o modelo <a title="Especificação do PubSub" href="http://xmpp.org/extensions/xep-0060.html">Publish-Subscribe</a> para publicar os resultados de busca em tempo real para os usuários da API. Então vamos rever o cenário:</p>
<ul>
<li>Logo ao abrir o site a aplicação web connecta anonimamente no servidor XMPP por meio do Strophe;</li>
<li>O usuário entra com uma busca;</li>
<li>A aplicação web se inscreve em um nó pubsub (no caso, a busca);</li>
<li>Ao confirmar a inscricão, a aplicação web está pronta para receber os eventos publicados;</li>
<li>Ao receber um evento, a aplicação web faz um parse do XML e apresenta o resultado em HTML;</li>
<li>O usuário pode agora comparar os resultados;</li>
</ul>
<p>Todo o código deste exemplo está no <a title="acesse o projeto no Github" href="http://github.com/lfcipriani/real-time-comparison">Github</a> caso queira acompanhar e executar o exemplo. Antes de detalharmos o que acontece em cada fluxo, as dependências dessa aplicação são as seguintes:</p>
<ul>
<li>jQuery: auxilia bastante no parsing de XML;</li>
<li>flXHR.js: componente flash que permite requisições cross-domain, necessário para a aplicação se conectar num servidor XMPP em outro domínio;</li>
<li>strophejs: sem ele não conseguimos usar o XMPP;</li>
<li>dependências do strophejs: códigos para gerar md5, base64 e usar o componente flash;</li>
<li>API key do Collecta: para usar a API do Collecta você precisa de uma <a title="para requisitar a chave de API do Collecta" href="http://developer.collecta.com/KeyRequest">chave</a>.</li>
</ul>
<p>Mesmo sendo todo implementado em HTML e Javascript, é importante servir essa página em um servidor web, para que o componente flash funcione.</p>
<p>Então vamos apresentar como se implementa cada fase do fluxo dessa aplicação (o foco será apenas no código javascript):</p>
<h3>Ao abrir o site</h3>
<p>A inicialização da conexão ao servidor XMPP já é feita logo que o usuário abre o site.</p>
<pre>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// config.js</span><br />
<span style="color: #003366; font-weight: bold;">var</span> Config <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; API_KEY<span style="color: #339933;">:</span> <span style="color: #3366CC;">'YOUR_COLLECTA_API_KEY'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; BOSH_SERVICE<span style="color: #339933;">:</span> <span style="color: #3366CC;">'http://collecta.com/xmpp-httpbind'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; HOST<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;guest.collecta.com&quot;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></div></div>
</pre>
<p>No arquivo de configuração acima, temos 3 itens importantes: a chave da API, o BOSH connection manager ao qual iremos conectar (tente abrir essa URL no seu browser) e o host (servidor XMPP) que queremos conectar. Temos um problema nesse ponto, a chave da API vai ser exposta aos usuários. Para o caso da API do Collecta, o único problema seria outro usuário consumir o rate limit, mas mesmo assim o time da Collecta deve procurar alternativas ainda, uma vez que a API é nova.</p>
<pre>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// real-time-comparison.js</span><br />
<span style="color: #006600; font-style: italic;">// initiating a BOSH connection to create an anonymous connection to the Collecta XMPP server</span><br />
connection <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Strophe.<span style="color: #660066;">Connection</span><span style="color: #009900;">&#40;</span>Config.<span style="color: #660066;">BOSH_SERVICE</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
connection.<span style="color: #660066;">connect</span><span style="color: #009900;">&#40;</span>Config.<span style="color: #660066;">HOST</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> onConnect<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
</pre>
<p>Graças ao strophejs, basta criar uma conexão como é feito acima, passando o serviço BOSH que deseja usar e depois chamar a função <em>connect</em> desse objeto. Os parâmetros passados são o host desejado, o usuário (que é null porque desejamos conectar anonimamente) e a referência à função que deve ser chamada (callback) ao receber algum status do processo de conexão.</p>
<pre>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// real-time-comparison.js</span><br />
<span style="color: #003366; font-weight: bold;">function</span> onConnect<span style="color: #009900;">&#40;</span><span style="color: #000066;">status</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">status</span> <span style="color: #339933;">==</span> Strophe.<span style="color: #000066;">Status</span>.<span style="color: #660066;">CONNECTING</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// ... outros status</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">status</span> <span style="color: #339933;">==</span> Strophe.<span style="color: #000066;">Status</span>.<span style="color: #660066;">CONNECTED</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// adding one handler for each type of XMPP stanza</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; connection.<span style="color: #660066;">addHandler</span><span style="color: #009900;">&#40;</span>onPresence<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'presence'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; connection.<span style="color: #660066;">addHandler</span><span style="color: #009900;">&#40;</span>onIq<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'iq'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; connection.<span style="color: #660066;">addHandler</span><span style="color: #009900;">&#40;</span>onMessage<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'message'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Sending presence...&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// app is available to use only after sending and receiving presence from the server</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; connection.<span style="color: #660066;">send</span><span style="color: #009900;">&#40;</span>$pres<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">tree</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
</pre>
<p>A função <em>onConnect</em>, ao receber o status informando que está conectado, irá criar os 3 <em>handlers</em> necessários para tratar o recebimento de cada um dos 3 stanzas existentes no XMPP. O primeiro parâmetro é o callback de referência e depois o tipo do stanza (leia a documentação do strophejs para saber quais são os outros parâmetros). Após a criação dos handlers, em toda conexão XMPP que é feita, o cliente deve enviar um stanza de presença para o servidor. Como estamos conectando anonimamente, neste caso, após o envio desse stanza, o servidor deve retornar um stanza de presença informando o Jabber ID do usuário anônimo.</p>
<pre>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// real-time-comparison.js</span><br />
<span style="color: #003366; font-weight: bold;">function</span> onPresence<span style="color: #009900;">&#40;</span>prs<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// in this case, presence got from the XMPP server means to activate UI and allow user to enter the 2 terms to compare</span><br />
&nbsp; &nbsp; console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Got presence!&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; anonymous_jid <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span>prs<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'to'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// ... outras coisas</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
</pre>
<p>Sendo assim, quando o servidor retorna a presença, nós simplesmente parseamos o xml com jQuery e pegamos o atributo &#8220;to&#8221;, que indica pra quem o servidor está mandando essa presença, ou seja, o usuário da aplicação. É importante retornar <em>true</em> no fim desse callback, pois sem ele o strophejs irá apagar esse handler. Com o return true, o handler não será apagado e deverá ser reutilizado no próximo stanza de presença que esse cliente receber.</p>
<h3>O usuário entra com uma busca</h3>
<p>Neste momento o usuário pode entrar com a busca no campo, ao clicar no botão &#8220;Go&#8221;, a seguinte função é chamada:</p>
<pre>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// real-time-comparison.js</span><br />
<span style="color: #003366; font-weight: bold;">function</span> startComparison<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// creates 2 search subscriptions and send the request to Collecta XMPP API via Strophejs</span><br />
&nbsp; &nbsp; console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Subscribing to nodes: &quot;</span><span style="color: #339933;">+</span> terms<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">+</span><span style="color: #3366CC;">&quot; and &quot;</span><span style="color: #339933;">+</span> terms<span style="color: #009900;">&#91;</span>1<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; connection.<span style="color: #660066;">send</span><span style="color: #009900;">&#40;</span>Collecta.<span style="color: #660066;">subscribeSearchStanza</span><span style="color: #009900;">&#40;</span>terms<span style="color: #009900;">&#91;</span>0<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">tree</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; connection.<span style="color: #660066;">send</span><span style="color: #009900;">&#40;</span>Collecta.<span style="color: #660066;">subscribeSearchStanza</span><span style="color: #009900;">&#40;</span>terms<span style="color: #009900;">&#91;</span>1<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">tree</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
</pre>
<h3>Inscrição em um nó Pubsub de busca</h3>
<p>Para evitar repetição de código, criamos uma pequena biblioteca chamada Collecta que monta os stanzas necessários para inscrever e desinscrever em um nó Pubsub, que representam as buscas. Nesta biblioteca também se encontra uma função para converter os resultados de busca de XML para JSON a fim de ser usado na hora de construir o HTML para o usuário.</p>
<pre>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// real-time-comparison.js</span><br />
<span style="color: #003366; font-weight: bold;">var</span> Collecta <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; subscribeSearchStanza<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>searchName<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// generate XML for a search subscription on Collecta XMPP API</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> $iq<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>type<span style="color: #339933;">:</span> <span style="color: #3366CC;">'set'</span><span style="color: #339933;">,</span> from<span style="color: #339933;">:</span> anonymous_jid<span style="color: #339933;">,</span> to<span style="color: #339933;">:</span> <span style="color: #3366CC;">'search.collecta.com'</span><span style="color: #339933;">,</span> id<span style="color: #339933;">:</span> searchName <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; .<span style="color: #660066;">c</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'pubsub'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>xmlns<span style="color: #339933;">:</span> <span style="color: #3366CC;">'http://jabber.org/protocol/pubsub'</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #660066;">c</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'subscribe'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>node<span style="color: #339933;">:</span> <span style="color: #3366CC;">'search'</span><span style="color: #339933;">,</span> jid<span style="color: #339933;">:</span> anonymous_jid<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; .<span style="color: #660066;">up</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">c</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'options'</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #660066;">c</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'x'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>xmlns<span style="color: #339933;">:</span> <span style="color: #3366CC;">'jabber:x:data'</span><span style="color: #339933;">,</span> type<span style="color: #339933;">:</span> <span style="color: #3366CC;">'submit'</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #660066;">c</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'field'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;var&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'FORM_TYPE'</span><span style="color: #339933;">,</span> type<span style="color: #339933;">:</span> <span style="color: #3366CC;">'hidden'</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #660066;">c</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'value'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">t</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'http://jabber.org/protocol/pubsub#subscribe_options'</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #660066;">up</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">up</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">c</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'field'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;var&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'x-collecta#apikey'</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #660066;">c</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'value'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">t</span><span style="color: #009900;">&#40;</span>Config.<span style="color: #660066;">API_KEY</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #660066;">up</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">up</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">c</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'field'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;var&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'x-collecta#query'</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .<span style="color: #660066;">c</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'value'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">t</span><span style="color: #009900;">&#40;</span>searchName<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp;<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp;<span style="color: #006600; font-style: italic;">// ...</span></div></div>
</pre>
<p>O trecho de código acima apresenta como devemos criar um stanza utilizando o XML Builder implementado no strophejs. No caso dessa função, estamos criando um stanza do tipo iq para realizar a inscrição do nosso usuário (observador) em um nó PubSub. A construção desse stanza respeita a especificação PubSub do XMPP. Dê uma olhada na <a href="http://developer.collecta.com/XmppApi/RealTime/">documentação da API do Collecta</a> para ver como deve ser esse stanza que é enviado ao servidor.</p>
<h3>Confirmação da inscrição</h3>
<pre>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// real-time-comparison.js</span><br />
<span style="color: #003366; font-weight: bold;">function</span> onIq<span style="color: #009900;">&#40;</span>xml<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// in this case, the IQ stanzas handled are just subscription results</span><br />
&nbsp; &nbsp; xmlDom <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span>xml<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> iqId <span style="color: #339933;">=</span> xmlDom.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'id'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>iqId <span style="color: #339933;">==</span> terms<span style="color: #009900;">&#91;</span>0<span style="color: #009900;">&#93;</span> <span style="color: #339933;">||</span> iqId <span style="color: #339933;">==</span> terms<span style="color: #009900;">&#91;</span>1<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>xmlDom.<span style="color: #660066;">find</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'subscription:first'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">attr</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'subscription'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #3366CC;">'subscribed'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Subscribed to &quot;</span><span style="color: #339933;">+</span>iqId<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
</pre>
<p>Após enviar o stanza de inscrição, devemos esperar uma resposta do servidor. Quem processa essa resposta é o handler que tínhamos criado anteriormente. O procedimento é simples, com jQuery podemos navegar no DOM da resposta, se o id da resposta for o mesmo da busca realizada e o status da inscrição é &#8220;subscribed&#8221;, então o usuário está inscrito e agora só precisa aguardar os itens publicados.</p>
<h3>Recebendo um evento publicado</h3>
<pre>
<div class="codecolorer-container javascript twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// real-time-comparison.js</span><br />
<span style="color: #003366; font-weight: bold;">function</span> onMessage<span style="color: #009900;">&#40;</span>msg<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// messages stanzas are converted to JSON and then prepended to the correspondent panel in the UI</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> result <span style="color: #339933;">=</span> Collecta.<span style="color: #660066;">processItem</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span>msg<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i<span style="color: #339933;">=</span><span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> result.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#term'</span><span style="color: #339933;">+</span> result<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">term</span> <span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;panel&quot;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.<span style="color: #660066;">prepend</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;&amp;lt;p&amp;gt;[&quot;</span><span style="color: #339933;">+</span>result<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">category</span><span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;] - &amp;lt;a href=<span style="color: #000099; font-weight: bold;">\&quot;</span>&quot;</span><span style="color: #339933;">+</span>result<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">url</span><span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;<span style="color: #000099; font-weight: bold;">\&quot;</span> target=<span style="color: #000099; font-weight: bold;">\&quot;</span>_blank<span style="color: #000099; font-weight: bold;">\&quot;</span> title=<span style="color: #000099; font-weight: bold;">\&quot;</span> Access &quot;</span><span style="color: #339933;">+</span>terms<span style="color: #009900;">&#91;</span>result<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">term</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">+</span><span style="color: #3366CC;">&quot; information<span style="color: #000099; font-weight: bold;">\&quot;</span>&amp;gt;&quot;</span><span style="color: #339933;">+</span>result<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">title</span><span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;&amp;lt;/a&amp;gt;&amp;lt;br /&amp;gt;...&quot;</span><span style="color: #339933;">+</span>result<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">description</span><span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;...&amp;lt;br /&amp;gt;Published in &quot;</span><span style="color: #339933;">+</span>result<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">published</span><span style="color: #339933;">+</span><span style="color: #3366CC;">&quot;&amp;lt;/p&amp;gt;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
</pre>
<p>Os eventos publicados vêm em um stanza &#8220;message&#8221; e extendidos com a especificação PubSub. O único passo necessário e realizar o parse dessa resposta e convertê-lo para JSON, assim poderemos construir todo o HTML necessário para repassar esses resultados de busca para o usuário de forma mais fácil.</p>
<p>Após todo esse processo, o usuário já pode visualizar os resultados na página assim que eles forem sendo publicados no nó PubSub. Ufa!</p>
<div id="attachment_10" class="wp-caption alignnone" style="width: 310px"><a href="http://blog.talleye.com/wp-content/uploads/2010/02/Picture-10.png"><img class="size-medium wp-image-10" title="real_time_comparison" src="http://blog.talleye.com/wp-content/uploads/2010/02/Picture-10-300x151.png" alt="" width="300" height="151" /></a><p class="wp-caption-text">Screenshot da comparação Ruby e Java</p></div>
<p>Quando há a necessidade de se obter resultados em tempo real na web, o antigo modelo de puxar a informação (pull) por meio de uma requisição HTTP já não é tão eficiente, pois perde-se tanto no desempenho do servidor, que terá uma alta carga devido às inúmeras requisições desnecessárias feitas, quanto na velocidade da informação, pois entre uma requisição e outra pode-se perder o efeito tempo real desejado.</p>
<p>Está crescendo cada vez mais o push como modelo para aplicações Web, na qual o servidor deve fornecer a informação para os clientes web logo que ela for publicada. Juntamente com o modelo de push, o modelo Publish-Subscribe também está se provando efetivo, uma vez que não é só implementado em XMPP, mas também em Webhooks, Pubsubhubbub, entre outros.</p>
<p>O diferencial do XMPP neste caso é a especificação da extensão Publish-Subscribe, que é bastante detalhada e cobre vários fluxos que podem existir no modelo PubSub, além é claro dos vários servidores que já implementam este módulo. Vale a pena experimentar.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.talleye.com/2010/02/03/brincando-com-apis-de-xmpp/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Breve introdução ao XMPP</title>
		<link>http://blog.talleye.com/2010/02/02/breve-introducao-ao-xmpp/</link>
		<comments>http://blog.talleye.com/2010/02/02/breve-introducao-ao-xmpp/#comments</comments>
		<pubDate>Wed, 03 Feb 2010 00:24:38 +0000</pubDate>
		<dc:creator>cipriani</dc:creator>
				<category><![CDATA[xmpp]]></category>
		<category><![CDATA[mensageria]]></category>
		<category><![CDATA[middleware]]></category>
		<category><![CDATA[protocolo]]></category>

		<guid isPermaLink="false">http://blog.talleye.com/?p=5</guid>
		<description><![CDATA[Apesar de ser um protocolo não muito novo (sim, 10 anos não é muito novo), o número de aplicações que utilizam XMPP (Extensible Messaging and Presence Protocol) vêm crescendo substancialmente apenas nos últimos anos. Exemplos de aplicações que usam XMPP para implementar a troca de mensagens entre componentes e usuários incluem: Google Wave, Chesspark, Collecta, [...]]]></description>
			<content:encoded><![CDATA[<p>Apesar de ser um protocolo não muito novo (sim, 10 anos não é muito novo), o número de aplicações que utilizam <a title="Website do protocolo" href="http://www.xmpp.org">XMPP</a> (Extensible Messaging and Presence Protocol) vêm crescendo substancialmente apenas nos últimos anos. Exemplos de aplicações que usam XMPP para implementar a troca de mensagens entre componentes e usuários incluem: <a title="Site do Google Wave" href="https://wave.google.com">Google Wave</a>, <a title="Xadrez online Chesspark" href="https://www.chess.com/chesspark.html">Chesspark</a>, <a title="Busca em tempo real" href="http://www.collecta.com">Collecta</a>, <a title="Agregador de feeds Superfeedr" href="http://www.superfeedr.com">Superfeedr</a>, entre outros.</p>
<p>Ele muitas vezes é lembrado apenas como um protocolo para criar <em>chats</em> e restrito apenas à plataforma cliente, mas não nos prendamos a esse pensamento simplista, existe muito mais poder que pode ser extraído das mensagens trafegadas por essa camada de aplicação.</p>
<p>Segundo os autores do protocolo, o XMPP é uma tecnologia aberta para comunicação em tempo real que permite a criação de vários tipos de aplicações, tais como instanting messaging, presença, chats multi-usuários, chamadas de voz e vídeo, colaboração, middleware, content syndication e qualquer transmissão de dados via <a title="XML na wikipedia" href="http://en.wikipedia.org/wiki/XML">XML</a>. Talvez a definição mais curta possível seja: <strong>é um protocolo para a criação de middlewares orientado a mensagens</strong>. E canais de troca de mensagens existem em qualquer sistema distribuído, e acredite, XMPP pode ser usado em cada um deles, desde que, é claro, isso traga benefícios ao sistema ou ao desenvovimento.</p>
<h2>Do que é feito o XMPP?</h2>
<p>O protocolo XMPP situa-se na camada de aplicação e é comumente transportado por conexões <a title="TCP na Wikipedia" href="http://en.wikipedia.org/wiki/Transmission_Control_Protocol">TCP</a>. Ele constitui-se de XML e possui apenas 3 unidades básicas de transporte, chamados <em>stanzas</em>: <code class="codecolorer xml twitlight"><span class="xml"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;presence<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></span></code>, <code class="codecolorer xml twitlight"><span class="xml"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;message<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></span></code> e <code class="codecolorer xml twitlight"><span class="xml"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;iq<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></span></code>. Iremos apresentar brevemente cada stanza, mas se quiser mais detalhes acesse o <a title="Seção de stanzas do RFC do XMPP" href="http://xmpp.org/rfcs/rfc3921.html#stanzas">RFC do XMPP</a>:</p>
<h3>Presence</h3>
<pre>
<div class="codecolorer-container xml twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;presence</span> <span style="color: #000066;">from</span>=<span style="color: #ff0000;">&quot;cipriani@talleye.com/casa&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;status<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Ouvindo música...<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/status<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/presence<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
</pre>
<p>O stanza de presença tem a funcionalidade de notificar servidores e a lista de contatos sobre o status de um usuário na rede XMPP. Essa é uma das grandes vantagens do XMPP em relação à outros protocolos de mensageria, pois a propagação de presença faz parte da especificação e portanto deve ser implementado por clientes e servidores por padrão. No exemplo acima, o usuário <em>cipriani@talleye.com/casa</em> está notificando a rede XMPP de que ele está online, e mais, ouvindo música.</p>
<p>Outro detalhe importante é a forma de endereçamento dos stanzas, ou melhor, de que forma você identifica unicamente um usuário na rede XMPP. No exemplo, o usuário é o <em>cipriani@talleye.com/casa</em>. &#8220;cipriani&#8221; é o nome do usuário, &#8220;talleye.com&#8221; é o host ao qual esse usuário pertence e a palavra &#8220;casa&#8221; é o recurso, utiliza-se o recurso para permitir que um mesmo usuário esteja conectado ao mesmo tempo em vários clientes diferentes (o usuário poderia ter um recurso de nome &#8220;escritório&#8221; por exemplo). Esses três pedaços constituem o <strong>Jabberd ID</strong>, ou <em>JID</em>, e é utilizado em todos os tipos de stanzas.</p>
<h3>Message</h3>
<pre>
<div class="codecolorer-container xml twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;message</span> <span style="color: #000066;">to</span>=<span style="color: #ff0000;">&quot;pedro@shorteye.com/escitorio&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp;<span style="color: #000066;">from</span>=<span style="color: #ff0000;">&quot;cipriani@talleye.com/casa&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp;<span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;chat&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;body<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Cadê você?<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/body<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/message<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
</pre>
<p>No stanza acima, um usuário envia uma mensagem para outro, do tipo &#8220;chat&#8221; com o conteúdo (body) &#8220;Cadê você&#8221;. Os stanza de mensagem é enviado e o cliente não deve esperar nenhuma resposta do servidor informando que a entrega foi feita, ele apenas envia para o usuário destino ou armazena caso o usuário esteja offline.</p>
<h3>IQ (Info Query)</h3>
<pre>
<div class="codecolorer-container xml twitlight" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;iq</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;set&quot;</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;an_id&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp;<span style="color: #000066;">from</span>=<span style="color: #ff0000;">&quot;cipriani@talleye.com/casa&quot;</span></span><br />
<span style="color: #009900;"> &nbsp; &nbsp; &nbsp;<span style="color: #000066;">to</span>=<span style="color: #ff0000;">&quot;talleye.com&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;query</span> <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">&quot;jabber:iq:roster&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/iq<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
</pre>
<p>Diferente do stanza message, cada stanza iq enviado ao servidor deve obter uma resposta, por isso existe o atributo type, que pode ter valores set ou get, e como resposta o usuário recebe um outro iq de tipo result ou error, dependendo do status.</p>
<p>No caso do stanza acima, estamos requisitando ao servidor XMPP a lista de contatos de um usuário. E a tag query dentro do iq nos remete a uma outra funcionalidade do protocolo XMPP, talvez a mais importante, que são as extensões!</p>
<h2>Extensões</h2>
<p>O significado da sigla XML é Extensible Markup Language. O XMPP usa XML para implementar o protocolo. Opa, peraí, quer dizer então que eu posso extender o XMPP? Sim!</p>
<p>O desenvolvedor é livre para incluir qualquer XML dentro ou fora dos stanzas, desde que seu cliente e servidor XMPP conheçam o seu significado. Para que o protocolo não virasse bagunça e todos pudessem usufruir de servidores e bibliotecas que implementam extensões, contruiu-se uma comunidade para especificar e publicar as especificações.</p>
<p>Após 10 anos, há um número alto de exensões, por exemplo, algumas disponíveis são:</p>
<ul>
<li>Service Discovery: extensão para que um usuário possa acessar quais serviços um servidor XMPP oferece.</li>
<li>Multi-User Chat: extensão para criar salas de bate-papo multi usuários.</li>
<li>Jingle: extensão que permite chamadas via vídeo.</li>
<li>Bidirectional-streams Over Synchronous HTTP (BOSH): essa extensão permite um cliente HTTP conectar em um servidor XMPP por meio de um connection manager, cuja responsabilidade é converter uma sessão XMPP de HTTP para TCP.</li>
<li>Publish-Subscribe (PubSub): essa extensão implementa o modelo Publicador/Observador, no qual um observador pode assinar um canal do publicador. E cada vez que um item for publicado nesse canal, o observador irá recebê-lo.</li>
<li>Tem muito mais de onde essas vieram, sugiro <a title="Lista de extensões do XMPP" href="http://xmpp.org/extensions/">dar uma olhada</a>.</li>
</ul>
<h2>Por quê XMPP?</h2>
<p>Quais as razões que faria com que eu utilizasse o XMPP como protocolo ao invés de qualquer outra implementação, como <a title="AMQP na Wikipedia" href="http://en.wikipedia.org/wiki/AMQP">AMQP</a> ou até um protocolo mais simples escrito por mim mesmo?</p>
<p>Como tudo na computação, não tem nenhuma tecnologia que é boa para todos os casos, por isso a melhor resposta é aquela de sempre: depende! <img src='http://blog.talleye.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  Primeiro vamos dar uma olhada em alguns motivos que favorecem o uso do XMPP:</p>
<p>Por ter uma comunidade forte o XMPP é um protocolo sólido, vários fluxos já foram pensados, testados e é um protocolo ativo, que se adapta às necessidades dos seus usuários. Além disso ele é apoiado por bibliotecas e servidores que implementam e oferecem as principais extensões, é descentralizado (e por isso, escalável), seguro e extensível.</p>
<p>Por outro lado, dependendo da complexidade da aplicação, o XMPP pode ser muito burocrático e um protocolo mais simples é bem mais efetivo. O mesmo acontece se você tentar utilizar uma extensão XMPP quando na verdade já existe algum outro protocolo especialista em um modelo de mensagem.</p>
<p>Por experiência própria, já iniciei um sistema que nem imaginava utilizar XMPP, mas à medida que a arquitetura foi crescendo ele foi se tornando um protocolo interessante e por fim se transformou no principal componente. Enfim, o importante é conhecer suas opções, estudar e experimentar. Mas sempre tenha na sua lista o XMPP e suas extensões, pois muito do que o arquiteto de software precisa criar já está escrito em algumas de suas especificações.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.talleye.com/2010/02/02/breve-introducao-ao-xmpp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hello world</title>
		<link>http://blog.talleye.com/2010/01/31/hello-world/</link>
		<comments>http://blog.talleye.com/2010/01/31/hello-world/#comments</comments>
		<pubDate>Sun, 31 Jan 2010 14:04:27 +0000</pubDate>
		<dc:creator>cipriani</dc:creator>
				<category><![CDATA[meta]]></category>
		<category><![CDATA[blog]]></category>
		<category><![CDATA[einstein]]></category>

		<guid isPermaLink="false">http://blog.talleye.com/?p=1</guid>
		<description><![CDATA[Um amigo meu me convenceu a começar um blog.
Rá!
Piadas infames à parte, divirtam-se e colaborem.
]]></description>
			<content:encoded><![CDATA[<p>Um amigo meu me convenceu a começar um blog.</p>
<div id="attachment_7" class="wp-caption alignnone" style="width: 310px"><a href="http://blog.talleye.com/wp-content/uploads/2010/01/eu_e_einstein.jpg"><img class="size-medium wp-image-7" title="eu_e_einstein" src="http://blog.talleye.com/wp-content/uploads/2010/01/eu_e_einstein-300x199.jpg" alt="eu e o Enistein na última vez que encontrei com ele" width="300" height="199" /></a><p class="wp-caption-text">Valeu, Einstein!</p></div>
<p>Rá!</p>
<p>Piadas infames à parte, divirtam-se e colaborem.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.talleye.com/2010/01/31/hello-world/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
<!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->
