sábado, 8 de dezembro de 2012

Javascript: Carregando e Usando Arquivos XML

1. Carregando um Arquivo XML

Para carregar um arquivo XML é simples, basta utilizar um objeto XMLHttpRequest e isso facilitará seu trabalho. Veja o código abaixo:

function xmlLoader(url){
  var Loader = new XMLHttpRequest(); 

  Loader.open("GET", url, false);
  Loader.send();
  return Loader.responseXML;
}



A função basicamente cria um objeto XMLHttpRequest e configura para receber os dados do XML via método GET. A url é o local onde está o arquivo XML. O terceiro parâmetro é se o processo é assíncrona, que neste caso é falso, ou seja, na hora que eu dar o comando send, ele só vai continuar o processamento depois que carregou. Esse tipo de procedimento não é recomendado quando tem arquivos grandes, pois a página ficará "travada" até que o carregamento termine. Então outra opção é substituir por uma requisição assíncrona, que apesar de fazer com que tenha que verificar se o arquivo foi ou não carregado, permite que o usuário possa fazer outras coisas que não envolve esse arquivo. Vamos ver um exemplo assíncrono:

function xmlLoaderAsync(url,callback){
  
var Loader = new XMLHttpRequest();
   Loader.onload = callback;
  
Loader.open("GET", url, true);
   Loader.send();

}


Aqui podemos ver que a função ganhou um parâmetro chamado callback, que vai ser uma função de resposta que vai ser executado quando o arquivo for carregado. Também ele não retorna o responseXML, como na primeira, uma vez que não é certeza que o arquivo já vai estar carregado para poder dar o retorno. Neste caso, quem fica com a responsabilidade de tratar o responseXML é a função callback. Vamos dar uma olhada de como é a estrutura do callback:

function xmlCarregada(){
  var xmlC  = this.responseXML;
  //Faça algo com o xmlC aqui
}
xmlLoaderAsync("meuXml.xml",xmlCarregada);

Como pode ver, a função de callback trata o responseXML como se fosse próprio, uma vez que essa função torna-se propriedade da XMLHttpRequest. Então basta dentro dessa função, realizar o parser.

2. Realizando o Parser de um XML
Realizar um parser quer dizer, transformar os dados XML em dados que eu possa manipular no computador. Geralmente, cada parser tem que ser implementado de acordo com as suas necessidades, isso dá mais agilidade ao programa, pois não precisa criar objetos intermediários para armazenar. Entretanto, é um trabalho mais forçado, pois a cada projeto vai necessitar implementar um Parser.
Aqui vou criar um parser genérico, ele vai transformar cada nó do XML em um objeto em que eu posso acessar de um modo computacionalmente confortável do que gerando um parser direto. Vamos ao código na qual já deixei comentado:

function xmlMontarArvore(xmlNode){
   //Criei um novo Array que guardará os nós da árvore
 var arvore = new Array();
       
 //Aqui começo a percorrer os nós filhos
 for(var i=0;i<xmlNode.childNodes.length;i++){
    /*Esse if é para poder ignorar os espaços em branco, que dependendo do navegador, pode ser considerado um nó */
    if(xmlNode.childNodes[i].nodeType == 1){
       //Aqui faço a verificação se ele tem filhos ou não
       if(xmlNode.childNodes[i].childNodes.length==0){
         /*se não tiver filhos eu verifico os atributos que o nó possa ter. Nesse caso, os atributos vão ficar em uma string com o formato "(nomeDoAtributo = valorDoAtributo)" para cada atributo.*/
         var atri="";
         for(var z=0;z<xmlNode.childNodes[i].attributes.length;z++){
           var atrib = xmlNode.childNodes[i].attributes[z];
           atri = atri + "(" + atrib.nodeName + " = " + atrib.nodeValue + ")";
         }
         /*Agora coloco o nó na árvore, aqui criando um objeto anônimo com os atributos value, com o valor do nó, atr com os atributos e child sempre com valor nulo */
         arvore.push({value:xmlNode.childNodes[i].nodeValue, atr:atri, child:null});
       }else if(xmlNode.childNodes[i].childNodes.length>0){
         /*Caso o nó tenha filhos, eu pego os atributos que nem anteriormente*/
         var atri = "";
         for(var z=0;z<xmlNode.childNodes[i].attributes.length;z++){
            var atrib = xmlNode.childNodes[i].attributes[z];
            atri = atri + "(" + atrib.nodeName + " = " + atrib.nodeValue + ")";
         }
         /*E aqui insiro o nó. O campo value vai receber o valor do primeiro nó filho, os atributos serão o que ele encontrou e no campo child, vai ser a árvore dos filhos, ou seja, uso essa mesma função recursivamente até encontrar todos os nós-folhas*/
         arvore.push( { value:xmlNode.childNodes[i].firstChild.nodeValue, atr:atri, child:xmlMontarArvore(xmlNode.childNodes[i])});
      }
    }
  }
  return arvore;

}

Então pessoal, esse foi o tutorial para manipulação de XML no Javascript.

Um comentário: