Assine os Feeds


Experimento AJAX #3 - A Propriedade responseXML

setembro 6th, 2006

Nos experimentos anteriores, publicados aqui no Viche, utilizei sómente uma das duas propriedades do objeto XMLHttpRequest que permitem acesso às respostas enviadas pelo servidor - a propriedade responseText.

Como o próprio nome indica, são respostas na forma de um texto não padronizado. Em geral é construído em um formato definido pelo desenvolvedor da aplicação, de maneira que possa ser mais facilmente manipulado para gerar conteúdo em uma página. Como por exemplo, em JSON, HTML ou texto simples sem formatação, normalmente para exibir alertas.

Já a segunda propriedade, responseXML, recebe um objeto XML que é padronizado pela W3C e pode ser manipulado pelas propriedades e métodos dos elementos DOM, através de qualquer linguagem de script.

No exemplo que será detalhado a seguir é utilizado o JavaScript para acessar e manipular o documento XML.

O Resultado do Experimento

Veja de imediato o resultado a ser alcançado, que consiste na manipulação de um objeto XML recebido através da propriedade responseXML, como dito, e apresentado na forma de uma tabela.

Se desejar, clique novamente no link acima para fechar a tabela - claro se aberta :-) - e vice-versa.

O Processo de Desenvolvimento

Penso valer a pena detalhar alguns fatos do processo de desenvolvimento, uma vez que tem um papel importante no resultado final do experimento.

Para minha “surpresa” deparei-me, de cara, com um problema no IE. Enquanto nos demais browsers testados por mim (Firefox, Opera e Netscape) obtinha o resultado esperado, no IE o resultado era nulo. Ou seja, não reconhecia a resposta como um documento XML apesar de ter no programa PHP a instrução correta para gerar o cabeçalho HTTP requerido:

header("Content-type: application/xml; charset=UTF-8");

O uso da instrução header é necessária pois o mime-type do Viche é text/html. Diante do fato fui a procura de informações na WWW, via Google, para identificar e corrigir o problema.

Encontrei vários companheiros na mesma situação e uns poucos artigos publicados com a solução. Testei algumas e, talvez por não compreender de forma adequada as explicações encontradas, continuei na mesma.

Lembrei-me, então, que o Analista de Sistemas Nailson Araújo Brito, da empresa em que trabalho, havia recentemente efetuado uma alteração em nossa Intranet com o uso da propriedade em questão e com o funcionamento correto no IE. Ao analisar o código observei que ele utilizava no método open() do objeto XMLHttpRequest, POST ao invés de GET.

Fiz a substituição e acrescentei a propriedade setRequestHeader(”header”) do objeto para alterar o mime-type do pedido, exigido ao se enviar dados através do método POST, conforme indicado abaixo:

xmlhttp.open("POST", url, true);
xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

Como o experimento a ser detalhado em seguida não exigia a passagem de parâmetros, alterei o método send() para:

xmlhttp.send('1')

E … funcionou, tanto no IE como nos demais browsers mencionados no início do artigo.

As Dúvidas

Mesmo com o problema solucionado ficaram dúvidas:

  1. É correta a solução, mesmo com o artifício utilizado no método send()?
  2. Por que o IE interpretou corretamente o objeto XML com o método POST?
  3. Qual seria a solução, nas condições do Viche (text/html), para funcionar com o método GET?

Deixo, as dúvidas, em aberto para quem quiser contribuir nos comentários e vamos, finalmente, ao que interessa.

O Experimento

O experimento consiste:

De um programa simples em PHP que gera o documento XML a partir da tabela Categories do Viche.

Do objeto XML.

De funções em JavaScript apresentadas a seguir com comentários que detalham os principais procedimentos executados.

// Cria o objeto XMLHttpRequest
function criaxmlhttp() {
   try {
      xmlhttp = new XMLHttpRequest();
   } catch(ee) {
      try {
         xmlhttp = new ActiveXObject(”Msxml2.XMLHTTP”);
      } catch(e) {
         try {
            xmlhttp = new ActiveXObject(”Microsoft.XMLHTTP”);
        } catch(E) {
            xmlhttp = false;
        }
      }
   }
}

function leXML(url) {
// Verifica se a tabela foi exibida. Se sim, ao clicar
// no link fecha - função limpaResultado()

   if (document.getElementById(”cabecalho”).hasChildNodes()) {
      limpaResultado();
      return;
   }
   criaxmlhttp();

   document.getElementById(”cabecalho”).innerHTML = “<img src=”%5C%22http:%5C/%5C/www.nghorta.com%5C/wp_aplicacoes%5C/copa2006%5C/progress.gif%5C%22″ alt=”\"\"” /> Carregando …”;

   xmlhttp.open(”POST”, url, true);
   xmlhttp.setRequestHeader(”Content-Type”, “application/x-www-form-urlencoded”);
   xmlhttp.setRequestHeader(”Cache-Control”, “no-store, no-cache, must-revalidate”);
   xmlhttp.onreadystatechange=function() {
// Verifica se o servidor enviou a resposta de forma
// correta
      if (xmlhttp.readyState == 4) {
         if (xmlhttp.status == 200) {
            limpaResultado();
            montaResultado();
         }
      }
   }
   xmlhttp.send(’1′)
}

function limpaResultado() {
//Código HTML utilizado no corpo do artigo para
// exibir a tabela
// <span id=”cabecalho”></span>
// <table id=”resultado” width=”100%”>
//     <tbody id=”r_body”>
//     </tbody>
// </table>
// O uso do elemento tbody é necessário por conta do IE
// que não aceita adicionar o elemento tr a tag table

   var header = document.getElementById(”cabecalho”);
   while(header.childNodes.length > 0) {
      header.removeChild(header.childNodes[0]);
   }
   var tabela = document.getElementById(”r_body”);
   while(tabela.childNodes.length > 0) {
      tabela.removeChild(tabela.childNodes[0]);
   }
}

function montaResultado() {
// Cria a linha de título das colunas da tabela
   var tr = document.createElement(”tr”);
// Cria a célula th
   var celula = document.createElement(”th”);
// Cria o conteúdo Id da celula
   var textoNode = document.createTextNode(’Id’);
// Adiciona o conteúdo à célula
   celula.appendChild(textoNode);
// Adiciona a célula th ao elemento tr
   tr.appendChild(celula);
   celula = document.createElement(”th”);
   textoNode = document.createTextNode(’Nome Categoria’);
   celula.appendChild(textoNode);
   tr.appendChild(celula);
   celula = document.createElement(”th”);
   textoNode = document.createTextNode(’Posts’);
   celula.appendChild(textoNode);
   tr.appendChild(celula);
// Adiciona o elemento tr à tabela
   document.getElementById(”r_body”).appendChild(tr);
// Adiciona estilo à linha
   tr.style.cssText = “background-color: #404e2a; color: #ffffff; padding: 5px; text-align: center”;

// Recebe o objeto XML
   var aDados = xmlhttp.responseXML;
// Recupera todos os elementos categoria do objeto
// XML como uma matriz
   var categorias = aDados.getElementsByTagName(”categoria”);
   for (var i = 0; i < categorias.length; i++) {
// Atribui a cat cada elemento da matriz
      cat = categorias[i];
// Recupera os valores dos nós id, nome e posts
      id = cat.getElementsByTagName(”id”)[0].firstChild.nodeValue;
      nome = cat.getElementsByTagName(”nome”)[0].firstChild.nodeValue;
      posts = cat.getElementsByTagName(”posts”)[0].firstChild.nodeValue;
// Chama a função que cria as linhas da tabela
      adicionaLinha(id, nome, posts)
   }
// Deste ponto em diante deixo para vocês
   var header = document.createElement(”h2″);
   var texto_header = document.createTextNode(”Resultado: Posts por Categoria”);
   header.appendChild(texto_header);
   document.getElementById(”cabecalho”).appendChild(header);
   document.getElementById(”resultado”).style.cssText = “border-bottom: 5px solid #404e2a;”;
}

function adicionaLinha(id, nome, posts) {
   var linha = document.createElement("tr");
   var celula = criaCelula(id);
   celula.style.cssText = "text-align: center;";
   linha.appendChild(celula);
   celula = criaCelula(nome);
   celula.style.cssText = "padding-left: 5px;";
   linha.appendChild(celula);
   celula = criaCelula(posts);
   celula.style.cssText = "text-align: center;";
   linha.appendChild(celula);
   linha.style.cssText = "color: #404e2a;";
   document.getElementById("r_body").appendChild(linha);
}

function criaCelula(texto) {
   var celula = document.createElement("td");
   var textoNode = document.createTextNode(texto);
   celula.appendChild(textoNode);
   return celula;
}

Observação Final

Para a edição dos códigos JavaScript utilizei a extensão Perfomancing do Firefox (link abaixo) que mantém a indentação ao gravar o artigo.

Mas se você utiliza o excerpt do WP, ou seja, publica apenas um trecho do artigo, e não o artigo todo, cuidado! pois você terá que fazer isto no editor do CMS. E aí, babau, a indentação vai para o espaço. Tema abordado no post Edição de Código no Wordpress

E como resolvi: simplesmente na “marra”, gravei o excerpt direto na Tabela que armazena os posts no MySQL.

Dica da extensão obtida no blog Mr. TheChessMan.

powered by performancing firefox

Categorias: AJAX, Javascript, PHP, Técnico

Imprima este artigo Envie este artigo para um(a) amigo(a) Adicionar ao del.icio.us Adicionar ao Linkk 11,921 Views



9 Comentários Adicione o seu

  • 1. Micox  |  setembro 6th, 2006 at 14:59:05

    Grande, realmente Grande post!!!!
    Parabéns!!

    Indicarei a todos que necessitarem.

  • 2. Thalis valle  |  setembro 6th, 2006 at 20:20:52

    Muito bom esse artigo. ´R raro encontrarmos algo assim. Abraços

  • 3. Lucas  |  setembro 25th, 2006 at 20:37:25

    legal seu blog, já está nos favoritos.

    Estou tentando abrir um xml tipo esse ai em baixo, porem no firefox ele nao está contando direito os nós

    *****xml

    Trabalho
    Dificl

    Trabalho02
    Faci

    ….

    *******
    usando o XMLHttpRequest
    xml = request..responseXML
    xml.firstChild.childNodes[0].childNodes.length

    ele retorna 5, ao invés do real numero de nos, 2. Ele ta contando o “ENTER” como um TEXT_NODE . Se eu colocar todo conteudo do nó em uma linha so, isso acaba, mas o xml fica uma zona pra editar. Você sabe o que se passa? valeuuu!

  • 4. Lucas  |  setembro 25th, 2006 at 20:38:11

    *****xml
    <portfolio>
    <works kind="print">
    <work>
    <title>Trabalho</title>
    <desc>Dificl</title>
    </work>

    <work>
    <title>Trabalho02</title>
    <desc>Faci</title>
    </work>
    </works>
    ….
    </portfolio>

  • 5. Rubens Borges Leal  |  setembro 27th, 2006 at 18:18:23

    Boa tarde , tudo bem ? Preciso desenvolver um site e estou estudando AJAX. O exemplo de cadastro é excelente, parabéns me ajudou muito adaptei a minha necessidade e funciona beleza com responseText. Esse segundo exemplo onde eu tenho o responseXML, teima em não funcionar. No retorno ele me traz zero . Uso o seu exemplo adaptando a minha realidade

    EX:
    xmlhttp.open(”POST”, url, true);
    xmlhttp.setRequestHeader(”Content-Type”, “application/x-www-form-urlencoded”);
    xmlhttp.setRequestHeader(”Cache-Control”, “no-store, no-cache, must-revalidate”);
    xmlhttp.onreadystatechange=function() {
    // Verifica se o servidor enviou a resposta de forma
    // correta
    if (xmlhttp.readyState == 4) {
    if (xmlhttp.status == 200) {
    // Recebe o objeto XML
    var aDados = xmlhttp.responseXML;
    // XML como uma matriz
    var categorias = ADados.getElementsByTagName”categoria”);

    qtde = categorias.length;
    xmlhttp.send(’1′)

    A Qtde sempre retorna zero. Quando informe na URLl um arquivo XML ele funciona.

    Já vasculhei pela rede e achei alguns com o mesmo problema , mas não encontrei a solução. Se vc puder me ajudar Agradeço.

    Um abraço

    Rubens B. Leal

  • 6. corsaria  |  outubro 1st, 2006 at 12:13:01

    Creo que Ajax y yo somos incompatibles. ;-)

    De todos modos miraré el código a ver si aprendo algo. Saludos. :-)

  • 7. Mr.TheChessMan  |  outubro 3rd, 2006 at 09:25:23

    Belo post e esta extensão é realmente muito boa!

    =)

  • 8. Micox  |  novembro 6th, 2006 at 08:37:11

    Respondendo: que isso Newton, você não precisa me agradecer por divulgar sua solução.
    Somos nós que devemos te agradecer por tão bem feito trabalho. Realmente facilitou pra muita gente. Obrigado aí.

    Outra coisa: Estamos com uma comunidade boa de desenvolvedores em um novo fórum: http://forum.ievolution.com.br . Passa lá e veja se te agrada. :)

  • 9. Paulo  |  agosto 13th, 2007 at 06:10:49

    Estou tentando implementar uma funcionalidade baseada na responseXML. No firefox está tudo OK, porém np IE, mesmo com as alterações sugeridas no artigo, não funciona.

Deixe seu Comentário

Obrigatório

Obrigatório, (não publicado)

São permitidas as seguintes tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Trackback this post  |  Subscribe to the comments via RSS Feed