<?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>Bruno Torres ponto netmedia-types &#187; Bruno Torres ponto net</title>
	<atom:link href="http://brunotorres.net/tag/media-types/feed" rel="self" type="application/rss+xml" />
	<link>http://brunotorres.net</link>
	<description>Textos infreqÃ¼entes sobre a web</description>
	<lastBuildDate>Thu, 24 Mar 2011 05:54:38 +0000</lastBuildDate>
	<language>pt-br</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Como fazer feeds de sites dos outros com PHP</title>
		<link>http://brunotorres.net/como-fazer-feeds-de-sites-dos-outros-com-php</link>
		<comments>http://brunotorres.net/como-fazer-feeds-de-sites-dos-outros-com-php#comments</comments>
		<pubDate>Sat, 11 Nov 2006 22:54:02 +0000</pubDate>
		<dc:creator>Bruno Torres</dc:creator>
				<category><![CDATA[feeds]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[media-types]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[rss]]></category>
		<category><![CDATA[utf8]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://brunotorres.net/2006/11/11/como-fazer-feeds-de-sites-dos-outros-com-php</guid>
		<description><![CDATA[De vez em quando recebo emails de pessoas querendo aprender como fazer pra criar feeds de sites dos outros, assim como eu jÃ¡ fiz de diversos sites que, pelo menos na Ã©poca, ainda nÃ£o disponibilizavam nenhum tipo de feed. A dificuldade para se criar feeds de sites dos outros Ã© inversamente proporcional Ã  qualidade do [...]]]></description>
			<content:encoded><![CDATA[<p>De vez em quando recebo emails de pessoas querendo aprender como fazer pra criar feeds de sites dos outros, assim como eu jÃ¡ fiz de diversos sites que, pelo menos na Ã©poca, ainda nÃ£o disponibilizavam nenhum tipo de feed.<!--<a id="gotocontentlink" href="#post-content">Pular anúncios</a>--><div class="adpostsearch">
<div>
<script type="text/javascript"><!--
google_ad_client = "pub-6502782542223555";
/* adPostSearch */
google_ad_slot = "4051981144";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div></div><!--<a name="post-content"></a>-->

<p>A dificuldade para se criar feeds de sites dos outros Ã© inversamente proporcional Ã  qualidade do cÃ³digo (X)HTML do site em questÃ£o. O problema Ã© que, em geral, os sites que tÃªm um cÃ³digo mais arrumadinho, com algum cuidado tanto com sintaxe quanto com semÃ¢ntica, muito provavelmente jÃ¡ disponibilizam seus prÃ³prios feeds.</p>
<p>Portanto, o que nos sobra sÃ£o aqueles sites que tÃªm algum conteÃºdo que nos interessa, mas cujo desenvolvedor, alÃ©m de nÃ£o saber ainda o que Ã© um feed, tambÃ©m nÃ£o faz idÃ©ia de como escrever decentemente um documento HTML.</p>
<p>O trabalho consiste basicamente de cinco passos:</p>
<ol>
<li>Pegar o cÃ³digo do site (via HTTP)
</li>
<li>Analizar o cÃ³digo e identificar onde estÃ¡ o conteÃºdo que nos interessa:
<ul>
<li>TÃ­tulo
		</li>
<li>Data de publicaÃ§Ã£o
		</li>
<li>Autor
		</li>
<li>Link
		</li>
<li>SumÃ¡rio e/ou conteÃºdo
		</li>
</ul>
</li>
<li>Criar expressÃµes regulares para isolar cada um desses dados
</li>
<li>Preparar os dados para inserÃ§Ã£o no feed
</li>
<li>Iterar pelos dados e criar, enfim, o cÃ³digo do feed
</li>
</ol>
<p>Com certeza, os passos mais complicados sÃ£o o passo 2 e o passo 3. Para eles nÃ£o hÃ¡ receita de bolo. Cada caso Ã© um caso e alguns casos podem te tirar algumas noites de sono pra resolver.</p>
<p>Vamos passo a passo. Vamos usar um site fictÃ­cio, sitesemfeed.com:</p>
<p>Comece seu cÃ³digo colocando em uma variÃ¡vel a URL onde se encontra o conteÃºdo que vocÃª deseja transformar em feed:</p>
<p><code>&lt;?php<br />
$url = &quot;http://semfeed.com/arquivo.html&quot;;</code></p>
<h3>Pegar o cÃ³digo do site via HTTP</h3>
<p>Esse passo Ã© simples. HÃ¡ duas maneiras. Uma usando <em><a href="http://br.php.net/file">file()</a></em> (ou <em><a href="http://br.php.net/file_get_contents">file_get_contents()</a></em>), que sÃ³ vai funcionar caso seu provedor de hospedagem tenha <a href="http://br.php.net/manual/en/ref.filesystem.php#ini.allow-url-fopen"><em>allow_url_fopen</em></a> habilitado o que nÃ£o Ã© muito seguro e a maioria das hospedagens, incluindo a <a href="http://brunotorres.net/descontos-dreamhost">dreamhost</a>, deixam desabilitado, e a outra usando <a href="http://br.php.net/curl">CURL</a>.</p>
<p>Para a primeira opÃ§Ã£o o cÃ³digo Ã© simples:</p>
<p>Se a sua versÃ£o do PHP for menor que 4.3.0, use o seguinte:</p>
<p><code>$content = file($url);<br />
$content = <a href="http://br.php.net/implode">implode</a>(&#39;&#39;, $content);</code></p>
<p>Caso contrÃ¡rio:</p>
<p><code>$content = file_get_contents($url);</code></p>
<p>Nesse ponto, o cÃ³digo HTML inteiro retornado pela URL do nosso site estÃ¡ na variÃ¡vel <em>$content</em>.</p>
<p>Pode ser interessante, em alguns casos, remover as quebras de linha do cÃ³digo. FaÃ§a assim:</p>
<p><code>$content = <a href="http://br.php.net/str_replace">str_replace</a>(&quot;\r&quot;, &quot;&quot;, $content);<br />
$content = str_replace(&quot;\n&quot;, &quot;&quot;, $content);</code></p>
<p>Se vocÃª precisar usar o CURL, aqui estÃ¡ uma funÃ§Ã£ozinha simples, tirada do prÃ³prio site do PHP:</p>
<p><code>function open_url($url){<br />
$curl = curl_init();<br />
curl_setopt ($curl, CURLOPT_URL, $url);<br />
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);<br />
$content = curl_exec ($curl);<br />
curl_close ($curl);<br />
return $content;<br />
}</code></p>
<p>Use assim:</p>
<p><code>$content = open_url($url);</code></p>
<p>Em qualquer um dos casos, a nÃ£o ser que o site em questÃ£o jÃ¡ esteja em UTF-8, faÃ§a:</p>
<p><code>$content = <a href="http://br.php.net/utf8_encode">utf8_encode</a>($content); //se o site for em ISO-8859-1<br />
$content = <a href="http://br.php.net/iconv">iconv</a>(&#39;windows-1252&#39;, &#39;UTF-8&#39;, $content); //caso seja windows-1252</code></p>
<p>Tente sempre com o primeiro exemplo. Se der algum problema, tente o segundo. Sites em windows-1252 frequentemente aparecem como ISO-8859-1 para os browsers. <a href="http://www.intertwingly.net/stories/2004/04/14/i18n.html">Mais sobre encodings e a diferenÃ§a entre ISO-8859-1 e windows-1252</a>.</p>
<h3>Analizar o cÃ³digo e identificar onde estÃ¡ o conteÃºdo que nos interessa</h3>
<p>Essa parte vai ser tÃ£o difÃ­cil quanto mais bizarro for o cÃ³digo do site. Para simplificar o artigo, vamos imaginar que o site tenha apenas tÃ­tulo, data, link e um sumÃ¡rio.</p>
<h4>Este Ã© o cÃ³digo que marca os tÃ­tulos:</h4>
<p><code>&lt;tr&gt;&lt;td&gt;&lt;font face=&quot;Verdana&quot; size=&quot;3&quot; color=&quot;#000FF&quot;&gt;&lt;a HREF=&quot;001.html&quot;&gt;Aqui estÃ¡ o tÃ­tulo!&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;</code></p>
<p>Claro, agradeÃ§a aos cÃ©us se o cÃ³digo que vocÃª for trabalhar for tÃ£o simples assim, com tags de fechamento, por exemplo. Frequentemente encontramos coisas muito mais bizarras por aÃ­.</p>
<p>Enfim, o que podemos usar como informaÃ§Ã£o Ãºnica para identificar o tÃ­tulo? Talvez a cor da fonte, talvez o tamanho. VocÃª vai precisar olhar o restante do cÃ³digo pra saber o que tem de Ãºnico nessa marcaÃ§Ã£o. Claro, uma classe jÃ¡ ajudaria muito, mas nÃ£o conte com isso.</p>
<p>Vamos usar a cor e o tamanho da fonte como nossos &quot;flags&quot; para os tÃ­tulos.</p>
<p>De quebra temos o link nessa mesma linha. Sorte nossa. <img src='http://brunotorres.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h4>Vamos ao cÃ³digo das datas:</h4>
<p><code>&lt;td&gt;&lt;font size=&quot;1&quot;&gt;11 de novembro de 2006&lt;/font&gt;&lt;/td&gt;</code></p>
<p>Aqui terÃ­amos um problema. VÃ¡rias outras informaÃ§Ãµes no site estÃ£o em um FONT com tamanho 1 dentro de um TD. Vamos tentar usar o formato da data para identificar as datas para o feed.</p>
<h4>Agora o cÃ³digo dos sumÃ¡rios:</h4>
<p><code>&lt;table border=0 cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;font size=&quot;2&quot; color=&quot;#000000&quot;&gt;Este Ã© o sumÃ¡rio do &lt;a href=&quot;teste.html&quot;&gt;texto&lt;/a&gt;&lt;br&gt;&lt;b&gt;cheio de marcaÃ§Ã£o estranha &lt;i&gt;&lt;/b&gt;etc e tal&lt;br&gt;&lt;br&gt;E por aÃ­ vai...&lt;/font&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</code></p>
<p>Mais uma vez, temos em diversos outros pontos do site, a mesma fonte, dentro de um TD, etc. Mas, por sorte, podemos usar a tabela com um Ãºnico TR e um Ãºnico TD como identificador para nossos sumÃ¡rios.</p>
<p>Claro que, como jÃ¡ disse, nÃ£o Ã© fÃ¡cil reproduzir as bizarrices que costumam fazer por aÃ­. Portanto, pode ser que vocÃª encontre casos muito mais complicados, quase impossÃ­veis. Mas, nesses casos, seu sucesso vai depender de sua perspicÃ¡cia. Novamente, nÃ£o tem receita de bolo&#8230;</p>
<h3>Criar expressÃµes regulares para isolar cada um desses dados</h3>
<h4>Para os tÃ­tulos e links:</h4>
<p><code><a href="http://br.php.net/preg_match_all">preg_match_all</a>(&quot;/&lt;tr&gt;&lt;td&gt;&lt;font face=\&quot;.+\&quot; size=\&quot;3\&quot; color=\&quot;#000FF\&quot;&gt;&lt;a [Hh][Rr][Ee][Ff]=\&quot;([^\&quot;]+)\&quot;&gt;(.+)&lt;\/a&gt;&lt;\/td&gt;&lt;\/tr&gt;/&quot;, $content, $tit_links);</code></p>
<p>A variÃ¡vel <em>$tit_links</em> Ã© um array contendo os resultados da busca usando a expressÃ£o regular. O Ã­ndice 0 contÃ©m a string completa, 1 contÃ©m o conteÃºdo do primeiro parÃªntese, o 2 o do segundo parÃªntese e por aÃ­ vai.</p>
<p>NÃ£o vou explicar aqui como funcionam expressÃµes regulares. Se vocÃª nÃ£o conhece o assunto, vale muito a pena aprender. HÃ¡ um <a href="http://guia-er.sourceforge.net/">guia excelente na web</a> e um <a href="http://aurelio.net/er/livro/">livro</a>, escritos pelo mesmo autor, <a href="http://aurelio.net/">AurÃ©lio Marinho Jargas</a>.</p>
<h4>Vamos Ã  ER para as datas:</h4>
<p><code>preg_match_all(&quot;/&lt;td&gt;&lt;font size=\&quot;[0-9]\&quot;&gt;([0-9][0-9]? de [A-Za-z]+ de [0-9][0-9][0-9][0-9])&lt;\/font&gt;&lt;\/td&gt;/&quot;, $content, $dates);</code></p>
<p>HÃ¡ meios de se usar expressÃµes mais complexas e menos extensas para este mesmo caso, mas procurei simplificar para tentar facilitar o entendimento.</p>
<h4>Agora os sumÃ¡rios:</h4>
<p><code>preg_match_all(&quot;/&lt;table border=\&quot;?0\&quot;? cellspacing=\&quot;[0-9]\&quot;&gt;&lt;tr&gt;&lt;td&gt;&lt;font size=\&quot;[0-9]\&quot; color=\&quot;#[0-9]+\&quot;&gt;(.+)&lt;/font&gt;&lt;td&gt;&lt;\/td&gt;&lt;\/tr&gt;&lt;\/table&gt;/&quot;, $content, $summaries);</code></p>
<p>Estou levando em conta que podem, no futuro, resolver mudar o tamanho da fonte, ou colocar aspas nos atributos que nÃ£o as tÃªm.</p>
<p>Perceba que estou usando um caso fictÃ­cio, nÃ£o testado, apenas para exemplificar. Se vocÃª nÃ£o analizar por si mesmo o site e nÃ£o entender como as expressÃµes regulares funcionam, Ã© melhor nem tentar fazer um feed.</p>
<p><strong>Mas, eu nÃ£o poderia usar um parser HTML?</strong> Talvez sim. Eu jÃ¡ fiz alguns testes e achei mais fÃ¡cil usar expressÃµes regulares. Se vocÃª teve alguma experiÃªncia boa usando um parser HTML em PHP, conte pra gente.</p>
<p><strong>Se o cara que fez o site mudar o cÃ³digo, meu feed jÃ¡ era?</strong> Yep. Esse Ã© um grande problema de feeds feitos dessa forma. Se o cidadÃ£o mudar o cÃ³digo seu feed pÃ¡ra de funcionar. Simples assim.</p>
<p><strong>E quanto ao copyright do site do camarada?</strong> Bem, tome cuidado com isso. Ã‰ melhor consultar o dono do site antes, ou entÃ£o assumir os riscos, se vocÃª tiver cara pra isso&#8230;</p>
<h3>Criando o feed</h3>
<p>Nesse ponto vamos iterar pelos itens coletados com as expressÃµes regulares e criar o cÃ³digo do feed. Vou usar o formato RSS 2.0, que Ã© mais popular.</p>
<p>O passo &quot;preparar os dados para inserÃ§Ã£o no feed&quot; vai ser feito dentro da iteraÃ§Ã£o.</p>
<p><code>&lt;?php  <br />
header(&quot;Content-type: application/xml; charset=utf-8&quot;); //Sem isso, o arquivo serÃ¡ enviado como HTML  <br />
echo &#39;&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;&#39; . &quot;\n&quot;;  <br />
?&gt;<br />
&lt;rss version=&quot;2.0&quot;&gt;<br />
&lt;channel&gt;<br />
&lt;title&gt;Site Sem Feed&lt;/title&gt;<br />
&lt;link&gt;&lt;?php echo $url ?&gt;&lt;/link&gt;<br />
?&gt;<br />
for ($i=0; $i&lt;sizeof($tit_links); $i++): //considerando que todos os arrays tem o mesmo nÃºmero de Ã­ndices, nÃ£o importa muito o tamanho de qual vocÃª pega aqui<br />
$title = $tit_links[2][$i];<br />
$link = $tit_links[1][$i];<br />
$tz_offset = -3;<br />
$date = date(&quot;D, d M Y H:i:s \G\M\T&quot;, strtotime($dates[1][$i]) + ($tz_offset * 3600)); //Isso aqui nÃ£o vai funcionar, na verdade. VocÃª vai ter que queimar a mufa pra transformar aquela data do exemplo em algo usÃ¡vel. TÃ´ sem saco pra isso agora...<br />
$summary = $summaries[1][$i];<br />
$summary = <a href="http://br.php.net/strip_tags">strip_tags</a>($summary, &#39;&lt;a&gt; &lt;br&gt;<br />
&lt;p&gt;&#39;);<br />
?&gt;<br />
&lt;item&gt;<br />
&lt;title&gt;&lt;?php echo $title ?&gt;&lt;/title&gt;<br />
&lt;link&gt;&lt;?php echo $link ?&gt;&lt;/link&gt;<br />
&lt;pubDate&gt;&lt;?php echo $date ?&gt;&lt;/pubDate&gt;<br />
&lt;description&gt;&lt;![CDATA[ &lt;?php echo $summary ?&gt; ]]&gt;&lt;/description&gt;<br />
&lt;/item&gt;<br />
&lt;?phpphp endfor; ?&gt;<br />
&lt;/channel&gt;<br />
&lt;/rss&gt;</code></p>
<p>E assim estÃ¡ feito nosso feed.</p>
<p>Antes de ter sucesso, vocÃª vai provavelmente ter que fazer diversos testes, arrancar alguns cabelos, xingar a mÃ£e do cara que fez aquele site tÃ£o bizarro e tudo mais. Mas, quem quis fazer o feed foi vocÃª, entÃ£o agÃ¼enta, malandro.</p>
<div id="crp_related"><h3>Leia tambÃ©m:</h3><ul><li><a href="http://brunotorres.net/atualizar-comentarios-sem-atualizar-feed" rel="bookmark" class="crp_title">Atualizando a quantidade de comentÃ¡rios sem atualizar o feed</a></li><li><a href="http://brunotorres.net/urls" rel="bookmark" class="crp_title">Gerenciamento de URLs &#8211; Criando URLs amigÃ¡veis</a></li><li><a href="http://brunotorres.net/bt-feedburner-subscribers" rel="bookmark" class="crp_title">BT Feedburner Subscribers &#8211; plugin para exibir a quantidade de assinantes de um feed</a></li><li><a href="http://brunotorres.net/como-mostrar-a-quantidade-de-assinantes-de-um-feed-no-seu-blog" rel="bookmark" class="crp_title">Como mostrar a quantidade de assinantes de um feed no seu blog</a></li><li><a href="http://brunotorres.net/evitando-caching-css-somente-quando-atualizado" rel="bookmark" class="crp_title">Evitando caching quando (e sÃ³ quando) o arquivo CSS for atualizado</a></li><li><a href="http://brunotorres.net/seguindo-padroes" rel="bookmark" class="crp_title">Seguindo Ã  risca os padrÃµes</a></li><li><a href="http://brunotorres.net/como-nao-contabilizar-suas-proprias-visitas-em-seu-blog-wordpress" rel="bookmark" class="crp_title">Como nÃ£o contabilizar suas prÃ³prias visitas em seu blog wordpress</a></li><li><a href="http://brunotorres.net/quem-disse-que-displaynone-esconde-conteudo-do-jaws" rel="bookmark" class="crp_title">Quem disse que display:none esconde conteÃºdo do JAWS?</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://brunotorres.net/como-fazer-feeds-de-sites-dos-outros-com-php/feed</wfw:commentRss>
		<slash:comments>34</slash:comments>
		</item>
		<item>
		<title>Quem disse que display:none esconde conteÃºdo do JAWS?</title>
		<link>http://brunotorres.net/quem-disse-que-displaynone-esconde-conteudo-do-jaws</link>
		<comments>http://brunotorres.net/quem-disse-que-displaynone-esconde-conteudo-do-jaws#comments</comments>
		<pubDate>Tue, 10 Oct 2006 06:47:02 +0000</pubDate>
		<dc:creator>Bruno Torres</dc:creator>
				<category><![CDATA[accessibility]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[media-types]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://brunotorres.net/2006/10/10/quem-disse-que-displaynone-esconde-conteudo-do-jaws</guid>
		<description><![CDATA[Hoje me deparei com um problema que me remeteu hÃ¡ uma histÃ³ria antiga, da ascensÃ£o e queda do FIR como tÃ©cnica eficiente de Image Replacement. Na Ã©poca, o FIR foi levado Ã  fogueira e deixou de ser recomendado pelos especialistas no assunto, pois o artifÃ­cio de se esconder o conteÃºdo de um SPAN usando display:none [...]]]></description>
			<content:encoded><![CDATA[<p>Hoje me deparei com um problema que me remeteu hÃ¡ uma histÃ³ria antiga, da ascensÃ£o e queda do <a href="http://www.stopdesign.com/articles/replace_text/"><acronym title="Fahrner Image Replacement">FIR</acronym></a> como tÃ©cnica eficiente de <a href="http://www.mezzoblue.com/tests/revised-image-replacement/"><em lang="en">Image Replacement</em></a>.<!--<a id="gotocontentlink" href="#post-content">Pular anúncios</a>--><div class="adpostsearch">
<div>
<script type="text/javascript"><!--
google_ad_client = "pub-6502782542223555";
/* adPostSearch */
google_ad_slot = "4051981144";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div></div><!--<a name="post-content"></a>-->

<p>Na Ã©poca, o FIR foi levado Ã  fogueira e deixou de ser recomendado pelos especialistas no assunto, pois o artifÃ­cio de se esconder o conteÃºdo de um SPAN usando <em>display:none</em> esconderia o conteÃºdo tambÃ©m de leitores de tela, notadamente do <a href="http://www.blazie.com/fs_products/software_jaws.asp">JAWS</a>, um dos mais (talvez o mais) usados leitores de tela do mundo.</p>
<p>Como leitores de tela sÃ£o extremamente difÃ­ceis de usar por pessoas que enxergam e como tinha gente importante dizendo que isso funcionava assim e ponto e que tinham testado e etcetera e tal, nunca me preocupei em verificar com minhas prÃ³prias mÃ£os (e ouvidos) se isso era realmente verdade.</p>
<p>Acontece que estou desenvolvendo um site para um portuguÃªs, que Ã© cego. Ele me pediu que, em algumas partes do site, usasse uma funÃ§Ã£o em JavaScript para alternar um determinado conteÃºdo (estilo <a href="http://www.dustindiaz.com/seven-togglers/"><em lang="en">toggle</em></a>). Como os conteÃºdos sÃ£o pequenos, nÃ£o precisei usar nada de AJAX, simplesmente deixÃ¡-los carregados (e escondidos) no HTML e, de acordo com a aÃ§Ã£o do usuÃ¡rio, esconder um elemento e mostrar outro. Simples assim.</p>
<p>Fui na onda de que o <em>display:none</em> iria esconder o conteÃºdo do JAWS&#8230;e me dei mal.</p>
<p>O cliente insistia em me dizer que o lance nÃ£o funcionava e eu nÃ£o entendia porque. Segundo ele, o leitor de tela (sim, o JAWS) estava lendo todo o conteÃºdo, mesmo o que deveria estar escondido.</p>
<p>Peguei um cafÃ© e comecei a pensar. O que poderia estar errado?</p>
<p>Simples, o JAWS ignora, sim, um determinado conteÃºdo escondido via <em>display:none</em>, <strong>a nÃ£o ser que vocÃª declare este display:none apenas para mÃ­dias visuais (<em lang="en">screen</em>, por exemplo)</strong>.</p>
<p>Veja bem. Em geral, quando aplicamos uma folha de estilos CSS a um HTML, esquecemos de declarar a(s) mÃ­dia(s) (ou <em lang="en">media type</em>) a que este CSS deve ser aplicado. Exemplo: <code>&lt;link rel="stylesheet" type="text/css" href="/c/estilo.css"&gt;</code></p>
<p>Usando o cÃ³digo acima, o estilo serÃ¡ aplicado independente da mÃ­dia. Se ela tiver suporte a CSS, este serÃ¡ aplicado. Ponto.</p>
<p>O mesmo aconteceria caso usÃ¡ssemos: <code>&lt;style type="text/css"&gt;@import url(/c/estilo.css);&lt;/style&gt;</code></p>
<p>O cÃ³digo acima costuma ser usado por aqueles que desejam que seu CSS seja ignorado por browsers antigos, como o Netscape 4, por exemplo.</p>
<p>SÃ³ que faz tempo que uso outro artifÃ­cio para esconder meus CSS das velharias (jÃ¡ que o mÃ©todo acima pode causar o que chamamos de <a href="http://www.bluerobot.com/web/css/fouc.asp"><acronym title="Flash of Unstyled Content">FOUC</acronym></a>). Declaro dois <em lang="en">media types</em>, separados por uma vÃ­rgula e um espaÃ§o. Assim: <code>&lt;link rel="stylesheet" type="text/css" href="/c/estilo.css" media="screen, projection"&gt;</code></p>
<p>E era isso que eu estava usando no site a que fiz referÃªncia acima. Retirei os <em lang="em">media types</em> e, <em lang="fr">voilÃ </em>, o JAWS passou a ignorar o conteÃºdo escondido pelo <em>display:none</em>.</p>
<p>Claro, nÃ£o quero dizer que vocÃª nÃ£o deva declarar media types ao aplicar um CSS a uma pÃ¡gina. Longe disso. O lance Ã© criar um outro CSS, apenas com os <em>display:none</em> que devam ser interpretados por leitores de tela e aplicar ao conteÃºdo sem declarar a mÃ­dia. (Preciso verificar se funcionaria usando a mÃ­dia aural).</p>
<p>Se alguÃ©m tiver disposiÃ§Ã£o e condiÃ§Ãµes de testar isso em outros leitores de tela, por favor, me conte os resultados para que eu publique aqui como referÃªncia.</p>
<p>Voltando ao FIR, acho que ele continua nÃ£o sendo uma boa forma de <em lang="en">image replacement</em>. NÃ£o porque torne o conteÃºdo inacessÃ­vel para leitores de tela, mas por outros motivos, como nÃ£o funcionar em situaÃ§Ãµes onde haja suporte a CSS e nÃ£o haja suporte a imagens.</p>
<p>Moral da histÃ³ria: por mais que especialistas te digam que alguma coisa Ã© assim e ponto final, Ã© sempre bom dar uma olhadinha e fazer os testes vocÃª mesmo para verificar. Eles podem estar errados, mesmo que seja apenas em parte.</p>
<div id="crp_related"><h3>Leia tambÃ©m:</h3><ul><li><a href="http://brunotorres.net/seu-menu-dropdown-funciona-com-o-teclado" rel="bookmark" class="crp_title">Seu menu dropdown funciona com o teclado?</a></li><li><a href="http://brunotorres.net/evitando-caching-css-somente-quando-atualizado" rel="bookmark" class="crp_title">Evitando caching quando (e sÃ³ quando) o arquivo CSS for atualizado</a></li><li><a href="http://brunotorres.net/eu-odeio-caixas-de-login-no-estilo-lightbox" rel="bookmark" class="crp_title">Eu odeio caixas de login no estilo lightbox</a></li><li><a href="http://brunotorres.net/seguindo-padroes" rel="bookmark" class="crp_title">Seguindo Ã  risca os padrÃµes</a></li><li><a href="http://brunotorres.net/mudancas-no-servico-browserfriendly-do-feedburner" rel="bookmark" class="crp_title">MudanÃ§as no serviÃ§o &#8220;BrowserFriendly&#8221; do FeedBurner</a></li><li><a href="http://brunotorres.net/como-mostrar-a-quantidade-de-assinantes-de-um-feed-no-seu-blog" rel="bookmark" class="crp_title">Como mostrar a quantidade de assinantes de um feed no seu blog</a></li><li><a href="http://brunotorres.net/o-que-importa-e-o-bom-senso" rel="bookmark" class="crp_title">O que importa Ã© o bom senso</a></li><li><a href="http://brunotorres.net/atualizar-comentarios-sem-atualizar-feed" rel="bookmark" class="crp_title">Atualizando a quantidade de comentÃ¡rios sem atualizar o feed</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://brunotorres.net/quem-disse-que-displaynone-esconde-conteudo-do-jaws/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>XHTML: pensando no futuro?</title>
		<link>http://brunotorres.net/xhtml-pensando-no-futuro</link>
		<comments>http://brunotorres.net/xhtml-pensando-no-futuro#comments</comments>
		<pubDate>Sat, 10 Sep 2005 06:17:18 +0000</pubDate>
		<dc:creator>Bruno Torres</dc:creator>
				<category><![CDATA[browsers]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[media-types]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[xhtml]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://www.brunotorres.net/?p=88</guid>
		<description><![CDATA[HÃ¡ algum tempo acompanho a discussÃ£o sobre se devemos usar XHTML ou HTML para desenvolver nossos sites hoje. JÃ¡ discuti com muitas pessoas sobre isso e a conclusÃ£o Ã© sempre a mesma, nenhuma. O principal argumento que se usa para defender o uso do XHTML Ã© que dessa maneira estarÃ­amos dando um passo a frente, [...]]]></description>
			<content:encoded><![CDATA[<p>HÃ¡ algum tempo acompanho a discussÃ£o sobre se devemos usar <acronym title="eXtensible HyperText Markup Language">XHTML</acronym> ou <acronym title="HyperText Markup Language">HTML</acronym> para desenvolver nossos sites hoje. JÃ¡ discuti com muitas pessoas sobre isso e a conclusÃ£o Ã© sempre a mesma, nenhuma.<!--<a id="gotocontentlink" href="#post-content">Pular anúncios</a>--><div class="adpostsearch">
<div>
<script type="text/javascript"><!--
google_ad_client = "pub-6502782542223555";
/* adPostSearch */
google_ad_slot = "4051981144";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div></div><!--<a name="post-content"></a>-->

<p>O principal argumento que se usa para defender o uso do XHTML Ã© que dessa maneira estarÃ­amos dando um passo a frente, pensando no futuro. Essa afirmaÃ§Ã£o nÃ£o estÃ¡ errada, XHTML Ã© sim um passo a frente, Ã© uma maneira de se pensar no futuro. Mas, para que isso seja realmente verdadeiro Ã© preciso prestar atenÃ§Ã£o a alguns detalhes.</p>
<p>Antes que alguÃ©m tire conclusÃµes precipitadas, devo dizer que sou a favor do XHTML. Escrevo este post apenas para tentar ajudar a esclarecer alguns pontos que tenho percebido nÃ£o estar muito claros na cabeÃ§a da maioria das pessoas que estÃ£o pegando o bonde dos padrÃµes web agora.</p>
<h3>XHTML enviado como text/html causa problemas</h3>
<p><a href="http://ln.hixie.ch/">Ian Hickson</a> jÃ¡ discorreu sobre os <a href="http://www.hixie.ch/advocacy/xhtml">problemas de se enviar XHTML como text/html</a> antes mesmo de eu ouvir falar em XHTML pela primeira vez. Este texto Ã© uma leitura quase obrigatÃ³ria para qualquer um que deseje entender um pouco sobre a maneira como seus documentos sÃ£o interpretados pelos browsers e pretende realmente desenvolver sites que sejam &#8220;future-proof&#8221;, ou seja, que causem o mÃ­nimo de problemas &#8212; ou nenhum, preferivelmente &#8212; no dia em que a migraÃ§Ã£o completa para XHTML for possÃ­vel.</p>
<p>Mas, Bruno, como assim? Ainda nÃ£o Ã© possÃ­vel migrar totalmente para XHTML? Eu escrevo documentos XHTML e eles funcionam muito bem em qualquer browser. Explica isso direito.</p>
<p>Bom, se vocÃª der uma boa lida no <a href="http://www.hixie.ch/advocacy/xhtml">texto</a> do Ian Hickson (pode ir lÃ¡ ler, eu espero&#8230;), vai  conseguir ter uma boa noÃ§Ã£o sobre o assunto. Mas se vocÃª Ã© preguiÃ§oso ou nÃ£o sabe inglÃªs, vou tentar explicar brevemente (e nÃ£o tÃ£o bem quanto o Ian) essa coisa toda de XHTML e HTML.</p>
<h3>Compatibilidade entre XHTML e HTML e o porquÃª dos DOCTYPEs</h3>
<p>A primeira coisa que vocÃª deve saber Ã© que <strong>o Internet Explorer 6 (e versÃµes anteriores) nÃ£o suporta XHTML. Ponto.</strong> Na verdade ele nem chega a suportar o HTML completamente. Seu XHTML funciona bem mesmo sendo enviado como se fosse HTML porque vocÃª aprendeu a escrever XHTML cumprindo as regras descritas no <a href="http://www.w3.org/TR/xhtml1/#guidelines">ApÃªndice C</a> da <a href="http://www.w3.org/TR/xhtml1/">especificaÃ§Ã£o do XHTML 1.0</a>, mesmo que inconscientemente.</p>
<p>O <a href="http://www.w3.org/TR/xhtml1/#guidelines">apÃªndice C</a> define as regras de compatibilidade entre XHTML 1.0 e HTML 4.01. SÃ£o as regras que vocÃª deve seguir para poder enviar seus documentos XHTML como text/html e assegurar que os <acronym title="User Agent">UA</acronym>s atuais consigam renderizÃ¡-lo a contento.</p>
<p>Outra coisa que vocÃª precisa colocar na cabeÃ§a e nÃ£o tirar nunca mais Ã© que o <strong>DOCTYPE nÃ£o define, <em>para o user agent</em>, o tipo de documento que estÃ¡ sendo enviado</strong>. Quem define isso Ã© o header <em>Content-Type</em> contido na resposta <acronym title="HyperText Transfer Protocol">HTTP</acronym> enviada pelo seu servidor ao UA.</p>
<p>Isso fica bem claro na seÃ§Ã£o &#8220;Why UAs can&#8217;t handle XHTML sent as text/html as <acronym title="eXtensible Markup Language">XML</acronym>&#8221; do texto do Ian Hickson. Se um documento Ã© enviado como text/html, nÃ£o hÃ¡ maneira confiÃ¡vel de detectar se seu conteÃºdo Ã© XML ou apenas mera &#8220;old-school tag soup&#8221;. Nem pelo doctype, nem pelo namespace declarado no elemento <em>html</em>, nem pela declaraÃ§Ã£o XML (que, aliÃ¡s, deve ser evitada por colocar o IE em quirks mode, explicado mais a frente), nem por qualquer outra maneira que se possa imaginar.</p>
<p>EntÃ£o para que serve o doctype? Por quÃª eu preciso declarar o danado do doctype no inÃ­cio de cada documento que escrevo para a web? Para duas coisas: poder informar a linguagem e versÃ£o usadas no documento a uma ferramenta automatizada de verificaÃ§Ã£o de validade (seja o <a href="http://validator.w3.org/"><acronym title="World Wide Web Consortium">W3C</acronym> validator</a> ou <a href="http://www.google.com/search?q=html+validator">qualquer outro</a>) e para dizer ao browser qual <em>modo de renderizaÃ§Ã£o</em> deve ser usado ao ler seu documento.</p>
<h3>Modos de renderizaÃ§Ã£o</h3>
<p><!--adsense#InsidePost468--><br />
Devo abrir um parÃªntese aqui para explicar aos desavisados o que Ã© este <em>modo de renderizaÃ§Ã£o</em>. Os browsers modernos (IE 6 incluÃ­do) usam um recurso chamado <strong>DOCTYPE Switching</strong> para decidir como renderizar um dado documento. Se vocÃª usa um doctype vÃ¡lido e completo, declarando estar usando qualquer coisa acima de HTML 4.0, os browsers vÃ£o renderizar seu documento em um modo chamado <strong>strict mode</strong> ou <strong>standards compliance mode</strong>. Neste modo de renderizaÃ§Ã£o o browser vai fazer o maior esforÃ§o possÃ­vel para renderizar o documento seguindo as especificaÃ§Ãµes (HTML ou XHTML e CSS 1 e 2). Na ausÃªncia de um DOCTYPE, ou na presenÃ§a de um que seja incompleto, invÃ¡lido ou que declare uma linguagem mais antiga (como HTML 3.2) o modo usado Ã© o que chamam de <strong>quirks mode</strong>, onde o browser &#8220;emula&#8221; a renderizaÃ§Ã£o de versÃµes anteriores, que lidavam com as &#8220;loucuras&#8221; (quirks) dos cÃ³digos <em>tag soup</em> tÃ£o comuns na web de ontem (e, infelizmente, ainda bem comuns na web de hoje).</p>
<p>Um detalhe sobre o modo de renderizaÃ§Ã£o Ã© que, no IE, se houver qualquer coisa antes do doctype &#8212; seja uma declaraÃ§Ã£o XML, um comentÃ¡rio, ou mesmo uma linha vazia &#8212; ele &#8220;chaveia&#8221; para quirks mode. Isso Ã© um bug. Alguns desenvolvedores preferem se valer disso para, propositalmente, jogar o IE6 em quirks mode para que ele renderize as pÃ¡ginas da mesma forma que o IE5. Eu prefiro nÃ£o usar este artifÃ­cio. </p>
<p>No <a href="http://opera.com/">Opera</a> (versÃµes 7.0 a 7.03), quando uma declaraÃ§Ã£o XML estiver presente e o documento for enviado como text/html, o quirks mode Ã© ativado. Talvez seja um bug tambÃ©m, mas nÃ£o tenho certeza. A partir da versÃ£o 7.1 isso nÃ£o acontece mais.</p>
<h3>Usar ou nÃ£o usar XHTML. Eis a questÃ£o</h3>
<p>Bem, voltemos ao ponto central deste texto. XHTML, da forma que Ã© usado hoje, Ã© ou nÃ£o um passo em direÃ§Ã£o ao futuro? Os documentos XHTML de hoje garantem compatibilidade futura, com os user agents de amanhÃ£ e, mais importante, ganhamos alguma coisa desenvolvendo sites em XHTML hoje, mesmo com o browser lÃ­der do mercado nÃ£o tendo suporte?</p>
<p>Vamos voltar ao texto do Ian Hickson. No texto, ele cita as vantagens do XHTML em relaÃ§Ã£o ao HTML. Basicamente as vantagens se resumem a: poder incluir conteÃºdo marcado em outros namespaces, como <a href="http://www.w3.org/Math/">MathML</a>, garantir que os documentos sejam <em>bem-formados</em> e poder processÃ¡-los com parsers XML, mais simples que os parsers SGML e os que precisam lidar com tag soup.</p>
<p>Se vocÃª nÃ£o envia seus documentos XHTML com o media type correto (application/xhtml+xml), jÃ¡ fica impossÃ­vel incluir conteÃºdo de outros namespaces nos seus documentos. Mas vocÃª pode ponderar: quem precisa de MathML hoje em dia? Ok. Mas vocÃª costuma validar seus documentos XHTML ou pelo menos verificar se sÃ£o bem formados? Se nÃ£o, vocÃª jÃ¡ invalida as outras duas vantagens do XHTML. Ou seja, nÃ£o estÃ¡ garantindo a boa formaÃ§Ã£o do documento e nÃ£o permite que ele possa ser analisado por parsers XML.</p>
<p>Quando vocÃª envia seus documentos XHTML com o media type correto, os user agents que suportam esse media type vÃ£o capturar imediatamente qualquer falha de boa formaÃ§Ã£o e mostrar um erro de XML. Mais uma vez vocÃª me interrompe e diz: eu nÃ£o quero que meus sites parem de funcionar por causa de um errinho bobo. E eu te pergunto: entÃ£o por que vocÃª usa XHTML?</p>
<p>Ao responder a esta pergunta, a maioria das pessoas diz que usa XHTML porque Ã© a linguagem do futuro da web, porque assim estÃ£o dentro dos padrÃµes e porque o XHTML as &#8220;forÃ§a&#8221; a escrever documentos semanticamente corretos e bem estruturados.</p>
<p>Ora, semÃ¢ntica e boa estruturaÃ§Ã£o nÃ£o dependem da linguagem de marcaÃ§Ã£o usada. Dependem somente do desenvolvedor. Quem disse que nÃ£o Ã© possÃ­vel escrever documentos semÃ¢nticos e bem estruturados em HTML? E quem disse que HTML nÃ£o faz parte dos padrÃµes web?</p>
<p>A Ãºltima versÃ£o do HTML, a 4.01, em sua &#8220;versÃ£o&#8221; strict, consta ainda como uma recomendaÃ§Ã£o da W3C, portanto faz parte dos padrÃµes web sim.</p>
<p>O grande problema de se usar XHTML hoje sem pensar em validaÃ§Ã£o e boa formaÃ§Ã£o Ã© que se amanhÃ£ todos os browsers passarem a suportar XHTML e todos que usam essa linguagem decidirem mudar seu media type para application/xhtml+xml, a grande maioria dos sites exibiriam apenas erros de XML.</p>
<p>Algumas pessoas torcem o nariz ao ver um site desenvolvido em HTML, mesmo sendo 4.01 Strict, mas a verdade Ã© que se vocÃª nÃ£o pode garantir a boa formaÃ§Ã£o e validade dos seus documentos XHTML, HTML 4.01 Strict Ã© a melhor opÃ§Ã£o. Nada nos impede de escrever documentos HTML seguindo as boas prÃ¡ticas de marcaÃ§Ã£o de conteÃºdo que o XHTML nos ensinou. Nada impede usarmos tag de fechamento em elementos onde ela Ã© opcional (P e LI, por exemplo) excetuando-se, obviamente os elementos vazios (BR, HR, IMG, LINK e META) e descrever elementos em que as tags de abertura e fechamento sÃ£o opcionais (HTML, BODY e HEAD), por exemplo.</p>
<p>No futuro, migrar de um HTML 4.01 Strict bem estruturado para XHTML 1.0 Strict (ou 1.1) serÃ¡ tÃ£o simples ou atÃ© mesmo mais simples que migrar de um XHTML 1.0 mal estruturado, mal formado e invÃ¡lido.</p>
<h3>ConclusÃ£o</h3>
<p>Como eu jÃ¡ disse no inÃ­cio deste texto, sou a favor do uso do XHTML. Desde que se tome o cuidado de garantir que ele seja, no mÃ­nimo, bem formado e nÃ£o vÃ¡ &#8220;quebrar&#8221; quando enviado com o media type correto.</p>
<p>O problema Ã© que para poder garantir que sua marcaÃ§Ã£o seja realmente vÃ¡lida &#8212; ou pelo menos bem formada &#8212; sempre, sem ter que validar cada pÃ¡gina criada com uma ferramenta de validaÃ§Ã£o, Ã© necessÃ¡rio trabalhar com ferramentas apropriadas para lidar com XML. Infelizmente os CMS que temos hoje a nossa disposiÃ§Ã£o pecam nesse aspecto. Sistemas legados entÃ£o nem se fala. Nesses casos, HTML 4.01 pode ser a escolha certa.</p>
<p>Pensar no futuro Ã© importante. Pensar no presente Ã© mais importante ainda. Use a ferramenta certa para que seus documentos funcionem corretamente hoje e, se quiser que eles continuem funcionando bem amanhÃ£, preste atenÃ§Ã£o Ã s especificaÃ§Ãµes, tente seguÃ­-las o mais fielmente possÃ­vel. </p>
<p>Se vocÃª usa XHTML pensando no futuro, procure garantir que seus documentos continuem funcionando no futuro. Se nÃ£o fizer isso, vocÃª nÃ£o estÃ¡ de fato pensando no futuro.</p>
<p>Agora, se vocÃª pensa que essa histÃ³ria toda de media type Ã© baboseira e nÃ£o pretende enviar seus documentos XHTML com o media type correto quando todos os user agents o suportarem, bem, desculpe nÃ£o ter avisado antes, mas este texto Ã© inÃºtil pra vocÃª.</p>
<h3>Links Interessantes</h3>
<ul>
<li><a href="http://www.hixie.ch/advocacy/xhtml">Ian Hickson: Sending XHTML as text/html Considered Harmful</a></li>
<li><a href="http://www.w3.org/TR/xhtml1/#guidelines">ApÃªndice C: como compatibilidade entre XHTML e HTML</a></li>
<li><a href="http://www.opera.com/docs/specs/doctype/">Doctype switching do Opera</a></li>
<li><a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnie60/html/cssenhancements.asp">Doctype switching do Internet Explorer</a></li>
<li><a href="http://www.mozilla.org/docs/web-developer/quirks/doctypes.html">Doctype switching do Mozilla (e browser baseados no Mozilla)</a></li>
<li><strong>[update 12/09/2005]</strong> Mais links</li>
<li><a href="http://lachy.id.au/log/2005/04/xhtml-future">Lachlan Hunt: The Future: HTML or XHTML</a></li>
<li><a href="http://lachy.id.au/log/2005/05/validation-quiz">Lachlan Hunt: Validation quiz</a></li>
<li><a href="http://lachy.id.au/log/2005/05/validation-quiz-explanation">Lachlan Hunt: Validation quiz explanation</a></li>
</ul>
<div id="crp_related"><h3>Leia tambÃ©m:</h3><ul><li><a href="http://brunotorres.net/seguindo-padroes" rel="bookmark" class="crp_title">Seguindo Ã  risca os padrÃµes</a></li><li><a href="http://brunotorres.net/mais-um-cerebro" rel="bookmark" class="crp_title">Mais um cÃ©rebro</a></li><li><a href="http://brunotorres.net/posicionamento-com-css" rel="bookmark" class="crp_title">Posicionamento com CSS: estÃ¡tico, absoluto, relativo e fixo</a></li><li><a href="http://brunotorres.net/mark-pilgrim-no-google-fazendo-o-que" rel="bookmark" class="crp_title">Mark Pilgrim no Google. Fazendo o quÃª?</a></li><li><a href="http://brunotorres.net/bfutnet-no-ar" rel="bookmark" class="crp_title">BFUT.net no ar</a></li><li><a href="http://brunotorres.net/revolucao-do-css" rel="bookmark" class="crp_title">RevoluÃ§Ã£o do CSS</a></li><li><a href="http://brunotorres.net/blogbits-podcast-8-microformatos-e-semantica" rel="bookmark" class="crp_title">Blogbits podcast #8: Microformatos e semÃ¢ntica</a></li><li><a href="http://brunotorres.net/qual-o-problema-da-w3c" rel="bookmark" class="crp_title">Qual o problema do W3C?</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://brunotorres.net/xhtml-pensando-no-futuro/feed</wfw:commentRss>
		<slash:comments>34</slash:comments>
		</item>
		<item>
		<title>Seguindo Ã  risca os padrÃµes</title>
		<link>http://brunotorres.net/seguindo-padroes</link>
		<comments>http://brunotorres.net/seguindo-padroes#comments</comments>
		<pubDate>Tue, 16 Nov 2004 17:20:00 +0000</pubDate>
		<dc:creator>Bruno Torres</dc:creator>
				<category><![CDATA[css]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[media-types]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[webstandards]]></category>
		<category><![CDATA[xhtml]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Talvez vocÃªs nem tenham reparado, mas meu site passou por uma grande mudanÃ§a nos Ãºltimos dias. A idÃ©ia era seguir de verdade os padrÃµes web, enviando XHTML como XHTML de verdade para os browsers que entendem. Como assim? Vou explicar. XHTML Ã© uma linguagem diferente do velho HTML. Na verdade Ã© uma junÃ§Ã£o de HTML [...]]]></description>
			<content:encoded><![CDATA[<p>Talvez vocÃªs nem tenham reparado, mas meu site passou por uma grande mudanÃ§a nos Ãºltimos dias.<br />
			A idÃ©ia era seguir de verdade os padrÃµes web, enviando XHTML como XHTML de verdade para os browsers<br />
			que entendem. Como assim?<!--<a id="gotocontentlink" href="#post-content">Pular anúncios</a>--><div class="adpostsearch">
<div>
<script type="text/javascript"><!--
google_ad_client = "pub-6502782542223555";
/* adPostSearch */
google_ad_slot = "4051981144";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div></div><!--<a name="post-content"></a>-->

<p>Vou explicar. XHTML Ã© uma linguagem diferente do velho HTML. Na verdade Ã© uma junÃ§Ã£o de HTML com<br />
			XML. Sendo uma linguagem diferente, o XHTML tem seu prÃ³prio MIME Type &#8211; application/xhtml+xml. Na verdade<br />
			nÃ£o faz sentido usar XHTML se vocÃª o envia com o MIME Type de HTML.</p>
<p>Mas qual a vantagem disso?</p>
<p>Na verdade, nÃ£o hÃ¡ vantagens reais perceptÃ­veis. Pelo menos nÃ£o pra mim. A Ãºnica coisa interessante Ã© que,<br />
			pelo menos na famÃ­lia Mozilla, um documento XHTML mal-formado nÃ£o Ã© exibido se o MIME Type correto for especificado.</p>
<p>Mal-formado? NÃ£o seria invÃ¡lido? NÃ£o, um documento XHTML bem-formado e invÃ¡lido serÃ¡ exibido perfeitamente. Ou seja, vocÃª precisa que todas as tags estejam devidamente fechadas e perfeitamente aninhadas, mas um id duplicado nÃ£o<br />
			evitarÃ¡ que a pÃ¡gina seja exibida. Caracteres como &#8216;&amp;&#8217;, &#8216;&lt;&#8217;, &#8216;&gt;&#8217; devem ser ser devidamente codificados na<br />
			forma de entidades HTML &#8216;&amp;amp;&#8217;, &#8216;&amp;lt;&#8217;, &#8216;&amp;gt;&#8217;, respectivamente. Existem outros caracteres que devem<br />
			ser codificados, estou citando apenas os mais comuns.</p>
<p>Mas, se nÃ£o hÃ¡ grandes vantagens em se usar esse MIME Type, por quÃª usÃ¡-lo? Bem, Ã© uma questÃ£o de escolha.<br />
			JÃ¡ que Ã© pra seguir os padrÃµes, vamos tentar seguÃ­-los da melhor forma possÃ­vel. De acordo com o<br />
			<a href="http://www.w3.org">W3C</a>, application/xhtml+xml <a href="http://www.w3.org/TR/xhtml-media-types/xhtml-media-types.xhtml#application-xhtml-xml"><strong>deveria</strong> ser usado para servir documentos XHTML para user agents que entendem XHTML</a> e os autores que quiserem suportar user agents XHTML e HTML ao mesmo tempo <strong>podem</strong> usar negociaÃ§Ã£o de conteÃºdo (vamos chamar a partir daqui de <em>content negotiation</em>) para servir documentos XHTML como application/xhtml+xml e HTML como text/html.</p>
<p>Como vocÃªs podem ver, nÃ£o Ã© obrigatÃ³rio, mas Ã© recomendado.</p>
<p>Dentre os user agents que nÃ£o entendem XHTML estÃ¡ &#8211; adivinhem quem &#8211; o, com o perdÃ£o da mÃ¡ palavra, Internet Explorer. Ainda sonho com o dia que nÃ£o vou precisar pensar neste &#8220;browser&#8221; ao desenvolver sites&#8230;</p>
<p>Existem outras complicaÃ§Ãµes ao se servir documentos XHTML como manda o figurino. Por exemplo, os anÃºncios do google nÃ£o sÃ£o exibidos em pÃ¡ginas XHTML, jÃ¡ que a funÃ§Ã£o javascript <a href="http://ln.hixie.ch/?start=1091626816&amp;count=1">document.write() nÃ£o funciona em XML</a>.</p>
<p>Bom, mas vamos ao que interessa.</p>
<h3>Content Negotiation</h3>
<p>Como eu jÃ¡ havia citado acima, nem todos os user agents &#8211; browsers, spiders, leitores de tela, etc &#8211; reconhecem o MIME Type application/xhtml+xml. Portanto, para podermos agradar a gregos e troianos, devemos utilizar uma coisa chamada <em>content negotiation</em> para identificar as capacidades do user agent e entregar o conteÃºdo de forma que ele possa entender.</p>
<p>Para os usuÃ¡rios de PHP, este processo Ã© bastante simples. Basta incluir algumas linhas de cÃ³digo no topo de seus scripts e pronto. Essas linhas eu tirei de um <a href="http://www.456bereastreet.com/archive/200408/content_negotiation/"> artigo sobre content negotiation</a> que li no site <a href="http://www.456bereastreet.com/">456 Berea Street</a>. SÃ£o elas:</p>
<p><code><br />
				&lt;?php<br />
				if (stristr($_SERVER['HTTP_ACCEPT'], "application/xhtml+xml") || stristr($_SERVER["HTTP_USER_AGENT"],"W3C_Validator")) {<br />
					header("Content-Type: application/xhtml+xml; charset=utf-8");<br />
					header("Vary: Accept");<br />
				echo("&lt;?xml version=&#92;\"1.0&#92;\" encoding=&#92;\"utf-8&#92;\"?&gt;&#92;\n");<br />
				} else {<br />
					header("Content-Type: text/html; charset=utf-8");<br />
					header("Vary: Accept");<br />
				}<br />
				?&gt;<br />
			</code></p>
<p>Vamos entender este cÃ³digo.</p>
<p>Na primeira linha verificamos se o user agent aceita application/xhtml+xml ou se o user agent Ã© o <a href="http://validator.w3.org">W3C Validator</a> &#8211; o validator nÃ£o envia um header ACCEPT, mas reconhece este MIME Type. Caso positivo, enviamos um header HTTP indicando o content-type (MIME Type) application/xhtml+xml, mais um header Vary e escrevemos o prologue XML.</p>
<p>Vary? Sim, Ã© interessante incluir este header para avisar a mecanismos intermediÃ¡rios de cache &#8211; como proxies por exemplo &#8211; que o content-type pode variar de acordo com o cliente que estÃ¡ fazendo a requisiÃ§Ã£o.</p>
<p>Caso negativo &#8211; o user agent nÃ£o aceita application/xhtml+xml e nÃ£o Ã© o validator &#8211; enviamos um header content-type indicando text/html e o header Vary. Perceba que neste caso nÃ£o escrevemos o prologue XML, jÃ¡ que ele pode causar problemas, principalmente naquele programinha (o do Ã­cone azul) daquela empresa de Redmond que muitos teimam em chamar de browser.</p>
<p>Este cÃ³digo nÃ£o Ã© completo. AlÃ©m de verificar a capacidade do user agent de reconhecer application/xhtml+xml, deverÃ­amos tambÃ©m levar em conta o q-rating. Q-rating Ã© uma forma de o user agent informar suas preferÃªncias por MIME Types, charsets, etc. O artigo <a href="http://www.autisticcuckoo.net/archive.php?id=2004/11/03/content-negotiation">Content Negotiation</a>, de Tommy Olsson explica passo a passo como reconhecer as capacidades do user agent e, levando em conta o q-rating, servir o conteÃºdo da forma mais adequada. Vale a pena a leitura.</p>
<p>E se eu tiver, alÃ©m dos scripts PHP, arquivos XHTML puros? Bom, neste caso ou vocÃª deixa que eles sejam servidos como text/html ou entÃ£o usa um artifÃ­cio do apache para fazer como que seus arquivos .html sejam interpretados pelo PHP. Ainda tirado do artigo supracitado:</p>
<p><code><br />
				RemoveHandler .html .htm<br />
				AddType application/x-httpd-php .html<br />
			</code></p>
<p>Isto deve ser incluÃ­do dentro do seu arquivo <a href="http://httpd.apache.org/docs-2.0/howto/htaccess.html">.htaccess</a>. Para que isso funcione, Ã© necessÃ¡rio que o servidor aceite este tipo de configuraÃ§Ã£o nos arquivos .htaccess. Se tiver dÃºvidas, consulte o administrador.</p>
<h3>E o Google Adsense?</h3>
<p>Para quem exibe anÃºncios do google em seu site, servir arquivos XHTML como application/xhtml+xml pode ser uma grande dor de cabeÃ§a. JÃ¡ que o google usa a um javascript, com funÃ§Ãµes document.write() para escrever o conteÃºdo de seus anÃºncios dentro de um &lt;iframe&gt; dentro da sua pÃ¡gina e <a href="http://ln.hixie.ch/?start=1091626816&amp;count=1">document.write() nÃ£o funciona em XML</a> e documentos XHTML sÃ£o XML, os anÃºncios nÃ£o sÃ£o exibidos em pÃ¡ginas servidas com o MIME Type correto.</p>
<p>Mas, felizmente, existe <a href="http://keystonewebsites.com/articles/adsense.php">uma maneira de contornar este problema</a>.</p>
<p>O que se deve fazer Ã© criar um documento HTML (servido com o MIME Type text/html) e incluÃ­-lo dentro da sua pÃ¡gina utilizando um &lt;object&gt;</p>
<p>Tirado do artigo <a href="http://keystonewebsites.com/articles/adsense.php">making AdSense work with XHTML</a>, do site <a href="http://keystonewebsites.com">Keystone Websites</a>:</p>
<p>Note que o caractere &#187; marca uma quebra de linha que foi inserida apenas por questÃµes de espaÃ§o e deve ser desconsiderada</p>
<p><code><br />
				&lt;?php header("Content-Type: text/html;charset=utf-8"); ?&gt;<br />
				&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"&gt;<br />
				&lt;html lang="pt"&gt;<br />
				&#160;&#160;&lt;head&gt;<br />
				&#160;&#160;&#160;&#160;&lt;title&gt;AnÃºncios&lt;/title&gt;<br />
				&#160;&#160;&#160;&#160;&lt;style type="text/css"&gt;<br />
				&#160;&#160;&#160;&#160;&#160;&#160;body { margin: 0; padding: 0; }<br />
				&#160;&#160;&#160;&#160;&lt;/style&gt;<br />
				&#160;&#160;&lt;/head&gt;<br />
				&#160;&#160;&lt;body&gt;<br />
				&#160;&#160;&#160;&#160;&lt;script type="text/javascript"&gt;<br />
				&#160;&#160;&#160;&#160;&#160;&#160;ParÃ¢metros normais do AdSense<br />
				&#160;&#160;&#160;&#160;&lt;/script&gt;<br />
				&#160;&#160;&#160;&#160;&lt;script type="text/javascript" src="http://pagead2.googlesyndication.com/ &#187;<br />
pagead/show_ads.js"&gt;<br />
&lt;/script&gt;<br />
				&#160;&#160;&lt;/body&gt;<br />
				&lt;/html&gt;<br />
			</code></p>
<p>A primeira linha envia um header content-type text/html. E o restante Ã© HTML comum, com o cÃ³digo que vocÃª pega do google para incluir na sua pÃ¡gina.</p>
<p>Salve este arquivo, por exemplo, como adsense.php e inclua no local desejado na sua pÃ¡gina da seguinte forma:</p>
<p><code><br />
				&lt;object data="/adsense.php" type="text/html"&gt;&lt;/object&gt;<br />
			</code></p>
<p>Se vocÃª quiser usar content negotiation, inclua as seguintes linhas, em PHP:</p>
<p><code><br />
				&lt;div class="adsense"&gt;<br />
				&lt;?php<br />
				if($mime == "application/xhtml+xml") {<br />
				&#160;&#160;&#160;&#160;print "&#160;&#160;&lt;object data=\"/adsense.php\" type=\"text/html\"&gt;&lt;/object&gt;\n";<br />
				} else {<br />
				?&gt;<br />
				&#160;&#160;&lt;script type="text/javascript"&gt;<br />
				&#160;&#160;&#160;&#160;Parametros normais do AdSense<br />
				&#160;&#160;&lt;/script&gt;<br />
				&#160;&#160;&lt;script type="text/javascript" <br />
src="http://pagead2.googlesyndication.com/ &#187;<br />
pagead/show_ads.js"&gt;<br />
&lt;/script&gt;<br />
				&lt;?php<br />
				}<br />
				?&gt;<br />
				&lt;/div&gt;<br />
			</code></p>
<p>Note que usamos uma variÃ¡vel $mime, para verificar o MIME Type. cabe a vocÃª usar o que aprendeu neste artigo para atribuir o valor certo a esta variÃ¡vel.</p>
<p>Problema resolvido. Mas tem uma outra questÃ£o. Se vocÃª usar mais de um bloco de anÃºncios na sua pÃ¡gina, pode acontecer de anÃºncios que foram exibidos no primeiro bloco, se repetirem nos prÃ³ximos, jÃ¡ que usando o &lt;object&gt; o google nÃ£o vai conseguir determinar a ordem dos blocos na sua pÃ¡gina. Na verdade ele nem vai conseguir saber que vocÃª estÃ¡ usando mais de um bloco. NÃ£o Ã© nada demais, mas Ã© bom avisar.</p>
<h3>ConclusÃ£o</h3>
<p>Se vocÃª estiver afim de seguir os padrÃµes de verdade, mesmo que nÃ£o tenha de inÃ­cio nenhuma vantagem aparente, acredito que este artigo pode ajudÃ¡-lo bastante nesta tarefa.</p>
<p>Recomendo a leitura dos artigos linkados aqui. Eles sÃ£o em inglÃªs mas serviram como base para que eu pudesse usar estas tÃ©cnicas e tambÃ©m para a elaboraÃ§Ã£o deste artigo.</p>
<p>Outras mudanÃ§as foram feitas no site alÃ©m do MIME Type. Agora estou usando UTF-8 ao invÃ©s de ISO-8859-1, dei uma enxugada no cÃ³digo XHTML para que ficasse mais legÃ­vel e mais fÃ¡cil de manter e tambÃ©m estou usando um esquema de templates e um arquivo PHP apenas para cuidar da manipulaÃ§Ã£o de todas as URLs e gerenciar o conteÃºdo. Mas explicaÃ§Ãµes sobre estas mudanÃ§as ficam para um artigo posterior.</p>
<p>Espero que este artigo os ajude. Infelizmente os comentÃ¡rios ainda estÃ£o desabilitados. Esta semana ainda devo reabilitÃ¡-los.</p>
<div id="crp_related"><h3>Leia tambÃ©m:</h3><ul><li><a href="http://brunotorres.net/xhtml-pensando-no-futuro" rel="bookmark" class="crp_title">XHTML: pensando no futuro?</a></li><li><a href="http://brunotorres.net/evitando-caching-css-somente-quando-atualizado" rel="bookmark" class="crp_title">Evitando caching quando (e sÃ³ quando) o arquivo CSS for atualizado</a></li><li><a href="http://brunotorres.net/posicionamento-com-css" rel="bookmark" class="crp_title">Posicionamento com CSS: estÃ¡tico, absoluto, relativo e fixo</a></li><li><a href="http://brunotorres.net/como-nao-contabilizar-suas-proprias-visitas-em-seu-blog-wordpress" rel="bookmark" class="crp_title">Como nÃ£o contabilizar suas prÃ³prias visitas em seu blog wordpress</a></li><li><a href="http://brunotorres.net/quem-disse-que-displaynone-esconde-conteudo-do-jaws" rel="bookmark" class="crp_title">Quem disse que display:none esconde conteÃºdo do JAWS?</a></li><li><a href="http://brunotorres.net/urls-again" rel="bookmark" class="crp_title">URLs amigÃ¡veis &#8211; esclarecendo dÃºvidas</a></li><li><a href="http://brunotorres.net/urls-php" rel="bookmark" class="crp_title">Gerenciamento de URLs com PHP</a></li><li><a href="http://brunotorres.net/caching-feeds" rel="bookmark" class="crp_title">Implementando caching em feeds RSS/ATOM</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://brunotorres.net/seguindo-padroes/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
	</channel>
</rss>

