luni, 10 noiembrie 2008

Utilizarea unui parser DOM in Java

M-am confruntat la Interfete Evoluate cu studiul si utilizarea documentelor XML. Deosebit de utile mi s-au parut implementarile SAX si DOM (doua dintre cele mai cunoscute parsere XML) din Java. Am sumarizat mai jos o descriere a implementarii DOM - Document Object Model
O aplicatie DOM creeaza mai intai un obiect parser (printr-o fabrica de obiecte) si apoi apeleaza metoda parse pentru acest obiect, cu specificarea unui fisier XML.
Metoda parse are ca rezultat un obiect de tip Document, care este arborele creat pe baza documentului XML, conform modelului DOM.
Pentru fisierul XML anterior cu lista de preturi, dar scris tot pe o singura linie si fara spatii albe, arborele DOM arata astfel:
De fapt, orice arbore DOM mai are un nivel radacina care corespunde intregului document XML (nod cu numele #document si valoarea null).
Fiecare nod dintr-un arbore DOM are un nume, o valoare si un tip. Tipurile sunt numere intregi, dar exista si nume mnemonice pentru aceste tipuri. Iata cateva exemple de constante din interfata Node:
public static final short ELEMENT_NODE = 1;
public static final short ATTRIBUTE_NODE = 2;

public static final short TEXT_NODE = 3;

public static final short DOCUMENT_NODE = 9;


Nodurile cu text au toate acelasi nume (#text), iar valoarea este sirul de caractere ce reprezinta textul. In exemplul anterior cele 4 noduri terminale sunt noduri text (cu valorile “CDC”,”540”,”SDS”,”495”). Parserul DOM creeaza noduri text si pentru grupuri de spatii albe.
Nodurile pentru elemente au numele marcajului si valoarea null. In arborele de mai sus am scris numele nodurilor de pe primele 3 niveluri (de tip 1) si valorile nodurilor de pe ultimul nivel (de tip 3).
Modelul DOM defineste mai multe interfete Java, implementate de parser si folosite de catre aplicatii :

- Interfata Node contine metode de acces la un nod de arbore DOM si la succesorii sai, dar si metode pentru crearea si modificarea de noduri de arbore DOM.
public String getNodeName(); // numele acestui nod public String getNodeValue() throws DOMException; // valoarea acestui nod public void setNodeValue(String nodeValue) throws DOMException; public short getNodeType(); // tipul acestui nod
public NodeList getChildNodes(); // lista succesorilor acestui nod
public Node getFirstChild(); // primul succesor al acestui nod
public Node getNextSibling(); // urmatorul succesor al acestui nod public Node removeChild(Node oldChild) throws DOMException;
public Node appendChild(Node newChild) throws DOMException;

public NamedNodeMap getAttributes(); //atributele acestui nod


- Interfata NodeList contine metode pentru acces la lista de succesori ai unui nod:
public Node item(int index); //nodul cu numarul “index”
public int getLength(); //lungime lista de noduri


- Interfetele Document, Element, Attr, CharacterData, Text, Comment, extind direct sau indirect interfata Node cu metode specifice acestor tipuri de noduri.

- Interfata NamedNodeMap corespunde unei liste de atribute (obiecte de tip Attr) si contine metode ca getLength() si item(i). Este folositoare pentru extragerea atributelor.

- Interfata Attr contine metode de acces la numele si valoarea unui atribut, precum si la elementul caruia apartine acel atribut:
public interface Attr extends Node
{

public String getName();
public String getValue();

public void setValue(String value) throws DOMException;

public Element getOwnerElement();
}

Cateva metode folositoare din interfata Element:
public String getAttribute(String name); //obtinerea valorii unui atribut cu nume dat
public void setAttribute(String name,String value) throws DOMException;
public NodeList getElementsByTagName(String name);

Ultima metoda este utila pentru extragerea selectiva de noduri dintr-un arbore DOM, desi exista si alte metode de filtrare a nodurilor din arbore.
Clasele care implementeaza interfetele DOM fac parte din parserul DOM, iar numele si implementarea lor nu sunt cunoscute utilizatorilor; ele constituie un bun exemplu de separare intre interfata si implementare si de programare la nivel de interfata. Clasa care implementeaza interfata Node contine si o metoda toString, care produce un sir de forma nume[valoare], cu numele si valoarea nodului, indiferent de tipul nodului si daca exista sau nu atribute asociate unui element.
Afisarea/prelucrarea unui arbore DOM se face de obicei printr-o functie recursiva care prelucreaza nodul curent (primit ca argument), atributele sale si apoi se apeleaza pe ea insasi pentru fiecare succesor. Parcurgerea listei de succesori se poate face usor in doua moduri:
- folosind metodele getFirstChild si getNextSibling ;
- folosind metoda getChildNodes si metode ale interfetei NodeList.

Un comentariu: