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.
<?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.
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
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
ReadXMLFile(Doc, 'test.xml'
);
Puis, nous obtenons l'élément racine et listons tous ses nœuds fils contenant le tag membre
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 :
writeln( lst.item[j].nodeName, ' : '
, lst.item[j].TextContent);
Le code complet permettant le parcours de l'arbre DOM est le suivant
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,
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 .
doc.AppendChild(racine);
Pour ajouter un nouveau nœud fils, nous utilisons la méthode AppendChild d'un TDOMNode dont voici le prototype :
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.
writexmlfile(doc, 'create.xml'
);
Le code complet permettant la création d'un document XML est le suivant
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 ».
<?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
//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.
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 :
<?xml version="1.0"?>
<pascal>
<compilateur
ide
=
"lazarus"
version
=
"2.2.1"
>
free pascal</compilateur>
<compilateur
version
=
"2.2"
>
Midlet Pascal</compilateur>
</pascal>