Leitura de arquivos XML utilizando JavaScript/ DOM

Desde o lançamento do Internet Explorer 5, que segundo a Wikipédia foi em março de 1999, foi introduzido o suporte à linguagem XML, permitindo a manipulação e leitura de arquivos XML. Esse suporte é uma analisador conhecido como XML Parser. O XML Parser analisa e armazena o documento na memória, que pode ser acessado utilizando JavaScript.

Mais não é somente o Internet Explorer que possui suporte para manipulação de XML, o Firefox e todos os navegadores mais modernos também têm.

Para carregar uma string ou um arquivo XML existem duas formas, uma para o Internet Explorer e outro para os demais navegadores como o Firefox.

Nesse primeiro artigo será realizado apenas a leitura dos nós, atributos e valores, no próximo será realizado manipulações como: criar, inserir, remover e alterar os nós, valore e tributos

Para o Internet Explorer, primeiro devemos criar um novo objeto através do ActiveX, em seguida desativar o método asynchronized, para que o navegador congele a execução do script até o carregamento total do arquivo XML e finalmente iniciar o carregamento do arquivo XML para a mémoria, para carregar um arquivo XML deve-se utilizar o load() e caso seja uma string (texto) utilize o loadXml().

xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async="false";
xmlDoc.load("documento.xml"); // caso seja uma estring utilize loadXml(string)

Em outros navegadores incluindo o Firefox existem ainda, mais duas formas para se trabalhar com XML, uma é com string e outra é com arquivos XML. A forma para carregar um arquivo XML nesses navegadores é semelhante à anterior, se diferenciado apenas pelos comandos. Primeiroé necessário criar um objeto XML, depois desativar o método asynchronized, pelo mesmo motivo informado na forma anterior e em seguida executar o comando load() para iniciar o carregamento.

xmlDoc=document.implementation.createDocument("","",null);
xmlDoc.async="false";
xmlDoc.load("documento.xml");

Para trabalhar com strings no Firefox e outros navegadores, utilizamos o comando DOMParser() para criar o objeto, e em seguida passamos a string para carregar

parser=new DOMParser();
xmlDoc=parser.parseFromString(string,"text/xml");

Para facilitar o carregamento de um arquivo XML, será criado uma função em JavaScript, utilizando o try e catch, identificando a forma correta de carregar o arquivo XML de acordo com o navegador. Salve esse arquivo em uma página JS, assim quando for utiliza-lo, basta somente incluí-la. Eu salvei com o nome de loadXMLDoc.js.

function loadXMLDoc(docname)
{
try //Tenta com o Internet Explorer
{
xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
}
catch(e)
{
try // Caso de erro tentar com o Firefox, Mozilla, Opera, etc.
{
xmlDoc=document.implementation.createDocument("","",null);
}
catch(e) {alert(e.message)}
}
try
{
xmlDoc.async=false;
xmlDoc.load(docname);
return(xmlDoc);
}
catch(e) {alert(e.message)}
return(null);
}

Como já foi explicado como carregar o arquivo XML para a memória do navegador, agora éhora de aprender a manipulá-lo. Para manipula-lo será utilizado JavaScript juntamente com DOM. O DOM fornecer um acesso à estrutura e conteúdo do documento.

O arquivo XML é composto por uma estrutura de TAGs, essas TAGs possuem TAGs pai, TAGs filhas, que também possuem, e são TAGs irmãs, como em uma arvore genealógica. Uma TAG pai pode possui diversas TAGs filhas, sendo essas TAGS filhas também irmãs uma das outras. Em DOM essas TAGs são conhecidas como nós, sendo assim, os nós pais podem também possui diversos filhos, tendo assim também irmãos. Sempre que fala em nó estarei falando em TAG.

  • Na estrutura de nós, o nó superior é chamado de nó raiz
  • Cada nó, exceto o nó raiz, tem exatamente um nó pai
  • Um nó pode ter qualquer número de filhos
  • Irmãos são os nós que possuem o mesmo pai

No XML Document Object Model (DOM), cada nó é um objeto. Objetos possuem métodos (funções) e propriedades (Informação sobre o objeto), que pode ser acessado e manipulado por JavaScript. Vejas os principais atributos na tabela abaixo

Propriedade Tipo Descrição
nodeName String O nome do nó
nodeValue String O valor do nó
nodeType Number O tipo do nó (elemento, texto, comentário…)
parentNode Node O elemento pai
childNodes NodeList A coleccção de nós filhos
firstChild Node O primeiro filho. null se não existir
lastChild Node O último filho. null se não existir
previousSibling Node O irmão anterior
nextSibling Node O irmão seguinte
attributes NamedNodeMap A colecção de atributos
ownerDocument Document O documento a que pertence o nó

As três primeiras propriedades são muito importantes para obter informações sobre os nós. As demais são utilizadas para navegar e obter um nó especifico. Dentre as propriedades acima uma que merece atenção é a nodeType, que retornar o tipo de nó. Ela é muito importante, pois navegadores como Firefox e outros podem reconhecer espaços ou linhas em branco como sendo um nó, então utilizamos o nodeType para testar o nó e descobrir se ele é realmente um nó (elemento) utilizado em arquivos XML.

Propriedade do nodeType

O nodeType especifica o tipo de nó e é somente leitura. O mais importante tipos de nó são:

Tipo de nó NodeType
Elemento 1
Atributo 2
Texto 3
Comentário 8
Documento 9

Alguns métodos para manipular os nós

Método Retorna Descrição
getAttribute(strName) Element

Retornar o atributo

getNamedItem() Element Retorna o nó especificado (por nome).
getElementsByTagName(tagname) NodeList Retorna diversos objetos com a tag específicada em uma array. Informarmos uma tag e temos todas aquelas que constam na página.

Dessa tabela de métodos utilizaremos mais o método getElementByTagName(nó). Como o arquivo XML e composto por diversos nós, esse método pegar todos os nós que constam na página e gerar uma array, esses nós são organizado em uma lista onde cada nó receber um índice, esses índices servem para organizar e pode acessar determinado nó, o índice sempre começa com zero, essa lista gerada é conhecida como NodeList. Existem três maneiras de acessar essa lista.

  1. Utilizando o getElementByTagName(nó) seguido por um valor do índice, como por exemplo, para acessar o primeiro nó especificamos getElementByTagName[0], ou para acessar o segundo nó getElementByTagName[1].
  2. Como todos os nós estão em uma lista, podemos recuperá-lo através de um comando de repetição, como o caso do comando for
  3. E ainda usando o getElementByTagName(nó) para pegar um determinado nó e utilizar os atributos que serão citados em uma tabela abaixo para navegar pelos nós, como por exemplos o pegar o segundo filho, ou terceiro pai.

Como já foi criada uma função no inicio para carregar o arquivo XML, é necessário agora inclui essa função dentro da tag HEAD, depois chamá-la passando a localização do documento XML, por questão de segurança o documento XML só será carregado se estiver no mesmo domínio que esta sendo executado o script, caso contrário, ocorrera um erro informando aceso negado.

<script type="text/javascript" src="loadXMLDoc.js">
xmlDoc.load("documento.xml");

Supondo que a estrutura do arquivo XML, armazenado na variável xmlDoc seja:

<root>
<nopai atributo=”PrimeiroFilho”>
<nofilho>Texto do primeiro nó filho</nofilho>
<nofilhoeirmao>Texto do primeiro nó filho e irmao</ nofilhoeirmao >
</nopai>
<nopai atributo=”SegundoFilho”>
<nofilho>Texto do segundo nó filho </nofilho>
<nofilhoeirmao>Texto do segundoo nó filho e irmao</ nofilhoeirmao >
</nopai>
<nopai atributo=”TerceiroFilho”>
<nofilho>Texto do terceiro nó filho </nofilho>
<nofilhoeirmao>Texto do terceiro nó filho e irmao</ nofilhoeirmao >
</nopai>
</root>

A propriedade parentNode é o nó pai ou seja a TAG <nopai>.
A propriedade childNodes são todos os filhos do nó pai, ou seja as três tags <nofilho> e as três <nofilhoeimao>
A propriedade firstChild é o primeiro filho do nó pai, ou seja a tag <nofilho>
A propriedade lastChild é o último filho do nó pai, ou seja a última tag <nofilhoeirmao>
A propriedade attributes são os atributos atributo=”"

Depois de identificado o nó, utilizamos:

A propriedade nodeValue é o valor do nó, ou seja, o texto “Texto” do nó filho <nofilho>
A propriedade nodeName é o nome do proprio nó
A propriedade nodeType é o tipo de nó

Acessando os nós

O texto está armazenado nos nós filhos <nofilho>, para acessar-lo e necessário primeiro utilizar o método getElementByTagName(“nofilho”) acompanhador do índice 0 para pegar o primeiro no <noFilho>, em seguida utilizar o atributo childNodes para acessar os nós filhos, e para retornar o valor do nó utilizamos o atributo nodeValue, resultando na seguinte declaração:

texto = xmlDoc.getElementsByTagName("nofilho")[0].childNodes[0].nodeValue;
document.write(texto);

Após a execução da declaração a variável texto vai ter o valor da primeira tag <nofilho>, ou seja, o valor “Texto do primeiro nó filho” isso porque:

xmlDoc é a estrutura XML armazenada na memória
getElementsByTagName(“nofilho”)[0] pegar somente o primeiro nó <nofilho>.
childNodes[0] acessa o primeiro nó filho
nodeValue retorna o valor ou texto do nó
document.write(texto) escrever o valor do nó na tela

Para acessar e pegar o valor do segundo nó filho <nofilhoeirmao>, basta apenas passa-lo para o método getElementByTagName()

texto = xmlDoc.getElementsByTagName("nofilhoeirmao")[0].childNodes[0].nodeValue;
document.write(texto);

No primeiro exemplo foi pego apenas o primeiro nó filho <nofilho>, de cada nó pai, pois informamos o número do índice ([0]) junto com o método getElementByTagName() , mas no arquivo XML existem três nós filhos <nofilho>. Para pode acessar e retonar todos os nós filho <nofilho>, é só utilizar um comando de repetição ou loop, como o caso do loop for, onde será retornado todos os nós filhos

x=xmlDoc.getElementsByTagName("nofilho");
for (i=0; i<x.length; i++)
{
document.write(x[i].childNodes[0].nodeValue);
document.write("<br />");
}

Você deve ter percebido que estamos apenas pegando os valores dos primeiros nós filhos <nofilho>, de cada nó pai <nopai>, sendo de cada nó pai existem três nós filhos. Para pega todos os nós filhos de um pai incluindo o nó filho e irmão <nofilhoeirmao> que também é um filho, devemos:

Primeiro pegar o nó pai <nopai> e depois acessar todos os nós filhos, sendo os nós <nofilho> e <nofilhoeirmao> e armazena-los na variável X, essa variável terá a lista com todos os nós filhos do nó pai, e será utilizada como parâmetro do comando de repetição for.

x=xmlDoc.getElementsByTagName("nopai")[0].childNodes;

Segundo acessar o nó pai <nopai> e com o atributo firstChild acessar o primeiro filho, e armazena-lo na variável y:

y=xmlDoc.getElementsByTagName("nopai")[0].firstChild;

A variavel y vai acessar o primeiro filho, depois de acessa o primeiro nó filho, será utilizado o atributo nextSibling para ir acessando os próximos filhos. Mas como já sabemos o Firefox pode interpretar espaços vazios como sendo um nó, isso pode atralhar e da erro no script, ja que teremos que acessar nó por nó, então antes de retornar o valor, vamos criar um teste com base na propriedade nodeType para sabe se realmente é um nó, como vimos um nó é um elemento, e todo elemento tem valor igual a 1 na propriedade nodeype, então:

if (y.nodeType==1) {
document.write(y.childNodes[0].nodeValue + "<br />");
}

Nó final da declaração, como ja foi retornado o primeiro valor do nó filho, será utilizado o nextSibling para acessar o próximo nó filho

y.nextSibling;

Ao final de tudo a declaração deve ser assim;

x=xmlDoc.getElementsByTagName("nopai")[0].childNodes;
y=xmlDoc.getElementsByTagName("nopai")[0].firstChild;
for (i=0;i<x.length;i++)
{
if (y.nodeType==1)
{
document.write(y.childNodes[0].nodeValue + "<br />");
}
y=y.nextSibling;
}

Como avança e volta um nó

Veja o exemplo aqui. A função getElementByTagName() armazena todos os nós em uma array, essa array como foi visto logo no inicio pode ser acessado pelo valor do índice, que sempre começar com zero. Será criada a variável i que armazenará que índice deve ser acessado, com o índice começa com zero, esse será o valor de i.

O que as funções próximo e anterior vai fazer e mudar os índices na lista de nós, como cada nó e representado nessa lista com um valor que se inicia com zero e vai até a última quantidade de nó, quando for acionado a função próximo() ele apenas soma mais um na variável que armazena o valor do índice da lista, assim ele retorna o próximo nó, e caso seja acionada a função anterior() ele diminua um valor do índice, retornando um índice anterior. Mais para evitar que no índice não tenha valores maiores que a quantidade de nós na lista, criaremos a variável x que terá o quantidade de nós no documento, e a função próximo será executada somente até o ultimo nó, evitando assim que seja acessando índices que não exista e retorne resultados em branco.

var x=xmlDoc.getElementsByTagName("nopai");
i=0;
function next()
{
if (i<x.length)
{
i++;
display();
}
}
function previous()
{
if (i>0)
{
i--;
display();
}
}

Agora iremos criar uma função para retornar os valores que estão nos nós. E mostra-los dentro da div cujo id é mostrar

function display()
{
tagpai=(x[i].getElementsByTagName("nofilho")[0].childNodes[0].nodeValue);
tagfilho=(x[i].getElementsByTagName("nofilhoeirmao")[0].childNodes[0].nodeValue);
document.getElementById("mostrar").innerHTML="Tag pai: " + tagpai + "<br />Tag filho: " + tagfilho;
}

A função display vai carregar no inicio a div mostrar, para que os valores do nós seja injetado dentro dela, e os botões serão responsáveis por acionar a função próximo e anterior

<body onLoad="display()">
<div id='mostrar'>
</div>
<br />
<input type="button" onClick="previous()" value="previous" />
<input type="button" onClick="next()" value="next" />

Acessando os atributo dos nós

No arquivo XML existem atributos (atributo=”PrimeiroFilho”), esses atributos podem ser lidos utilizando o atributo attributes. Para acessar um atributo do arquivo XML, utilize o método getElementsByTagName(“nopai”) para acessar o nó com atributo e getAttribute(“atributo”) para retorna o valor do atributo

texto=xmlDoc.getElementsByTagName("nopai")[0].getAttribute("atributo");
document.write(texto);

Para acessar todos os valores dos tributos, é so utilizar o método getElementsByTagName(“nopai”) para acessar o nó pai e utilizar um comando de repetição

var x=xmlDoc.getElementsByTagName('nopai');
for (i=0;i<x.length;i++)
{
document.write(x[i].getAttribute('atributo'));
document.write("<br />");
}

Acessando os nome dos nós

Para retornar o nome do nó é necessário pega-lo com o método método getElementsByTagName(tagname) e utilizar o atributo nodeName

texto = xmlDoc.getElementsByTagName("nopai")[0].nodeName;
document.write(texto);

Para acessar os nome de todo os nós que o método getElementsByTagName(tagname) recuperou, basta apenas utilizar o atributo nodeName com um comando de repetição

x=xmlDoc.getElementsByTagName("nofilho");
for (i=0; i<x.length; i++)
{
document.write(x[i].nodeName);
document.write("<br />");
}

Qualquer dúvida envie um email para marcelo@marceloramos.blog.br ou acesse meu blog www.marceloramos.blog.br

Escrito por Marcelo Ramos on abril 20, 2008. Arquivado em Javascript. Você pode seguir as respostas a esse artigo pelo RSS 2.0. Você pode deixar respostas para esse artigo

9 respostas a Leitura de arquivos XML utilizando JavaScript/ DOM

  1. Muito bom!!!

    Parabéns pelos detalhes, marcelo !!!

    Só fico triste pela Microsoft assumir posturas comerciais no fato de nomear códigos exclusivos para o IE.

  2. Cara,
    Show de bola esse seu artigo hein
    parabéns rapaz.

    abssss

  3. Pois, só vou colocar um desafio que me tem feito a cabeça em água e não encontro forma de resolver:

    Como ler isto (representa um menu):

    Como é que isto se resolve?

    Abraço
    Um Portuga

  4. foi o xml à parte porque as tags não passaram à primeira

  5. Cara pesquizei tanto na net sobre isso e ounico lugar que encontrei bem esplicadinho foi aqui, muito obrigado pelo belo poste…….

  6. Olá!
    Muito bom seu tutorial!
    Gostei bastante.

    Estou com uma dúvida:
    Se o conteúdo de um nó for um texto com formatação em HTML, como eu pego esse conteúdo?
    Eu testei aqui e ele “confunde” as tag’s HTML com nós =/

  7. Bom acabei usando uma POG mesmo…
    Usei a função replace XD

  8. Muito Boa a explicação sobre XML

    Dúvida??????

    Exportei um arq TXT do Excel para XML 2003

    Como devo acessar os dados utilizando o conceito de Pai e Filho?

    Origado

  9. Ótima explicação.

    Dúvida:

    Exportei um TXT pelo Excel 2007 para o XML 2003

    Como devo acessar os ROWS contendo o atributo NOME?

    Utilizei o comendo abaixo e não funcionou?

    var texto = xmlDoc.getElementsByTagName(“NOME”)[0].childNodes[0].nodeValue;

    var texto = xmlDoc.getElementsByTagName(“NOME”)[0].nodeValue;

    Obrigado

Deixe uma resposta

O seu endereço de email não será publicado Campos obrigatórios são marcados *

*

Você pode usar estas tags e atributos de HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>