• Nenhum resultado encontrado

O módulo Traversal permite atravessar a árvore de um documento filtrando itens especificados. Isto é possível graças às interfaces NodeIterator, TreeWalker e NodeFilters definidas neste módulo.

As interfaces NodeIterator e TreeWalker representam visões lógicas da árvore DOM que podem não ter todos os nós que estão na árvore do documento. Estas visões têm formas diferentes de representar os nós de uma árvore. A NodeIterator apresenta uma

DOM 2 e DOM 3

45 visão plana da árvore como uma lista ordenada de nós. A TreeWalker mantém os relacionamentos hierárquicos de árvore [Kesselman 2000, Fesler 2001].

Para determinar os nós que devem ou não fazer parte de uma visão, é possível usar um flag whatToShow ou um filtro da interface NodeFilter. Quando um objeto NodeIterator ou TreeWalker é criado, pode ser associado a ele um filtro que examina cada nó e determina se ele deve aparecer na visão lógica. O flag pode ser usado para especificar que tipo de nó deve ocorrer na visão.

NodeIterators e TreeWalkers ajustam-se automaticamente às mudanças na árvore subjacente.

4.1.2.1 A Interface NodeIterator

A interface NodeIterator extrai um sub conjunto dos nós de um documento e o apresenta como uma lista na ordem que aparece no documento: primeiro o nó do documento, nó pai antes dos filhos e nós irmãos na mesma ordem que suas tags de abertura aparecem no documento [Harold 2002]. Por exemplo, considere o documento abaixo:

<A>

<B>text1</B> <C>

<D>child of C</D>

<E>another child of C</E> </C>

<F>moreText</F> </A>

Uma representação plana do NodeIterator para este documento XML é: A B C D E F

Neste tipo de visão não há relacionamento de pai e filho. Por isto, para acessar os nós da lista a interface NodeIterator define métodos que permitem mover-se para frente e para trás na lista como mostra a Listagem 4.1.

Cada iterator pode ser pensado como tendo um cursor que é inicialmente posicionado antes do primeiro nó na lista. O método nextNode() retorna o nó imediatamente depois do cursor e avança o cursor uma posição. O método previousNode() retorna o nó imediatamente antes do cursor e ajuda o cursor para uma

DOM 2 e DOM 3

posição anterior. Se o iterator está posicionado no fim da lista, nextNode() retorna nulo. Se o iterator está posicionado no começo da lista, previousNode() retorna nulo [Kesselman 2000].

Listagem 4.1 – Interface NodeIterator

package org.w3c.dom.traversal; public interface NodeIterator {

public Node getRoot(); public int getWhatToShow(); public NodeFilter getFilter();

public boolean getExpandEntityReferences(); public Node nextNode() throws DOMException; public Node previousNode() throws DOMException; public void detach();

}

Para criar um NodeIterator é necessário definir um objeto da interface DocumentTraversal e invocar o método createNodeIterator() deste objeto. Quando um NodeIterator é criado, flags podem ser utilizados para determinar que tipos de nó serão "visíveis" e que nós serão "invisíveis" enquanto se atravessa a árvore.

O método createNodeIterator() recebe como parâmetros quatro argumentos:

root – o nó por onde o iterator começa a atravessar. Apenas este nó e os seus descendentes são atravessados pelo iterator.

whatToShow – uma constante inteira que especifica que tipo de nó o iterator irá incluir. As constantes são:

NodeFilter.SHOW_ELEMENT 0x00000001 NodeFilter.SHOW_ATTRIBUTE 0x00000002 NodeFilter.SHOW_TEXT 0x00000004 NodeFilter.SHOW_CDATA_SECTION 0x00000008 NodeFilter.SHOW_ENTITY_REFERENCE 0x00000010 NodeFilter.SHOW_ENTITY 0x00000020 NodeFilter.SHOW_PROCESSING_INSTRUCTION 0x00000040 NodeFilter.SHOW_DOCUMENT 0x00000080 NodeFilter.SHOW_DOCUMENT_TYPE 0x00000100 NodeFilter.SHOW_DOCUMENT_FRAGMENT 0x00000200 NodeFilter.SHOW_NOTATION 0x00000400 NodeFilter.SHOW_ALL 0xFFFFFFFF

• filter – um objeto NodeFilter que seleciona os nós que farão parte do iterator. Apenas os nós que passarem pelo filtro ficarão de fora. O valor nulo indica que

DOM 2 e DOM 3

47

entityReferenceExpansion – um boolean que determina se os nós de referência de entidade serão expandidos ou não.

O código seguinte cria um iterator com todos os elementos de uma árvore e imprime o nome de cada elemento presente na lista:

NodeIterator iterator=

(DocumentTraversal)document).createNodeIterator( root,

NodeFilter.SHOW_ELEMENT, null, true); Node n;

while ((n = iterator.nextNode()) != null) System.out.println (n.getNodeName());

Se ocorrer alguma mudança na árvore do documento, o iterator reflete tais mudanças. Por Exemplo, considere o iterator seguinte, a posição do iterator é indicada pelo asterisco (*)

A B C * D E

Se o nó D for apagado da árvore e o método nextNode() for chamado, ele retornará o nó E. Se inserir o nó X entre B e C, e chamar previousNode(), o nó retornado será o X.

Deve-se observar que a posição corrente de um iterator é sempre entre dois nós ou antes do primeiro nó ou depois do último nó. Nunca a posição de um iterator será um nó.

4.1.2.2 A Interface NodeFilter

O argumento whatToShow permite selecionar apenas nós de tipos específicos em uma subárvore. Para realizar uma seleção mais rigorosa dos nós, DOM2 define a interface NodeFilter, que permite que o usuário crie objetos que "filtram” nós. Cada filtro contém a função acceptNode(), escrita pelo usuário, que olha um nó e determina se ele deve ou não fazer parte da visão lógica do traversal do documento [Kesselman 2000].

O método acceptNode() pode retornar uma das três constantes seguintes:

• NodeFilter.FILTER_ACCEPT - aceita o nó;

• NodeFilter.FILTER_REJECT - rejeita o nó e os seus filho;

• NodeFilter.FILTER_SKIP - rejeita o nó, mas permite que os seus filhos sejam verificados.

Para um iterator, que não tem a relação de nó pai e nó filho, só dois valores de constante fazem sentido: FILTER_ACCEPT e FILTER_REJECT (a constante FILTER_REJECT é semelhante a FILTER_SKIP).

DOM 2 e DOM 3

4.1.2.3 A Interface TreeWalker

O objetivo de TreeWalker é o mesmo de NodeIterator, atravessar uma árvore DOM e filtrar nós. Entretanto, TreeWalker, é baseado em uma árvore com pai, filhos, e irmãos.

Objetos TreeWalker são criados da mesma forma que objetos NodeIterator, isto é, chamando o método createTreeWalker() da interface DocumentTraversal Este método recebe os mesmos argumentos que createNodeIterator(): o nó raiz da subárvore, uma constante inteira que especifica o tipo de nós a ser exibido, um objeto NodeFilter ou nulo, e um boolean que indica se as referências de entidade devem ou não ser expandidas [Kesselman 2000].

Considerando o documento XML seguinte, a estrutura de árvore que o representa é mostrada na Figura 4.2.

<A>

<B>text1</B> <C>

<D>child of C</D>

<E>another child of C</E> </C>

<F>moreText</F> </A>

Figura 4.2 – Exemplo da árvore TreeWalker

Para acessar os nós da estrutura de árvore, a interface TreeWalker define os métodos listados na Listagem 4.2.

Em geral, TreeWalkers são melhores para tarefas em que a estrutura do documento em volta dos nós selecionados será manipulada, enquanto NodeIterators são melhores

A

B

C

F

DOM 2 e DOM 3

49

Listagem 4.2 – Interface TreeWalker

package org.w3c.dom.traversal; public interface TreeWalker { public Node getRoot(); public int getWhatToShow(); public NodeFilter getFilter();

public boolean getExpandEntityReferences(); public Node getCurrentNode();

public void setCurrentNode(Node currentNode) throws DOMException;

public Node parentNode(); public Node firstChild(); public Node lastChild(); public Node previousSibling(); public Node nextSibling(); public Node previousNode(); public Node nextNode(); }