Rémi Godard Vivian Perez Florian Pérugini Bertrand Vitrant DOCUMENTATION TECHNIQUE Comparateur de documents XML
SOMMAIRE 1 Introduction... 3 2 Langage et choix de programmation... 4 2.1 Le langage PHP... 4 2.1.1 Les APIs de PHP5 utilisées... 4 3 Fonctionnement général... 5 4 Les différents modules... 6 4.1 Afficher arbre... 6 4.2 Charger sauvegarder arbre... 6 4.3 Comparateur... 6 4.4 Comparer un nœud... 6 4.5 Création arbre des différences... 6 4.6 DomNode to DomElement... 7 4.7 Filtres... 7 4.8 Petites fonctions du comparateur... 7 4.9 Principale... 7 4.10 XSL... 7 5 Détail des méthodes par module... 8 5.1 Afficher arbre... 8 5.2 Charger sauvegarder arbre... 8 5.3 Comparateur... 9 5.4 Comparer un nœud... 9 5.5 Création arbre des différences... 10 5.6 DomNode to DomElement... 12 5.7 Filtres... 12 5.8 Petites fonctions du comparateur... 13 5.9 Principale... 13 5.10 XSL... 14 2
1 Introduction Le comparateur de documents XML que nous avons programmé est un outil générique. Cela veut donc dire qu il peut être utilisé dans le but de comparer tout type de document XML. Afin de pouvoir finaliser une version valable de ce programme, nous avons décidé de limiter la comparaison entre deux nœuds à un niveau. Cette solution est tout de même valable, puisque qu aucun comparateur actuellement sur le marché, ne compare une section entière de nœuds par une autre (ce qui serait la solution optimale). Nous nous sommes inspirés d un programme existant, nommé XyDiff, réalisé par l INRIA Rocquencourt, afin de parcourir correctement nos arbres modèle et testé. Un site web dédié à cette application est disponible à l adresse: http://gemo.futurs.inria.fr/software/xydiff/cdrom/www/xydiff/index-eng.htm 3
2 Langage et choix de programmation 2.1 Le langage PHP Nous avons choisi le langage PHP car celui-ci propose les API DOM et XSL nécessaires à la programmation du comparateur de documents XML et à l affichage des résultats. Notre choix a été motivé aussi par le fait que l environnement dans lequel est placé le comparateur est une plateforme web et qu il est donc plus simple d intégrer du code PHP dans des pages web déjà programmées également en PHP. Nous avons choisi de ne pas créer de classe, nous avons simplement créé des modules (fichiers PHP) où les méthodes sont rangées par proximité au niveau de la fonctionnalité. Ce choix est le résultat d une réflexion commune, nous ne voyions pas l intérêt de créer une classe «comparateur», par exemple, car les principales méthodes que nous avons programmées prennent en paramètres des objets correspondants à des librairies PHP et retournent ces mêmes types d objet. 2.1.1 Les APIs de PHP5 utilisées - DOM: Cette interface de programmation permet la manipulation de fichiers XML. DOM, signifiant Document Objet Model, permet de construire une arborescence de la structure d'un document et de ses éléments. C est grâce à celle-ci que nous pouvons charger, comparer, sauvegarder, etc., des documents XML. Une documentation complète de cette API est disponible à l adresse: http://fr3.php.net/manual/fr/book.dom.php - XSL: L'extension XSL de PHP5 implémente le standard XSL, elle permet d effectuer des transformations XSLT en utilisant la bibliothèque «libxslt». En ce qui concerne notre projet, nous utilisons la classe XSLTProcessor qui permet de lier un document XML à un fichier XSL. Une documentation complète de cette API est disponible à l adresse: http://fr3.php.net/manual/fr/book.xsl.php 4
3 Fonctionnement nnement général Le principe du comparateur repose sur un parcours récursif simultané de deux arbres XML. Pour faciliter la compréhension, les arbres parcourus seront nommés arbres modèle et testé. Pour commencer, les deux arbres sont placés sur leur racine respective, et une comparaison des racines est effectuée. La fonction de comparaison indique si les deux nœuds sont égaux, ou s il y a une substitution. Puis une liste des fils de chacun des nœuds est créée. On se place sur le premier fils modèle et la liste des fils testés est parcourue afin de savoir si un des nœuds testés est identique au nœud modèle. Si c est le cas alors ce nœud testé est choisi, sinon un deuxième parcours de la liste des nœuds testés permet la sélection de celui qui est le plus ressemblant au nœud modèle. Une fois le nœud testé choisi, la fonction de parcours est rappelé (la récursivité s effectue donc à ce niveau), et les deux nœuds sont comparés à leur tour par la fonction de comparaison. Un tableau des différences est renseigné des substitutions, insertions et délétions qui ont lieu. La liste des fils de chacun de ces deux nœuds est alors éditée et les mêmes opérations sont effectuées. Tous les autres fils modèles sont, eux aussi à leur tour, parcourus. Lorsque l on est sur le dernier nœud modèle et qu il reste des nœuds testés non choisis alors il y a une ou plusieurs insertions. Le tableau des différences est alors renseigné. Lorsque le parcours de tous les nœuds est terminé, le tableau des différences est rempli et l arbre des différences se construit à partir de celui-ci. 5
4 Les différents modules 4.1 Afficher arbre Le module afficherarbre.php contient les fonctions relatives à l affichage d un arbre dans un navigateur web. Ce module nous a beaucoup servi pour les tests que nous avons effectués mais il n est pas utilisé dans la plateforme car nous n affichons pas l arbre des différences à l utilisateur mais plutôt les différences observées, expliquées sous forme de phrases. 4.2 Charger / sauvegarder arbre Comme son nom l indique, le module chargersauvegarderarbre.php permet de charger ou sauvegarder un arbre DOM. Il est indispensable à notre programme car sans chargement d un fichier XML sous forme d un arbre DOM, nous ne pouvons effectuer aucune comparaison. La sauvegarde est nécessaire notamment pour l enregistrement de l arbre des différences dans un fichier XML. 4.3 Comparateur Le module comparateur.php est le fichier principal du programme car c est ici qu est effectué, entre autre, le parcours récursif et simultané des deux arbres modèle et testé. Toutes les fonctions de choix de nœuds identiques ou ressemblants sont aussi présentes dans ce module. 4.4 Comparer un nœud Le module comparerunnoeud.php est assez proche du module comparateur.php car les méthodes de comparerunnoeud.php sont appelées dans comparateur.php. Il effectue des comparaisons, tout comme l autre module, mais seulement sur deux nœuds préalablement choisis. La comparaison de deux nœuds s effectue en regardant aussi le niveau suivant afin de voir si les fils de ces deux nœuds sont égaux ou non. Grâce à cette méthode, nous interprétons si nous avons affaire à une substitution, délétion ou insertion. Plus de détails sur la comparaison sont donnés dans la partie 5 (Détail des méthodes par module). 4.5 Création arbre des différences Le module creationarbredifferences.php contient des méthodes permettant de créer la racine de l arbre des différences, de compléter cet arbre à l aide du tableau des différences et de rajouter des identifiants aux nœuds insérés, délaissés ou substitués. C est donc grâce à lui que les arbres différence, modèle et testé sont correctement renseignés par les identifiants. 6
4.6 DomNode to DomElement Il a fallu créer le module DOMNode_TO_DOMElement.php par rapport à un besoin normalement prévu par l API DOM de PHP5. Cette interface propose la classe DOMNode qui elle-même possède une méthode nommée appendchild(). D après la documentation disponible sur le site http://php.net, à partir d un objet DOMNode, on appelle la méthode appendchild(domnode) et celle-ci nous retourne le nœud sur lequel on est placé, modifié de l ajout du nœud passé en paramètre de la fonction. Or on ne peut passer, en paramètre de cette fonction, un objet DOMNode. Il faut obligatoirement passer un objet DOMElement pour que l ajout fonctionne. Nous avons donc créé ce module afin de palier à ce problème. 4.7 Filtres Le module filtres.php est complémentaire au comparateur à proprement parler. Les méthodes programmées dans ce module sont soit des filtres, soit des pré ou post traitements. Par exemple, l une d entre elles permet de supprimer les commentaires des fichiers XML modèle et testé avant la comparaison. Ou encore la fonction ajouternamespace() ajoute les espaces de noms des fichiers générés par la suite oppenoffice.org à l arbre des différences afin de pouvoir visualiser celui-ci correctement. 4.8 Petites fonctions du comparateur Le module petitesfonctionscomparateur.php contient toutes les méthodes très courtes et simplistes appelées régulièrement dans le code. Par exemple, des fonctions qui calculent le nombre d attributs d un nœud. 4.9 Principale Principale.php appelle toutes les méthodes nécessaires à la comparaison et à la création et l affichage du résultat. Les filtres sont appliqués selon des variables booléennes passés en paramètres de la fonction principale(). 4.10 XSL Ce module est externe au comparateur, il permet simplement d effectuer le lien entre le fichier XML correspondant à l arbre des différences et le fichier XSL associé, ce dernier permettant de présenter les résultats de la comparaison d une manière tournée vers l utilisateur. 7
5 Détail des méthodes par module 5.1 Afficher arbre Fonction affichearbre ($arbre, $espace): Pré requis: Donner l'arbre à afficher ainsi qu'un entier $espace correspondant au nombre d'espaces de la première balise (simule une indentation). Action: Affiche l'arbre donné en argument. Résultat: Affiche l'arbre sur le navigateur. Fonction afficheespace ($nb): Pré requis: Donner en paramètres le nombre d'espaces. Action: Créé une chaîne de caractères du nombre d'espaces vides passé en argument. Résultat: Retourne la chaîne de caractère. 5.2 Charger sauvegarder arbre Fonction chargerarbre ($document): Pré requis: Donner le document XML à charger. Action: Créé un arbre DOM à partir du document XML donné en argument, puis se place sur la racine. Résultat: Retourne la racine du document. Fonction sauvegarderarbre ($arbre, $chemin): Pré requis: Donner l'arbre DOM à sauvegarder ainsi que le chemin absolu du fichier de destination. Action: Sauvegarde l'arbre DOM dans un fichier XML. Résultat: Retourne "true" si l'opération s'est bien déroulée "false" sinon. Fonction sauvegarderarbredom ($dom, $chemin): Pré requis: Donner le document à sauvegarder ainsi que le chemin absolu du fichier de destination. Action: Sauvegarde l'arbre DOM dans un fichier XML. Résultat: retourne "true" si l'opération s'est bien déroulée "false" sinon. 8
5.3 Comparateur Fonction parcoursarbre ($modele, $teste, $tab, $niveau, $myid): Pré requis: Donner les 2 nœuds à comparer en arguments (noeudmodèle et noeudtesté) ainsi qu'un tableau vide (ou "null"), le niveau (0 à l'appel) et 0 (correspondant au premier ID). Action: Parcours les arbres donnés en argument, les compare et renseigne les différences rencontrées dans le tableau passé en paramètres. Résultat: Retourne le tableau des différences. Fonction recherchetesteidentique ($filsmodele, $listefilsteste, $tabfilsteste): Pré requis: Donner le fils modèle, la liste des fils à tester et le tableau des fils testés. Action: Recherche dans la liste des fils à tester celui ou ceux qui sont identiques au fils modèle. Résultat: Retourne le tableau des fils testés. Fonction recherchetesteressemblant ($filsmodele, $listefilsteste, $tabfilsteste): Pré requis: Donner le fils modèle, la liste des fils à tester, et le tableau des fils testés. Action: Recherche dans la liste des fils à tester celui qui ressemble le plus au fils modèle. Résultat: Retourne le fils testé choisi, ou "null". Fonction choixtesteressemblant ($noeudmodele, $tabnoeudtesteressemblant): Pré requis: Donner le nœud modèle, un tableau de nœuds testés ressemblants. Action: Recherche dans le tableau des nœuds, déjà testés ressemblants, celui qui ressemble le plus au nœud modèle. Résultat: Retourne le nœud testé ressemblant le plus au nœud modèle ainsi que son indice dans un tableau. Fonction testsousarbreidentique ($noeudmodele, $noeudteste): Pré requis: Donner un nœud modèle, et un nœud testé. Action: Compare les sous arbres des nœuds modèle et testé passés en paramètres. Résultat: Retourne un entier correspondant à la ressemblance entre les des sous arbres des nœuds modèle et testé. 5.4 Comparer un nœud Fonction choixnoeudidentique ($noeudmodele, $noeudteste): Pré requis: Passer les 2 nœuds à comparer en paramètres (noeudmodèle et noeudtesté). Action: Compare les deux nœuds. Résultat: retourne - 0 si les 2 nœuds sont complètement différents, - 1 s'ils sont identiques, et - 2 s'ils se ressemblent. Fonction compare ($noeudmodele, $noeudteste, $tab, $niveau, $myid): Pré requis: Passer les 2 nœuds à comparer en paramètres ainsi que le tableau des différences à compléter et retourner, le niveau et un identifiant unique (par référence). Action: Compare le type, le nom et le contenu texte des deux nœuds ainsi que le nombre, le nom et la valeur des attributs de chaque nœud. Puis renseigne le tableau des différences passé en paramètres de la fonction. Résultat: retourne le tableau des différences complété. 9
Fonction comparecontenubool ($noeud1, $noeud2): Pré requis: Passer les 2 nœuds à comparer en paramètres. Action: Compare le contenu texte des deux nœuds. Résultat: Retourne "true" si les contenus textes sont identiques, "false" sinon. Fonction compareattributs ($noeudmodele, $noeudteste): Pré requis: Donner deux nœuds qui ont le même nombre d'attributs. Action: Compare les noms des attributs des deux nœuds ainsi que leurs valeurs. Résultat: Retourne "true" si les noms et valeurs de tous les attributs sont égaux, "false" sinon. Fonction comparefils ($noeudmodele, $noeudteste): Pré requis: Passer les 2 nœuds pères. Action: Compare les fils des nœuds pères. Résultat: Retourne "true" s'ils sont tous égaux, "false" sinon. Fonction comparebool ($noeudmodele, $noeudteste): Pré requis: Passer les 2 nœuds à comparer en paramètres. Action: Compare le nom et le contenu TEXT des deux nœuds ainsi que le nombre, le nom et la valeur des attributs de chaque nœud. Résultat: Retourne "true" s ils sont identiques "false" sinon. 5.5 Création arbre des différences Fonction creerarbrediff ($noeudmodele, $noeudteste, $arbredifferences): Pré requis: Donner les 2 nœuds à comparer en arguments ainsi que la racine de l'arbre des différences. Action: Appelle la fonction de création du tableau des différences puis celle qui crée l'arbre des différences à partir du tableau. Résultat: Retourne l'arbre des différences. Fonction creerracinearbrediff (): Pré requis: Aucun. Action: Créé la structure de l'arbre des différences, à savoir: <Début> <délétion> <substitution> <insertion> Résultat: Retourne la racine de la structure de l'arbre des différences. Fonction deletion ($noeudmodele, $niveau, $tab, $clonerecursif, $myid): Pré requis: Donner en paramètres le nœud modèle, le niveau de ce nœud, le tableau contenant les différences, un booléen correspondant à la récursivité du clonenode() et un identifiant unique pour référencer le nœud modèle. Action: Copie le nœud modèle, le complète des informations "refpere", "niveau", créé une référence vers l'arbre modèle grâce à l'attribut "MyID" et renseigne le tableau des différences de cette copie, partie "deletion". Résultat: Retourne le tableau des différences complété. 10
Fonction insertion ($nœud, $niveau, $tab, $clonerecursif, $myid): Pré requis: Donner en paramètres le nœud testé, le niveau de ce nœud, le tableau contenant les différences, un booléen correspondant à la récursivité du clonenode() et un identifiant unique pour référencer le nœud modèle. Action: Copie le nœud testé, le complète des informations "refpere", "niveau", créé une référence vers l'arbre testé grâce à l'attribut "MyID" et renseigne le tableau des différences de cette copie, partie "insertion". Résultat: Retourne le tableau complété. Fonction substitution ($noeudteste, $noeudmodele, $niveau, $tab, $clonerecursif, $typesubst, $myid): Pré requis: Donner en paramètres le nœud testé, le nœud modèle, le niveau de ces nœuds, le tableau des différences, un booléen correspondant à la récursivité du clonenode(), le type de substitution (nom, attribut, nombre d attribut, ou contenu) et un identifiant unique pour référencer les nœuds modèle et testé. Action: Copie le nœud modèle, le complète des informations "refpere", "niveau","subst" et "refmodele"; créé deux références, une vers l'arbre testé et une autre vers l'arbre modèle, grâce à l'attribut "MyID"; et renseigne le tableau des différences de cette copie, partie "substitution". Résultat: Retourne le tableau des différences complété. Fonction creernoeudsubstitution ($nœud, $pere, $niveau, $type, $modele, $teste): Pré requis: Donner le nœud à compléter, la référence de son père, le niveau, le type de substitution et la référence du nœud modèle. Action: Complète le nœud $nœud en y ajoutant les attributs refpere, niveau, subst et refmodele. Résultat: Retourne le nœud modifié. Fonction ajoutermyid ($nœud, $val): Pré requis: Donner un nœud et une valeur unique. Action: Ajoute l'attribut MyID ainsi que la valeur $val au nœud $nœud. Résultat: Retourne le nœud modifié. Fonction creernoeudinsertion ($nœud, $pere, $niveau, $refteste): Pré requis: Donner le nœud à compléter, la référence de son père, son niveau et la référence du document testé. Action: Complète le nœud $nœud en y ajoutant les attributs refpere, niveau et refteste. Résultat: Retourne le nœud modifié. Fonction creernoeuddeletion ($nœud, $pere, $niveau, $refmodele): Pré requis: Donner le nœud à compléter, la référence de son père, son niveau et la référence du document modèle. Action: Complète le nœud passé en paramètres en y ajoutant les attributs refpere, niveau et refmodele. Résultat: Retourne le nœud modifié. 11
5.6 DomNode to DomElement Fonction creerelement ($arbre, $nœud) : Pré requis : Donner l'arbre à recopier et le nœud sur lequel on va le copier. Action : Recopie $arbre et ajoute cette copie en tant que fils de $nœud. Résultat : Retourne la racine de l'arbre créé. Fonction creerelementboucle ($tab, $arbrediff) : Pré requis : Donner le tableau des différences correctement rempli, et la structure de l'arbre des différences (vide). Action : Rempli l'arbre des différences à partir du tableau des différences. Résultat : Retourne la racine de l'arbre des différences. 5.7 Filtres Fonction ajouternamespace ($arbrediff, $arbremodele) : Pré requis : Donner les 2 arbres modèles et différences en arguments. Action : Ajoute la définition des namespaces dans l'arbre des différences. Résultat : Retourne l'arbre des différences modifié ou non. Fonction enlevercommentaires ($src, $dest) : Pré requis : Donner les chemins source et destination du fichier à modifier en arguments. Action : Créé une copie du fichier, passé en paramètre, sans commentaires. Résultat : Le fichier n'a plus de commentaires, il se situe à l'adresses $dest. On retourne l'arbre correspondant. Fonction parcourscomment ($arbre, $tab) : Pré requis : Donner l'arbre à parcourir et "null". Action : Parcours l'arbre passé en paramètre et stocke les nœuds commentaire dans un tableau. Résultat : Retourne le tableau contenant tous les nœuds commentaires. Fonction posttraitementcontenu ($arbre): Pré requis : Donner un arbre des différences généré par l'application. Action : Supprime les substitutions portant sur le contenu. Résultat : Retourne l'arbre des différences modifié. Fonction parcourscontenu ($arbre, $tab) : Pré requis : Donner l'arbre à parcourir et "null". Action : Parcours l'arbre passé en paramètre et stocke les nœuds ayant l'attribut subst="contenu" dans un tableau. Résultat : Retourne le tableau contenant tous les nœuds récupérés. 12
5.8 Petites fonctions du comparateur Fonction nbnoeuds ($racine) : Pré requis : Donner un arbre en arguments. Action : Calcule le nombre de nœuds de l'arbre. Résultat : Retourne le nombre de nœuds de l'arbre. Fonction nbattributsnoeud ($nœud) : Pré requis : Donner un nœud en arguments. Action : Calcule le nombre d'attributs du nœud. Résultat : Retourne le nombre d'attributs du nœud. Fonction initazero ($longueur) : Pré requis : Donner la longueur du tableau à créer. Action : Créé le tableau de longueur $longueur et l'initialise à zéro. Résultat : Retourne le tableau créé. Fonction rechercheattribut ($nœud, $attr) : Pré requis : Donner un nœud et l'attribut à trouver dans ce nœud. Action : Recherche l'attribut passé en paramètres parmi les attributs du nœud lui aussi passé en paramètre. Résultat : Retourne la valeur si l'attribut existe, "false" sinon. 5.9 Principale Fonction principale ($srcficmodele, $srcficteste, $destarbremodele, $destarbreteste, $destarbrediff, $ajouternamespace, $supprcommentavantcomparaison, $supprsubstcontenu, $srcxsl, $desthtml) : Pré requis : Donner les chemins des fichiers XML modèle et testé ainsi que la destination de ces deux fichiers modifiés (auxquels les références ont été ajoutées) et celle de l'arbre des différences. Mais aussi trois booléens correspondant à trois filtres: l'ajout de namespaces dans l'arbre des différences correspondant à la comparaison de fichiers générés par la suite Open Office la suppression des commentaires dans les fichiers modèle et testé avant comparaison la suppression des différences de contenu TEXT dans l'arbre des différences Et pour finir, passer le chemin du fichier XSL à associer avec l'arbre des différences et le chemin de destination du fichier HTML généré (ou "null"). Action : Effectue la comparaison XML, enregistre les fichiers modèle et testé modifiés ainsi que l'arbre des différences. Résultat : Retourne une chaîne de caractères contenant le résultat XSL. 13
5.10 XSL Fonction lierxslaxml ($arbre, $srcxsl, $desthtml) : Pré requis : Donner le fichier XML sous forme d'arbre, la source du fichier XSL à lui associer et un chemin de destination correspondant au fichier HTML créé (null si l'on ne veut pas de fichier HTML). Action : Créé un objet contenant la chaîne de caractère à afficher et enregistre le résultat en HTML dans $desthtml si ce paramètre est non nul. Résultat : Retourne l'objet en question. 14