OLE Automation pour XML

par fabrice.marguerie@cogisoft.fr
Télécharger la version du 27/04/1999


Introduction

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.Var1vStrings est un variant contenant l'objet TStrings.


Utilisation

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';

Limites

Conflits de noms

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é.

Symboles

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.

Attributs/Eléments

Comment accéder à un attribut X quand il existe un élément X ?

Création automatique

Ce sont des éléments qui sont créés automatiquement. Comment créer des attributs ? En utilisant une autre option de configuration ?


Notes

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);

Référence

Perspectives

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