Utilisation du DOM sous Lazarus/Free Pascal


précédentsommairesuivant

IV. Manipulation du DOM

Avec votre éditeur de texte favori, créer un nouveau fichier texte, copier/coller ou télécharger le document XML ci-dessous.
Voici maintenant venu le moment de parler code : démarrer Lazarus, puis créer un projet personnalisé nommé xmlproject.

 
TéléchargerSélectionnez
<?xml version="1.0" ?>
 <developpez>
  <membre>
   <pseudo>darrylsite</pseudo>
   <message>500</message>
   <status>redacteur</status>
 </membre>
 <membre>
   <pseudo>mbr</pseudo>
   <message>1500</message>
   <status>moderateur</status>
 </membre>
</developpez>

IV-A. Chargement d'un document XML

Pour travailler avec le DOM, nous aurions à ajouter les unités Dom, Xmlread, Xmlwrite à notre programme. Comme vous pouvez le deviner, l'unité Dom contient la déclaration des classes et fonctions de traitement du XML, Xmlread et Xmlwrite contiennent des routines pour la lecture et l'écriture du d'un document XML dans un fichier ou d'autres sources.

Voici un code qui charge un document XML contenu dans un fichier à l'aide de la méthode ReadXMLFile. test.xml est le nom du fichier sur le disque, et doc la variable qui contiendra l'arbre chargé en mémoire.

 
Sélectionnez
program xmlProject;
 
{$mode objfpc}{$H+}
 
Uses Dom, XMLRead, XMLWrite;
 
var doc : TXMLDocument;
      racine : TDOMElement;
 
begin
 try
  writeln('Chargement ...');
  ReadXMLFile(doc, 'test.xml');
  Racine:= doc.DocumentElement;
  writeln('OK !');
 except
  writeln('Echoue !');
 end;
end.	
	

Si la compilation et l'exécution s'effectuent sans problème, l'arbre chargé en mémoire est contenu dans l'objet doc. L'attribut DocumentElement représente la racine de l'arbre DOM.

On peut toutefois lire un document XML contenu dans une chaîne de la manière suivante

 
Sélectionnez
program creation;
 
{$mode objfpc}{$H+}
 
Uses Dom, XMLRead, Classes; 
 
var  stream : TStringStream;
     doc : TXMLDocument;
     chaine : string;
 
Begin
 try
  chaine:='<?xml version="1.0" ?><developpez><membre id="n1"><pseudo >darrylsite</pseudo></membre></developpez>';
  stream:= TStringStream.Create(chaine);
  writeln('Chargement ...');
  ReadXMLFile(doc,stream);
  writeln('OK !');   
 except
 end.
End.     

IV-B. Parcours d'un arbre DOM

Maintenant, voyons un exemple complet qui parse un document XML, parcourt tous les nœuds et donne leurs valeurs.

Nous commencerons par charger l'arbre en mémoire depuis le fichier test.xml

 
Sélectionnez
ReadXMLFile(Doc, 'test.xml');

Puis, nous obtenons l'élément racine et listons tous ses nœuds fils contenant le tag membre

 
Sélectionnez
racine:=doc.DocumentElement;
liste:=racine.GetElementsByTagName('membre');
				

liste.item un tableau de nœuds fils du nœud racine. Le premier élément est à la position 0 et contient liste.count éléments.
Enfin, l'affichage de la valeur du nœud et du texte qu'il contient se fait par :

 
Sélectionnez
writeln( lst.item[j].nodeName, ' : ', lst.item[j].TextContent);

Le code complet permettant le parcours de l'arbre DOM est le suivant

 
TéléchargerSélectionnez
program Parcours;
{$mode objfpc}{$H+}
Uses Dom, XMLRead, xmlWrite;
 
var doc    : TXMLDocument;
    racine : TDOMElement;
    liste, lst  : TDOMNodeList;
    taille, etaille, i, j : LongWord;
 
begin
 try
 {partie 1 : chargement et creation de l'arbre}
  writeln('Chargement ...');
  ReadXMLFile(Doc, 'test.xml');
  writeln('OK !');
 
{partie 2 : }
  racine:=doc.DocumentElement;
  liste:=racine.GetElementsByTagName('membre');
  taille:= liste.Count;
 
{partie 3}
  for i:=0 to taille-1 do
  begin
   lst:=liste.Item[i].GetChildNodes;
   etaille := lst.count;
   writeln('------------------------------------------------');
   for j:=0 to etaille-1 do
   begin
   {partie 4}
    writeln( lst.item[j].nodeName, ' : ', lst.item[j].TextContent);
   end;
  end;
 except
  writeln('Echoue !');
 end;
 readln;
end.	
	

Pour parcourir l'arbre DOM, on dispose aussi des méthodes suivantes faisant partie de la classe TDOMNode :

Attribut Rôle
FirstChild: TDOMNode Représente le premier nœud fils du nœud courant
LastChild: TDOMNode Représente le dernier nœud fils du nœud courant
NextSibling: TDOMNode Pointe sur le nœud frère suivant. C'est en fait le nœud qui suit le nœud courant dans la liste de ParentNode.ChildNodes. Il contient nil si c'est le dernier fils
PreviousSibling: TDOMNode Pointe sur le nœud frère précédent. C'est en fait le nœud qui précède le nœud courant dans la liste de ParentNode.ChildNodes. Il contient nil si c'est le premier fils
ParentNode: TDOMNode Représente le nœud parent

IV-C. Création d'un document XML

Maintenant que nous savons lire un document XML, nous allons voir comment on peut en créer par programmation.
Le procédé est simple. Nous allons créer le document (TXMLDocument), puis créer l'élément racine,

 
Sélectionnez
doc:= TXMLDocument.create;
racine:=doc.CreateElement('pascal');
				

Un fois le nœud racine crée, nous ajoutons ce nœud comme la racine de l'arbre DOM. Les méthodes createXXX permettent de créer différents types de nœuds : createElement , createTextNode , createAttribute .

 
Sélectionnez
doc.AppendChild(racine);

Pour ajouter un nouveau nœud fils, nous utilisons la méthode AppendChild d'un TDOMNode dont voici le prototype :

 
Sélectionnez
function AppendChild(NewChild: TDOMNode): TDOMNode;

Enregistrer le document XML dans un fichier se fait simplement par le code suivant où create.xml est le nom du fichier sur le disque.

 
Sélectionnez
writexmlfile(doc, 'create.xml');

Le code complet permettant la création d'un document XML est le suivant

 
TéléchargerSélectionnez
program xmlproject2;
{$mode objfpc}{$H+}
 
uses dom, xmlwrite;
 
  var doc               : TXMLDocument;
      racine, ele, fils : TDOMElement;
 
begin
 
try
  {partie 1}
  doc:= TXMLDocument.create;
  racine:=doc.CreateElement('pascal');
  doc.AppendChild(racine);
  {partie 2}
  ele:= doc.CreateElement('compilateur');
  racine.AppendChild(ele);
  ele.AppendChild(doc.CreateTextNode('free pascal'));
  ele.SetAttribute('version', '2.2.0');
  {partie 3}
  ele:= doc.CreateElement('compilateur');
  racine.AppendChild(ele);
  ele.SetAttribute('version', '7.0');
  fils:=doc.CreateElement('nom');
  fils.AppendChild(doc.CreateTextNode('Turbo Pascal'));
  ele.AppendChild(fils);
  fils:=doc.CreateElement('type');
  fils.AppendChild(doc.CreateTextNode('console'));
  ele.AppendChild(fils);
  {partie 4}
  writexmlfile(doc, 'create.xml');
 
  writeln('OK !');
except
 writeln('echoue');
end;
 
readln;
end.
	

Il est important de créer un nouveau nœud avec doc.createElement() car un nœud donné contient toujours une référence vers l'arbre DOM auquel il appartient.
Dans la première partie, on crée la racine en ajoutant le nœud crée au document XML. La deuxieme partie se diffère un peu de la première en ce sens que le nœud créé est ajouté comme nœud fils de la racine de l'arbre DOM. Le nouveau nœud contient à son tour un nœud fils ne contenant que du texte. Le reste du code peut se passer de tout commentaire. Nous reviendrons sous peu sur l'utilisation des attributs.

En exécutant ce programme, le document XML créé est enregistré sur le disque sous le nom « create.xml ».

 
Sélectionnez
<?xml version="1.0"?>
<pascal>
  <compilateur version="2.2.0">free pascal</compilateur>
  <compilateur version="7.0">
    <nom>Turbo Pascal</nom>
    <type>console</type>
  </compilateur>
</pascal>

Pour enregistrer le document XML dans une chaîne, on peut procéder comme suit

 
Sélectionnez
//var st : TStringStream; //contenue dans l'unité classes
st:=TStringStream.Create('');
writexml(racine, st); writeln(st.DataString);
				

IV-D. Modification d'un document XML

Nous nous proposons de modifier le document XML que nous avons créé dans l'exemple précédant. Nous allons modifier l'attribut version de Free Pascal en 2.2.1, supprimer le compilateur Turbo Pascal, puis ajouter un nouveau compilateur MIDletPascal.

Voici d'autres méthodes de la classe TDOMNode que nous allons utiliser :

Méthode Rôle
function RemoveChild(OldChild: TDOMNode): TDOMNode; Retire un nœud fils du nœud courant
function ReplaceChild(NewChild, OldChild: TDOMNode): TDOMNode; Remplace un nœud fils du nœud courant
function HasAttributes: Boolean; Indique si le nœud contient au moins un attribut


Et quelques méthodes de TDOMElement:

Méthode Rôle
function GetAttribute(const name: DOMString): DOMString; Donne la valeur de l'attribut dont le nom est passé en paramètre
procedure SetAttribute(const name, value: DOMString); Modifie la valeur de l'attribut dont le nom est passé en paramètre. Si l'attribut n'existe pas encore, il sera créé
procedure RemoveAttribute(const name: DOMString); Retire l'attribut dont le nom est passé en paramètre de l'élément.


Dans le code suivant, seule la procédure Modification permet la modification du l'arbre DOM. Le reste du reste est donné par soucis de complétude et pour servir d'exemple pour un parcours approfondi de l'arbre.

 
TéléchargerSélectionnez
program pmodif;
{$mode objfpc}{$H+}
uses dom, xmlRead, xmlWrite;
 
procedure espace(sp : word);
 var i : word;
begin
if sp<>0 then
 sp:=sp+1;
 for i:=1 to sp do
  write(' ');
end;
 
procedure affichage(element : TDOMElement; prof : word);
 var liste : TDOMNodeList;
     i, t, j : word;
begin
 liste:= element.ChildNodes;
 t:= liste.Count-1;
 for i:=0 to t do
 begin
  if liste.Item[i].HasChildNodes then
   begin
    espace(prof);
    write('<', liste.Item[i].NodeName, ' ');
    if (liste.Item[i].HasAttributes) then
     begin
      for j:= 0 to liste.Item[i].Attributes.Length-1 do
       write(liste.Item[i].Attributes.Item[j].NodeName, '="',liste.Item[i].Attributes.Item[j].NodeValue, '" ');
     end;
    writeln('>');
    affichage(TDOMElement(liste.Item[i]), prof+1);
    espace(prof);
    writeln('</', liste.Item[i].NodeName, '>');
   end
   else
   begin
    espace(prof);
    writeln(liste.Item[i].NodeValue);
   end;
 end;
end;
 
procedure modification(rac : TDOMElement);
 var liste : TDOMNodeList;
     element : TDOMElement;
begin
 liste:= rac.GetElementsByTagName('compilateur');
 {modification de free pascal}
 TDOMElement(liste.Item[0]).SetAttribute('version', '2.2.1');
 TDOMElement(liste.Item[0]).SetAttribute('ide', 'lazarus');
 {suppression de Turbo Pascal}
 rac.RemoveChild(liste.Item[1]);
 {ajout de midlet pascal}
 //toujours crÚe l'element a partir du TXMLDOcument
 element:=rac.OwnerDocument.CreateElement('compilateur');
 element.SetAttribute('version', '2.2');
 element.AppendChild(rac.OwnerDocument.CreateTextNode('Midlet Pascal'));
 rac.AppendChild(element);
end;
 
var doc : TXMLDocument;
    racine : TDOMElement;
 
begin
try
 readXmlFile(doc, 'create.xml');
 racine:= doc.DocumentElement;
 writeln('Avant : ');
 affichage(racine,  0);
 writeln('**************************');
 writeln('Apres :');
 modification(racine);
 affichage(racine,  0);
 writeXmlFile(doc, 'modifcreate.xml');
except
 writeln('Echoue !');
end;
 readln;
end.

L'exécution du programme donne le fichier XML suivant :

 
Sélectionnez
<?xml version="1.0"?>
<pascal>
  <compilateur ide="lazarus" version="2.2.1">free pascal</compilateur>
  <compilateur version="2.2">Midlet Pascal</compilateur>
</pascal>

précédentsommairesuivant

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2010 Darryl Kpizingui. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.