par fabrice.marguerie@cogisoft.fr
Télécharger la version du 27/04/1999
Actuellement, pour accéder au contenu d'un document XML, nous disposons de parsers qui fournissent une interface DOM (Document Object Model).
Prenons le document suivant (Books.xml):
<bookstore> <book genre="autobiography" count="15"> <title>The Autobiography of Benjamin Franklin</title> <author> <first_name>Benjamin</first_name> <last_name>Franklin</last_name> </author> <price>8.99</price> </book> <book genre="novel"> <title>The Confidence Man</title> <author> <first_name>Herman</first_name> <last_name>Melville</last_name> </author> <price>11.99</price> </book> <book genre="philosophy" count="2"> <title>The Gorgias</title> <author> <name>Plato</name> </author> <price>9.99</price> </book> </bookstore>
Dans le cas où nous utilisons le parser XML de Microsoft (msxml.dll version 2), nous disposons d'interfaces COM (IXMLDOMDocument, IXMLDOMNode, ...) pour manipuler le document XML sous la forme d'un arbre. Ces interfaces ne sont pas toujours adaptées à certains traitements pour lesquels un système plus simple serait apprécié. Ainsi, dans certains cas, nous aimerions pouvoir utiliser une notation du genre book.author.last_name pour accéder au contenu de ce document comme à des champs d'une structure.
Nous pouvons parvenir à cela grace au mécanisme de gestion des appels OLE
Automation dans Delphi.
Pour comprendre ce mécanisme, vous pouvez consulter l'exemple StringsAuto
qui permet de manipuler les variables contenues dans un objet TStrings comme des champs d'une structure.
Ainsi, si un objet TStrings contient le texte suivant:
Var1=abc Var2=def
on pourra accéder à la valeur de Var1 avec l'appel vStrings.Var1 où vStrings est un variant contenant l'objet TStrings.
Nous allons voir comment implémenter cette fonctionnalité avec Delphi 4 et le parser XML de Microsoft (Internet Explorer 5 est requis).
Le code nécessaire est fourni dans l'unité XMLAuto.
Lors de l'affectation d'une valeur à la propriété Visible de l'objet Word dans l'exemple ci-dessous, on utilise un appel OLE Automation géré par la procédure VarDispInvoke de l'unité ComObj de Delphi.
var Word: Variant; begin Word := CreateOleObject('Word.Application'); Word.Visible := True; end;
Delphi fournit la variable VarDispProc qui permet de mettre en place un nouveau gestionnaire pour les appels OLE Automation. Nous allons utiliser ce mécanisme pour gérer les appels effectués sur un document XML et son contenu.
var Document: Variant; begin Document := CoDOMDocument.Create; Document.load('Books.xml'); ShowMessage(Document.bookstore.book.author.last_name.text); end;
Ce type de notation n'exclue pas les appels au DOM:
ShowMessage(Document.bookstore.childNodes[1].author.last_name.text);
Ce genre d'appel fonctionne à condition que la variable globale EnableDOM soit à True (défaut) pour pouvoir accéder à des méthodes ou à des propriétés du DOM telles que childNodes ici.
Nous pouvons également effectuer l'appel suivant qui référence le deuxième livre:
ShowMessage(Document.bookstore.book[1].author.last_name.text);
Pour obtenir un code encore plus compact, il est possible de positionner la variable EnableDefaultProperty à True, ce qui indique une réference implicite à la propriété text.
ShowMessage(Document.bookstore.book.author.last_name);
Bien sûr, les modifications du document XML sont possibles:
Document.bookstore.book.title.text := 'test write 1';
y compris avec EnableDefaultProperty = True:
Document.bookstore.test1 := 'test write 3';
Nous avons aussi la possibilité de créer dynamiquement les éléments s'ils n'existent pas:
Document.bookstore.test1.text := 'test Write 2';
La variable globale AutoCreateElement indique si le mécanisme de création automatique est activé.
AutoCreateElement est compatible avec EnableDefaultProperty:
Document.bookstore.test2 := 'test write 4'; Document.bookstore.test2[1] := 'test write 5';
Dans le cas où EnableDOM = True, on peut arriver à des conflits
entre des éléments/attributs du document XML et des méthodes/propriétés du
DOM XML.
Imaginons que un élément element contenant un sous-élément text:
<element> <text>exemple de texte</text> <autre_sous_element>de conflit<autre_sous_element> </element>
L'appel element.text retournera toujours "exemple de texte".
Dans certains cas on veut accéder au texte "exemple de texte de conflit".
Cela se fait en temps normal avec EnableDOM = True et l'emploi de la propriété text du DOM du noeud.
Ici, il y a conflit entre l'élément text et la propriété text.
Pour contourner le problème, on peut jouer sur les différences majuscules/minuscules.
Ainsi, l'appel element.Text retournera "exemple de texte de conflit" si le DOM est activé.
Il n'est pas possible d'accéder aux éléments ou attributs contenant des symboles non supportées par Delphi pour les noms d'identifiants (exemple: last-name est invalide, last_name est valide). Pour accéder à des éléments ou des attributs dont le nom comporte un symbole, il faut utiliser le DOM.
Comment accéder à un attribut X quand il existe un élément X ?
Ce sont des éléments qui sont créés automatiquement. Comment créer des attributs ? En utilisant une autre option de configuration ?
Il est grandement conseillé de passer par des variables intermédiaires pour ne pas ralentir les traitements.
Par exemple, pour accéder aux informations sur un livre, comme ci-dessous:
ShowMessage(Document.bookstore.book[1].author.last_name.text); ShowMessage(Document.bookstore.book[1].author.first_name.text);
il est préférable d'utiliser une variable Book de type Variant:
Book := Document.bookstore.book[1]; ShowMessage(Book.author.last_name.text); ShowMessage(Book.author.first_name.text);
Le même type de travail peut être fait pour les datasets (TTable, TQuery, ...) afin de permettre un accès direct aux champs: tblCustomer.LastName := 'toto'.
Pour avoir plus d'informations, pour soumettre des bugs, pour émettre des suggestions, n'hésitez pas à me contacter: fabrice.marguerie@cogisoft.fr
Pour obtenir la dernière version, rendez vous à http://www.cogisoft.fr/tech ou http://www.cogisoft.fr/downloads