Flux RSS d'opikanoba.org

Sur l’interopérabilité, l’architecture et les systèmes d’informations de santé


Le format XML raté de HL7 v2.x

HL7 est une organisation internationale en charge de la définition et de la standardisation d’un format d’échange d’informations circulant dans les SIH (Systèmes d’Informations Hospitalier). Le format HL7 permet donc à des applications hétérogènes d’échanger des informations cliniques, qu’elles soient d’ordre médico-administratif, comme l’admission d’un patient, médico-technique comme les résultats d’examen de laboratoire, etc.

Les premières versions de ce format d’échange sont antérieures à la spécification XML, elles se reposent donc assez naturellement sur un format spécifique. Un message est composé de segments. Chaque segment est représenté par une ligne. Les trois premières lettres indiquent le type du segment. Un jeu de caractères spéciaux (^~& \ et |) permet de séparer les informations. Ainsi le message d’admission du patient William Jones (exemple tiré de la spécification HL7 2.5) ressemble à :

MSH|^~\&|ADT1|MCM|LABADT|MCM|198808181126|SECURITY|ADT^A01^ADT_A01|MSG00001-|P|2.5| EVN|A01|198808181123||
PID|1||PATID1234^5^M11^ADT1^MR^MCM~123456789^^^USSSA^SS||JONES^WILLIAM^A^III||19610615|M||C|1200 N ELM STREET^^GREENSBORO^NC^27401-1020|GL|(91-9)379-1212|(919)271-3434||S||PATID12345001^2^M10^ADT1^AN^A|123456789|987654^NC|
NK1|1|JONES^BARBARA^K|WI^WIFE||||NK^NEXT OF KIN
PV1|1|I|2000^2012^01||||004777^LEBAUER^SIDNEY^J.|||SUR||||ADM|A0|

Peu lisible au premier coup d’œil, l’information est pourtant bien compartimentée et le format est efficace, à défaut d’être exprimé dans un format « standard ». Prenons un exemple : la date de naissance du patient venant juste d’être admis pour une hospitalisation se retrouve dans la « case » PID-7 (soit le 7ème champ du segment PID), c’est-à-dire le 15/06/1961.

Le passage à XML

Comme toute organisation spécifiant des messages d’échange, HL7 s’est intéressée à XML, une fois la recommandation du W3C publiée. Seulement ce projet a été mal conduit. Seul le volet syntaxique a été mené, délaissant totalement le volet sémantique. Ainsi, le groupe de travail centré sur XML au sein de HL7 a produit un document proposant un algorithme de convertion de la notation classique à une version XML. Il s’agit là d’une traduction technique des champs et des segments en éléments XML. Le message d’admission précédent au format XML n’est pas insérable ici tellement sa longueur est rédhibitoire. En ne reprenant que le début du segment PID (jusqu’au champ 8), il est possible de se faire une première idée :

Avec le format classique

PID|1||PATID1234^5^M11^ADT1^MR^MCM~123456789^^^USSSA^SS||JONES^WILLIAM^A^III||19610615|M||

En XML

<PID>
  <PID.1>1</PID.1>
  <PID.3>
     <CX.1>PATID1234</CX.1>
     <CX.2>5</CX.2>
     <CX.3>M11</CX.3>
     <CX.4><HD.1>ADT1</HD.1></CX.4>
     <CX.5>MR</CX.5>
     <CX.6><HD.1>MCM</HD.1></CX.6>
   </PID.3>
   <PID.3>
     <CX.1>123456789</CX.1>
     <CX.4><HD.1>USSSA</HD.1></CX.4>
     <CX.5>SS</CX.5>
   </PID.3>
   <PID.5>
     <XPN.1><FN.1>JONES</FN.1></XPN.1>
     <XPN.2>WILLIAM</XPN.2>
     <XPN.3>A</XPN.3>
     <XPN.4>III</XPN.4>
   </PID.5>
   <PID.7>
     <TS.1>19610615</TS.1>
   </PID.7>
   <PID.8>M</PID.8>
   .../...
</PID>

Ainsi chaque champ est entouré de balises qui n’exprime pas sa signification mais sa position technique relative au format original ! Le PID-7 se trouve donc dans l’arborescence <PID><PID.7><TS.1>…</TS.1></PID.7></PID>. Apparaissent également certains types de données. Par exemple, le PID-3 est composé de plusieurs éléments CX. En HL7, CX désigne un identifiant étendu.

Au final

  • La lisibilité est sans doute pire que dans la version initiale,
  • Les messages sont plus complexes, beaucoup plus longs (voir le graphique).

Comparaison du nombre de caracteres (utiles, format classique, XML) du message HL7

Alors, quel intérêt ?

  • La communication entre deux logiciels ? Chaque logiciel capable de produire et de lire du HL7 utilise nativement la version texte. La transformation des messages dans les ESB ou les bus d’échange ? Il est certainement plus rentable de mettre en place un connecteur HL7.
  • La génération automatique d’objets métier grâce à la définition de la grammaire XML (proposée par des librairies de type XMLBeans) ? La définition est tellement technique que cela ne représente aucun intérêt !
  • La validation des messages ? Sans doute l’aspect le plus intéressant. Cependant, il faut savoir que les échanges de messages dans les SIH se basent certes sur les messages HL7, mais ils s’inscrivent également dans des transactions IHE. Le problème est donc complexe.

Conclusion

Si XML est devenu un passage obligé dans la définition de formats d’échange dans les SI, il ne doit pas être utilisé à mauvais escient. Il semblerait que l’exemple d’HL7 version 2.x montre assez bien ce qu’il ne faut pas faire : un projet technique avec un algorithme de conversion automatique. Sans sémantique, les messages XML n’ont aucun intérêt, se révèlent lourds, verbeux, difficiles à manipuler. Et par conséquent, ils ne sont pas utilisés. HL7 doit en être conscient puisque la philosophie XML de la version 3 (toujours en cours) est totalement différente !

XInclude, l’inclusion XML

L’inclusion de fichier est un problème classique, existant depuis les premiers programmes informatiques, quelle que soit la technologie. Curieusement, les spécifications XML (1.0 et 1.1) n’ont pas abordé cette question. Heureusement cinq années après XML 1.0, XInclude vient combler ce manque. Magazine Login: n°129, juin 2005 - Frédéric Laurent

Les longs fichiers monolithiques ont toujours posé des problèmes. A l’inverse, les fragments de fichier permettent de gagner en robustesse, en simplicité de gestion, en factorisation, en partage d’informations, etc. Si c’est vrai pour les programmes (import java, include en C…), ça l’est également pour les documents. Cinq documents de vingt pages sont nettement plus aisés à maintenir et à faire évoluer qu’un long document de cent pages (surtout dans les environnements collaboratifs).

XML n’est pas épargné par ce problème. En ajoutant des balises permettant d’exprimer la structure d’un document, XML enrichit l’information utile, mais la surcharge. Le document est plus gros et plus long. Pouvoir le découper permet de mieux le maîtriser, de réutiliser et de partager les sous-documents et d’assurer une cohérence qui ne peut l’être en dupliquant la même information dans de multiples fichiers. Les exemples d’utilisation sont légion. Un entête et une information sur des droits d’auteur répétés dans chaque page web XHTML, un livre découpé en plusieurs chapitres, des paramètres généraux inclus dans des fichiers de configuration, etc…

Inclusion d'un fichier python dans un document XHTML
Figure 1 : Inclusion d’un fichier
python dans un document XHTML

Cependant, ce sujet semble avoir été oublié par les spécifications et ne fait donc pas partie du coeur de XML. Plusieurs solutions ont donc été imaginées pour faire des inclusions : par exemple, l’utilisation des instructions de traitement ou des entités externes.

Si les instructions de traitement ont l’avantage de pouvoir être placées à tout endroit du document et de ne pas être intrusives pour la DTD ou le schéma (aucune déclaration nécessaire), elles présentent un inconvénient de taille. Elles demandent un traitement spécifique de la part de l’application qui doit reconnaître l’instruction, la traiter et ainsi gérer l’inclusion du fichier. De plus, le processus de gestion des erreurs est totalement déporté dans l’application, voire inexistant.

Une autre solution, l’utilisation des entités externes, s’est plus largement répandue. Elle se base sur un mécanisme défini par les DTD. Il s’agit de déclarer une entité qui fait référence à un fichier externe, désigné par son URI (voir listing 1). Lors du traitement du fichier XML, le processeur remplacera chaque appel d’entité par son contenu. Le processeur lira donc le contenu du fichier externe désigné et procédera au remplacement de l’appel d’entité.

Cependant, ce système d’inclusion est confronté à de nombreuses limitations. Le document inclus ne peut pas être un document XML bien formé de façon globale, car les déclarations <!DOCTYPE> et <?xml ?>ne peuvent pas être présentes et le document importé peut contenir deux racines. Par ailleurs, il n’est pas possible d’importer un document qui n’a pas une syntaxe XML. L’inclusion d’un fichier java devant figurer dans un document XHTML technique est impossible. Si un problème survient lors du chargement du fichier désigné par l’entité, le processeur provoque une erreur fatale. Aucune gestion des erreurs n’est donc possible. De plus, seule la totalité du document peut être importée. Une inclusion plus fine, c’est-à-dire, une inclusion d’un fragment de document est impossible. Enfin, les entités nécessitent d’être déclarées dans le sous-ensemble interne (voir le listing 1) ou dans la DTD. C’est un processus intrusif qui peut avoir des répercutions désagréables.

<?xml version="1.0"?>
<!DOCTYPE html [
  <!ENTITY haut SYSTEM "head.xml">
  <!ENTITY bas  SYSTEM "tail.xml">
]> 

<html>
  <head><title>test entite</title></head>
  <body>
    &haut;
    <p>texte du document</p>
    &bas;
  </body>
</html>

Listing 1 : inclusion à l’aide d’entités externes

L’inclusion avec XInclude

XInclude permet de faire l’inclusion d’un document XML entier, d’un fragment de document XML ou d’un fichier non XML. Le mécanisme est très simple. Il se compose de deux éléments : include et fallback. Ces deux éléments sont présents dans un espace de noms qu’il faut déclarer. L’espace de noms http://www.w3.org/2003/XInclude est souvent associé au préfixe «xi», bien que le préfixe ne soit pas important puisque seul l’URI compte. Le listing 2 montre un exemple simple d’inclusion.

<!DOCTYPE html PUBLIC
   "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr"
   lang="fr" xmlns:xi="http://www.w3.org/2001/XInclude">
  <head><title>test xinclude</title></head>
  <body>
    <xi:include href="head.xml" mce_href="head.xml"/>
    <p>texte du document</p>
    <xi:include href="tail.xml" mce_href="tail.xml"/>
</body>
</html>

Listing 2 : inclusion grâce à XInclude

L’élément XInclude

Les attributs de cet élément en détail… (lire la suite)

L’élément xi:includedéfinit six attributs : href, parse, xpointer, encoding, accept et accept-language (voir encadré 2). Ils permettent de fournir l’information nécessaire en terme de localisation (du fichier et de la zone réelle à inclure qui peut être une partie du fichier), d’encodage et de négociation de contenu. L’inclusion est récursive. Chaque fragment inclus est analysé à son tour et les inclusions qu’il définit sont traitées. Les inclusions circulaires sont détectées et ne peuvent pas aboutir à un processus infini. XInclude permet d’inclure des données, XML ou non, en les considérant comme non-analysables. Cette fonctionnalité, forte intéressante, permet alors d’intégrer des documents Java, C#, python ou même XML dans un autre document (figure 1). Dans ce traitement spécial, les caractères de balisage sont échappés. Le caractère ‘<’, par exemple, est transformé en < ;

Négociation de contenu

L’inclusion de fichier peut faire intervenir des serveurs HTTP locaux ou distants. Certains offrent une gestion de contenu fine, c’est-à-dire prenant en compte la valeur des paramètres accept et accept-language des requêtes HTTP, et ne se contentent pas de renvoyer la même page quelles que soient ces valeurs. Il s’agit de la négociation de contenu. Selon la valeur de ces paramètres, fixée par le client par le biais de ses préférences, le serveur cherche la représentation de la ressource qui correspond la mieux.

La négociation de contenu permet d'obtenir des versions différentes d'une même ressource
Figure 4 : La négociation de contenu
permet d’obtenir des versions différentes
d’une même ressource

XInclude fait l’analogie avec les en-têtes HTTP, puisque l’expression des préférences en matière d’inclusion se fait par l’ajout des attributs accept et accept-language. Le premier définit le format souhaité de la ressource demandée, c’est-à-dire html, text, xml, etc. Le second permet d’exprimer la préférence quant à la langue, il s’agit d’une valeur ayant la forme, fr-Fr, fr, en-us, etc. Une valeur “fr-fr, en” signifie : je préfère une représentation en langue française utilisée en France, par opposition au français utilisé au Canada par exemple, mais j’accepte aussi toute forme de ressource en langue anglaise. Ainsi, il est possible de demander une version française et html d’une page web ou cette même page dans un format XML et en anglais. Par exemple, le serveur web qui héberge la documentation du serveur apache permet d’utiliser la gestion de contenu. Il délivre un URL différent selon la langue choisie. Dans l’exemple suivant, la page française est demandée:

<xi:include href="http://httpd.apache.org/docs-2.0" mce_href="http://httpd.apache.org/docs-2.0"
        accept-language="fr"  accept="text/html"/>

La figure 4 montre un exemple plus détaillée d’utilisation de la négociation de contenu avec ce site.

Gestion d’erreur

L’inclusion de document externe est sujette à tous les problèmes de défaillances informatiques classiques. Le fichier peut être absent, il peut être inaccessible en raison d’un échec du réseau, d’un blocage de requête par un proxy, d’une suppression de la ressource par un tiers, ainsi de suite… La possibilité de définir un comportement en cas d’échec de l’inclusion constitue un apport non négligeable de Xinclude. Cette possibilité était une carence de l’inclusion faite avec les entités externes. L’élément xi:fallback permet de spécifier ce comportement. C’est un élément fils de l’élément xi:include. Son contenu sera inséré à la place de l’élément xi:include en cas d’erreur. Le contenu de xi:fallback est libre. Il peut s’agir d’un simple texte, d’un fragment de document ou d’une nouvelle instruction xi:include, comme nous pouvons le voir dans le listing 3.

<body>
  <xi:include href="head.xml" mce_href="head.xml">
      <xi:fallback>
        <xi:include href="errHead.xml" mce_href="errHead.xml"/>
      </xi:fallback>
  </xi:include>
  <p>texte du document</p>
  <xi:include href="tail.xml" mce_href="tail.xml">
      <xi:fallback>Probleme d'inclusion</xi:fallback>
  </xi:include>
</body>

Listing 3 : gestion des erreurs

L’inclusion conditionnée par la détection d’erreur est intéressante à plus d’un titre. Imaginons l’inclusion d’un document externe EnteteComplexe.xml (listing 4).

<xi:include href="EnteteComplexe.xml" mce_href="EnteteComplexe.xml">
   <xi:fallback>
      <xi:include href="EnteteSimple.xml" mce_href="EnteteSimple.xml">
         <xi:fallback>erreur d'inclusion du fichier
         externe et du fichier alternatif </xi:fallback>
      </xi:include>
   </xi:fallback>
</xi:include>

Listing 4 : inclusion alternative en cas d’erreur

Si celui-ci n’est pas atteignable, un document alternatif, EnteteSimple.xml, sera inclus. Mais s’il ne peut l’être, suite à une nouvelle erreur de localisation du fichier par exemple, on peut imaginer un simple texte laconique, qui sera présent dans le document original et sera donc toujours disponible. Dans tous les cas, la gestion d’erreur est traitée correctement.

L’inclusion partielle

Xinclude permet de faire des inclusions partielles de document. La technologie XPointer permet d’y parvenir. Elle est utilisée à travers l’attribut xpointer de l’élément xi:include. Les processeurs ne sont pas obligés de fournir un support complet de XPointer, seuls le schéma element() et les pointeurs abrégés sont obligatoires. Par ailleurs, certains processeurs, comme celui de libxml ou XInclude.net, offrent la possibilité d’utiliser les schémas xpointer() et xmlns(). Par exemple, l’inclusion ci-dessous permet d’avoir la liste de l’ensemble des documents techniques (Technical Reports ou TR) du W3C, dont le sujet contient RDF :

<xi:include href="http://www.w3.org/TR" mce_href="http://www.w3.org/TR"
  xpointer="xmlns(html=http://www.w3.org/1999/xhtml)
  xpointer(//html:dt[@class='TR']/html:a[contains(
  text(),'RDF')])”>

Inclusion d'un fragment de document distant en utilisant XPointer
Figure 2 : Inclusion d’un fragment de
document distant en utilisant XPointer

Dans l’attribut xpointer, le schémaxmlns() permet de déclarer l’espace de noms du document référencé. Cet espace de noms sera utilisé pour localiser l’information dans le schéma xpointer(). Le contenu du schéma xpointer est une expression XPath, dont une version française pourrait être : “toutes les balises <a> qui ont pour élément père une balise <dt>, dont l’attribut class vaut TR, et dont le contenu textuel (de la balise <a>) contient le texte RDF” (figure 2).

Support de xml:base

XInclude utilise la spécification du W3C xml:base. Le processeur XInclude positionne l’attribut xml:base sur la balise racine du fragment inclus, de sorte que chaque lien relatif, contenu dans le fragment, soit correct. Ainsi deux liens vers doc.xml ne pourront pas être confondus car ils seront relatifs à l’URL spécifié par leur attribut parent respectif. Par exemple, l’incorporation de la liste des technologies proposées par le W3C ne pose pas de problème relatifs aux liens hypertextes, grâce au positionnement d’un attribut xml:base. Les liens ne sont pas modifiés (<a href="/amaya/" mce_href="/amaya/">Amaya</a>) et l’URL est correct car il est chapoté par une déclaration xml:base permettant de construire le lien cible (voir figure 3).

Le processeur insère un attribut xml:base rendant les URL consistants
Figure 3 : Le processeur insère un attribut
xml:base rendant les URL consistants

xml:base peut également être utilisé par le document faisant l’inclusion. Les inclusions seront alors spécifiées relativement à cette base, évitant de ressaisir les URI complets. Cette facilité apporte non seulement de la lisibilité mais aussi de la robustesse car le risque d’erreur dans les URI est diminué.

<doc xml:base="http://www.site.org/mondocument">
  <xi:include href="chapitre1.xml" mce_href="chapitre1.xml" />
  <xi:include href="chapitre2.xml" mce_href="chapitre2.xml" />
  <xi:include href="chapitre3.xml" mce_href="chapitre3.xml" />
</doc>

Quelques limitations

Malgré ses nombreux atouts, XInclude présente quelques désagréments. Cette spécification a pris pas de moins de cinq années pour voir le jour. Ce temps extrêment long dans le domaine des formats XML, a vu éclore nombre de spécifications ne prenant pas en compte XInculde, jugé dans un état instable. Ainsi les définitions de schémas (DTD, XML Schémas, schémas RelaxNG, etc) ont fait l’impasse sur XInclude et cela vient perturber la validation. Il faut en effet déclarer l’espace de noms XInclude pour permettre au processeur de traiter les balises d’inclusion, mais cette déclaration reste dans le document après la transformation. Une spécification XHTML, même récente, ne s’attend pas à trouver une déclaration xmlns:xi="http://www.w3.org/2003/XInclude" sur sa racine.

Support de XInclude

De nombreux processeurs mettent déjà en œuvre XInclude mais de façon très inégale (lire la suite)

Le document, après inclusion sera donc invalide. L’ajout par le processeur de l’attribut xml:base pose le même type de problème. Plusieurs solutions sont envisageables. On peut imaginer de ne pas valider le document résultant, de modifier les grammaires pour prendre en compte ce genre d’information ou encore de définir au niveau même de XML, que les attributs xmlns ou xml:* peuvent être présents à tout endroit dans un document et ne doivent pas être pris en compte par la validation. Quoi qu’il en soit, cet inconvénient risque de prendre du temps avant qu’il ne soit totalement résolu.

Une option à explorer

XInclude vient remplacer l’utilisation délicate des entités externes. Cette nouvelle spécification comble ainsi un manque important dans l’espace XML et formalise un mécanisme d’inclusion robuste, qui utilise les concepts XML fonctionnant par ailleurs (élément, URI, espace de noms, xml :base). Même si certains questions restent posées, notamment sur la post-validation, et que la mise en oeuvre de cette spécification par les processeurs est aujourd’hui disparate, XInclude repésente une avancée vraiment intéressante pour les documents orientés données. Le développement rapide de cette technologie permet d’envisager à terme un support natif par les navigateurs Internet, fournissant alors la possibilité de faire des inclusions dans les pages XHTML.

Les sources de l’article

L’élément XInclude

Les différents attributs de l’élément XInclude sont les suivants :

attributs description
href définit la localisation des données à inclure. L’attribut peut être omis, le document sur lequel se fera l’inclusion sera le document dans lequel est définie cette inclusion. Si hrefest présent, il s’agit d’un URI ou d’un IRI (URI internationnalisé sans obligation d’échapper les caractères spéciaux)
parse indique si le fichier doit être analysé (parse="xml") ou non (parse="text")
xpointer permet de limiter l’inclusion à une partie du document. La définition de la zone restreinte utilise le framework XPointer
encoding permet de définir l’encodage attendu de la ressource lorsque parse="text"
accept permet de fixer l’entête HTTP accept pour définir une préférence sur le format de la ressource à obtenir.
accept-language permet de fixer l’entête HTTP accept-language pour définir une préférence quant à la langue de la ressource à inclure

Support de XInclude

De nombreux processeurs mettent déjà en œuvre XInclude mais de façon très inégale. La principale différence réside dans le support plus ou moins poussé de XPointer et de ses schémas (xpointer(), xmlns(), element()…).

XOM et JDom, par le biais de la brique XIncluder, supportent une partie de XInclude (les fragments et les fallbacks ne sont pas implémentés par exemple). Il en est de même pour Xerces, qui fait cependant l’impasse sur XPointer. GnuJax offre un support également très partiel de XInclude. Enfin, les framework de publication dynamique XML comme Cocoon ou Orbéon offre également un support partiel de XInclude. Libxml fournit un support complet de la spécification, tout comme XInclude.NET qui supporte des schémas XPointer complémentaires (element(), xmlns(), xpath1(), xpointer()). Que ce soient les librairies pour Python (4Suite) , pour perl (Petal ou XML::Filter::XInclude) ou php, les supports sont d’ores-et-déjà présents mais avec des niveaux de complétudes très disparates. Sans doute s’agit-il d’une question de temps.

XML au cœur des suites Office

Moins de deux semaines après l’annonce de la promulgation, par le consortium OASIS, du format OpenDocument au rang de standard, Microsoft annonce à son tour un nouveau format, Office Open XML, pour sa prochaine version d’Office.

XML est plus que jamais la technologie pivot des systèmes d’informations. Déjà au cœur de l’échange des messages et des services, voici que l’ensemble des suites bureautiques se l’approprie. Si OpenOffice a introduit XML très rapidement, fin 2000, comme format de stockage (les documents sxw,sxc,sxi…), Microsoft vient également d’annoncer que les formats propriétaires doc, xls et ppt ne seraient plus les formats de sauvegarde par défaut (ils seront toujours gérés malgré tout) de la nouvelle suite Office, labellisée Office 12. Cette dernière, planifiée lors du second semestre 2006, adoptera un format plus proche de celui d’OpenDocument : une archive zip contenant plusieurs fichiers distincts.

L’apparition des formats ouverts

La standardisation d’OpenDocument 1.0 par l’OASIS (Organization for the Advancement of Structured Information Standards) pose un jalon important. C’est la première fois, qu’un format de document bureautique est défini de façon indépendante d’un éditeur de logiciel, de façon totalement ouverte et qu’il est mis en œuvre avec succès. La précédente tentative, ODA pour Open Document Architecture, fut jugée trop complexe et ne s’est pas imposée face aux formats SGML et RTF, plus simples et pragmatiques. Si OpenOffice 2 est la figure de proue de ce nouveau standard, basé sur celui utilisé par OpenOffice 1.0 et soumis en 2002 par Sun à l’OASIS, les suites bureautiques alternatives l’ont également adopté ou sont en passe de le faire. StarOffice 8, la version fondée sur OpenOffice et vendue par Sun et Koffice, du projet KDE, l’utilisent déjà. Par ailleurs, AbiWord, du projet Gnome, propose un support expérimental. Séduits par cette carte de l’indépendance du format vis-à-vis des logiciels, de grands acteurs comme Adobe, Corel et IBM ont rallié le comité technique d’OASIS afin de contribuer à cet élan.

La préoccupation en termes de formats ouverts n’a pas l’apanage des grands acteurs du monde logiciel. Les documents bureautiques étant une composante essentielle des systèmes d’informations gouvernementaux, l’interopérabilité et la pérennité des informations sont au cœur des attentions des utilisateurs finals. L’Union Européenne a ainsi commandé, en 2003, à la société de conseil Valoris, un rapport sur les différentes tendances et acteurs autour des formats ouverts de document. Suite aux résultats de ce rapport, qui met face à face Microsoft et le format d’OpenOffice, l’Union Européenne fait des recommandations sur l’utilisation de ce type de format pour les administrations publiques. Elle encourage par la même occasion Microsoft et OASIS à prendre des mesures pour rendre leur format plus ouvert et plus conforme aux attentes de ces administrations.

Suite à ces commentaires et à la pression de certains gouvernements, en particulier du gouvernement danois, Microsoft finit par libérer l’accès aux schémas XML utilisés dans Office 2003. Ils sont alors soumis à licence non contraignante, à acceptation tacite, c’est-à-dire sans obligatoire de signature.

C’est devant cette montée en puissance de OpenDocument et pour répondre à la volonté croissante des clients privés et institutionnels, que Microsoft pousse sa stratégie XML beaucoup plus loin. Non seulement, Office 12 sera publié avec les schémas, les formats par défaut seront XML, mais Microsoft agite le drapeau de l’ouverture de son format comme une véritable révolution.

Microsoft exploite donc le travail réalisé sur ses deux formats WordprocessingML et SpreadsheetML, introduits dans la suite Office 2003, pour créer deux nouveaux schémas, incompatibles avec leurs aînés. C’est également l’occasion de combler une absence concernant le logiciel de présentation Powerpoint et de le doter lui aussi d’un schéma XML, ce qu’OpenOffice met en œuvre depuis longtemps déjà. Les suffixes des fichiers se voient agrémenter d’une lettre ‘x’ finale pour les documents ne contenant pas de macros et d’une lettre ‘m’ finale pour ceux qui en possèdent. Nous aurons donc des fichiers .docx, .docm, .xslx, .xslm, etc… Ces formats seront libres de droits et la documentation des schémas sera disponible. A l’instar d’OpenDocument, ils resteront soumis à une licence libre et gratuite. Cependant, seul Microsoft sera capable de les modifier. Les tierces-applications auront alors pour challenge de suivre et de répercuter ces changements.

Techniquement

D’un point de vue technique, les concepts des deux solutions sont très similaires. OpenDocument et Office Open XML se présentent sous la forme de deux archives compressées au format zip (au format jar pour OpenDocument pour être plus précis). Dans ce conteneur, se trouvent divers fichiers XML. Ils représentent les différentes entités du document : contenu, méta-données, informations de style, de présentation, images référencées dans le document…

Tout deux présentent alors des avantages indéniables :

  • taille réduite, grâce à la compression,
  • indépendance vis-à-vis de l’application : chaque document peut être décompressé et tout le contenu est lisible et modifiable à l’aide un simple éditeur de texte,
  • robustesse améliorée à partir du moment où un fichier corrompu (à l’intérieur de l’archive) n’a pas d’impact sur les autres,
  • séparation des concepts : le contenu est clairement séparé de la présentation et des autres informations qui ne sont pas essentielles. Ce mécanisme ouvre la voie de l’évolutivité, de la transparence et de l’agilité des informations. L’abandon d’un format monolithique, difficilement manipulable en dehors de l’outil qui le produit, permet donc d’échanger l’information et de la manipuler facilement. Une feuille de style XSLT pourra, par exemple, suffire à passer d’un format à l’autre,
  • la définition de schéma introduit un concept nouveau pour un document bureautique : la validité. Cette validité permettra de renforcer la qualité d’échange de l’information entre applications,
  • des technologies maîtrisées : XML, W3C XML Schema et le format zip sont des technologies mûres et maîtrisées. De nombreux outils permettent donc de manipuler ces nouveaux formats quelle que soit la plate-forme ou le langage de programmation. Leur prise en main et donc leur adoption seront rapides.

Il reste néanmoins des différences entre les deux formats. Toutes ne sont pas connues, car l’annonce de Microsoft est très en amont de toutes les informations techniques disponibles. On peut noter cependant qu’OpenDocument fournit un seul schéma qui couvre les documents issus du traitement de texte, du tableur, du logiciel de présentation alors que Microsoft fournit un schéma par type de document. OpenDocument utilise une grammaire RelaxNG, dont les bases mathématiques lui offrent un plus forte robustesse de validation par raport aux autres schémas, alors qu’Office Open XML emploie les schémas XML (XSD). OpenDocument se base fortement sur des standards reconnus : HTML, SVG, XSL, SMIL, XLink, XForms, MathML et Dublin Core. Au vu des documents techniques disponibles, Microsoft semblerait ne pas les prendre en compte.

Malgré tout, de façon générale, les deux formats se ressemblent fortement. Une question essentielle est alors sur toutes les lèvres : OpenDocument étant déjà spécifié et identifié comme un standard, pourquoi Microsoft, membre du consortium OASIS, crée encore un nouveau format et n’adopte pas OpenDocument ? Si Dare Obasanjo (spécialiste XML chez Microsoft) se pose en victime face aux détracteurs du nouveau format, Jean Paoli, architecte XML senior chez Microsoft et l’un des artisans de la technologie XML explique ce choix. Il semblerait que l’adoption du format OpenDocument soit impossible, bien qu’il fût qu’envisagé, en particulier à cause des contraintes de compatibilité avec les formats MS Office précédents et de la somme d’utilisateurs des suites bureautiques de Microsoft. Echaudé par la migration à Office 97, Microsoft tente de faire passer sa révolution en douceur auprès de sa base d’utilisateurs. Toujours selon Jean Paoli, le format OpenDocument ne serait pas adapté pour une telle évolution. Par ailleurs, Microsoft mettra à disposition gratuitement des convertisseurs, permettant de prendre en compte ces nouveaux formats dans les produits déjà déployés. Ils seront disponibles pour chaque version d’Office (Office 97 et ultérieures).

À suivre…

Poussé par le rapport de Valoris pour l’Union Européenne, OpenDocument poursuit son chemin de la reconnaissance en tant que standard. La prochaine étape met en jeu l’ISO, au sein duquel le format est proposé. Quant à sa mise en œuvre, elle est d’ores et déjà concrète puisqu’au cœur des nouvelles versions d’OpenOffice, de StarOffice et de KOffice.

La firme de Redmond, quant à elle, déploie son savoir-faire marketing en multipliant les communiqués de presse et les sites dédiés à sa nouvelle technologie, avec des livres blancs (sur les formats, pour les développeurs) sur le sujet présentant nombre de cas d’utilisation. L’outil weblog n’est pas oublié. Brian Jones, travaillant chez Microsoft depuis 6 ans dans l’équipe Office et plus particulièrement sur le support de XML dans Word, en a ouvert un pour l’occasion. Son but est de créer une dynamique autour de ce nouveau format et de donner des réponses rapides à tous ceux qui s’interrogent sur le tournant que prend Microsoft.

Les plus pessimistes jugeront que Microsoft ne fait pas assez ou ne fait pas assez bien et devrait opter pour un format encore plus ouvert. Ils pointeront du doigt une fausse bonne nouvelle, objectant que délaisser OpenDocument au profit de nouveaux schémas est une erreur. Les plus optimistes, au contraire, se réjouiront que le format des documents bureautiques soit enfin accessible de façon simple et qu’il offrira ainsi des possibilités d’échange jamais atteintes jusqu’à présent. Bien qu’on puisse regretter cette disparité de format entre le monde de l’OpenSource et Microsoft, il est intéressant de noter à quel point la technologie XML s’est imposée en moins de dix ans. Cette omniprésence de XML permet désormais d’envisager de vrais scénarios d’interopérabilité de systèmes et d’échange de données.

voir aussi sur le site xmlfr.org:

Hibernate 3.0 ajoute la persistance des documents XML

La nouvelle version d’Hibernate, passé sous le giron de JBoss, permet de prendre en compte, grâce à DOM4j, le traitement et la transformation des documents XML pour rendre leurs données facilement persistantes.

Hibernate est un framework Java de persistance qui permet de faire correspondre des tables de base de données relationnelle avec des objets java simples (POJO ou «Plain Old Java Object»). Une fois la correspondance entre les deux mondes définie, le programme Java peut manipuler toutes les données en utilisant que des JavaBean, masquant alors totalement la base de données sous-jacente et ses spécificités. Le framework assure le remplissage de ces objets et la mise à jour de la base en se basant sur leur contenu. Avant la sortie de la version 3 de ce framework, XML constituait déjà le format de description de la correspondance entre les tables relationnelles et les classes Java.

Hibernate 3 franchit un pas supplémentaire. De la même façon que les POJO permettent de manipuler des objets dont les données sont stockées dans une base de données, cette nouvelle fonctionnalité permet de s’affranchir des solutions XML propriétaires. En effet, chaque fournisseur, se devant de se préoccuper de l’importation/exportation des données XML, fournit une solution qui lui est propre à défaut de se baser sur un standard.

Le framework Hibernate permet d’obtenir une représentation XML du résultat d’une requête. Il permet aussi de rendre persistant, c’est-à-dire d’insérer ou de mettre à jour des données dans la base de données depuis des fragments de document XML de façon très simple et similaire à la manipulation de POJO.

Pour illustrer ces ajouts, prenons l’exemple (extrêmement simple) d’une table contenant une liste de tâches à faire, les fameux TODO. Voici une définition SQL possible de la table TODO_TASK:

CREATE TABLE TODO_TASK (
  TODOID INTEGER NOT NULL PRIMARY KEY,
  SUMMARY VARCHAR(45) NOT NULL ,
  DESCRIPTION VARCHAR(45),
  PRIORITY INTEGER,
  DONE TIMESTAMP);

Hibernate permet non seulement de définir une correspondance entre cette table et un bean Java, mais également entre la table et un document XML. Dans cet exemple, le structure des données XML sera la suivante :

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
      "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="bean">
  <class name="TodoTask"
         table="todo_task" node="todo">
    <id name="todoid" node="@id"/>
    <property name="summary" not-null="true" node="sum"/>
    <property name="description" node="descr"/>    <property name="priority" node="@priority"/>
<property name="doneDate" column="done"/>
  </class>
</hibernate-mapping>

Ainsi, Hibernate fera une correspondance automatique entre, par exemple, le contenu du noeud sum, fils du noeud todo et la colonne summary. Par ailleurs, la colonne done sera disponible dans les beans Java (via la propriété doneDate), mais ne le sera pas dans les fragments XML.

La gestion du XML est assurée par DOM4j. Cette librairie très complète offre le support de DOM, SAX et JAXP mais également des requêtes XPath et de XSLT. Ainsi un document provenant au programme sous une forme SOAP par exemple, peut être transformé dans le format XML pivot par le biais d’une transformation XSLT avant d’être pris en compte par Hibernate. Il peut alors être délivré sous une autre forme, comme un format de sortie SVG, par une autre transformation XSLT. L’association DOM4j/Hibernate permet donc de définir le format XML qui sera utilisé par le métier et délivre un environnement complet de transformation et de traitement de l’information.

Le bout de code Java suivant montre comment, à partir d’un fichier XML, contenant une liste de tâches, hibernate met à jour la base de données relationnelle :

SAXReader sr=new SAXReader(false);
Document doc=null;

try {
  doc = sr.read(ClassLoader.getSystemClassLoader().
                getResourceAsStream("todo-ex.xml"));
} catch (DocumentException e} { ...} 

List todo=doc.selectNodes("//todo");

Session session = sessionFactory.openSession();

Session xmlSession = session.getSession(EntityMode.DOM4J);
Transaction tx=session.beginTransaction();

for (Iterator it=todo.iterator(); it.hasNext(); ) {
xmlSession.saveOrUpdate(”bean.TodoTask”,it.next());
}

tx.commit();

session.close();

Le document est lu grâce à un analyseur syntaxique SAX. La requète XPath permet d’obtenir une liste de tâches Todo. Puis, une session est ouverte. Elle est de type «EntityMode.DOM4J», ce qui indique au framework qu’il doit utiliser la librairie XML et que les données se trouvent dans des fragments XML et non dans des POJO. La boucle les parcourt et les fournit à la session XML qui se charge de mettre la base de données à jour. Le fait de spécifier bean.TodoTask lors de l’action sur la base, permet au framework de connaître à quelle correspondance les noeuds «todo» font référence.

De façon similaire, la consultation de la base peut se faire ainsi :

Element root=docFactory.createElement("todolist");
Document doc=docFactory.createDocument(root) ; Session session = sessionFactory.openSession();

Session xmlSession = session.getSession(EntityMode.DOM4J);
List res=(List) xmlSession.createQuery(”from TodoTask”).list();

for (int i=0; i<res.size(); i++){
  Element elt = (Element) res.get(i);
  root.add(elt);
}

session.close();

Un document hôte est créé de façon classique. La racine accueillera les différents éléments issus du résultat de la requête. Pour afficher le document XML, DOM4j fournit une classe XMLWriter :

XMLWriter xw;

try {
  xw = new XMLWriter(System.out, new OutputFormat("  ",true));
  xw.write(doc);
} catch (Exception e) {...}

Avec cette nouvelle version, Hibernate facilite non seulement la persistance en offrant une couche d’abstraction par rapport à la base de données, mais il permet désormais d’intégrer des données provenant de documents XML, de messages SOAP, de messages JMS, etc… Même si Hibernate n’a pas vocation à devenir un framework spécialiste du XML, cette extension au monde XML renforce les possibilités offertes par le framework pour assurer un découplage des objets métier avec les détails de mise en oeuvre du stockage en base de données relationnelle.

voir aussi :

Hibernate 3.0 ajoute la persistance des documents XML - fichiers d’exemple

Le test suivant se propose de tester la nouvelle fonctionnalité de mapping XML d’Hibernate. Voir l’article associé, pour plus d’informations.

Le projet se compose de plusieurs répertoires :

  • cfg : fichiers de configuration d’Hibernate, de propriétés (hibernate et log) et script pour la création de la table de la base de données
  • res : fichier XML de données, qui seront insérées dans la base
  • src : sources Java du test
  • build.xml: fichier Ant de compilation, exécution du test

Initialisation de la base

La base de données utilisée pour ce test, HSQLdb, est 100% Java et très simple à installer. Après l’avoir téléchargé et décrompressée dans un répertoire, il suffit de lancer le serveur et de provisionner la table. Pour plus d’informations, consulter la note à ce sujet.

java -cp lib/hsqldb.jar org.hsqldb.Server

Une fois le serveur démarré, l’insertion se fait à l’aide du DatabaseManager, par lecture et exécution du script SQL (create_todo.sql) suivant :

DROP TABLE TODO_TASK if EXISTS;

CREATE TABLE TODO_TASK (
  TODOID INTEGER NOT NULL PRIMARY KEY,
  SUMMARY VARCHAR(45) NOT NULL ,
  DESCRIPTION VARCHAR(45),
  PRIORITY INTEGER,
  DONE TIMESTAMP);

INSERT INTO TODO_TASK VALUES(001,'faire le cafe',
  'Prendre 7 volumes deau et 7 volumes de cafe', 1, CURRENT_DATE);

Ce script se situe dans le répertoire cfg du projet.

Lancement du test

Le test se lance grâce au script Ant. Il compile les classes et lance le programme Java MappingXML qui réalise 3 opérations :

  • modification de données via la manipulation d’un POJO (scénario classique)
  • lecture d’un fichier XML et insertion de ses données dans la base en utilisant les facilités d’Hibernate
  • consultation de la base, et génération d’un fichier de résultat au format XML
> ant

...
     [java] <?xml version=”1.0″ encoding=”UTF-8″?>

     [java] <todolist>
     [java]   <todo id=”1″ priority=”1″>
     [java]     <sum>faire le cafe</sum>

     [java]     <descr>Prendre 7 volumes deau et 7 volumes de cafe</descr>
     [java]     <doneDate>2005-05-02 00:00:00</doneDate>
     [java]   </todo>
     [java]   <todo id=”2″ priority=”2″>

     [java]     <sum>Faire une pause</sum>
     [java]     <descr>Allez a la cafet, prendre un cafe avec Bob</descr>
     [java]   </todo>
     [java]   <todo id=”4″ priority=”2″>

     [java]     <sum>installer eclipse</sum>
     [java]     <descr>une nouvelle version est disponible</descr>
     [java]   </todo>
     [java]   <todo id=”5″ priority=”1″>

     [java]     <sum>redemarrer le serveur</sum>
     [java]     <descr>une mise a jour du serveur tartenpion necessite un redemarrage</descr>
     [java]   </todo>
     [java]   <todo id=”6″ priority=”3″>

     [java]     <sum>documentation du product</sum>
     [java]     <descr>faire une documentation complete de notre super produit</descr>
     [java]   </todo>
     [java] </todolist>

all:

BUILD SUCCESSFUL

Le bean Java utilisé est bean.TodoTask et son fichier de correspondance Hibernate, Todo.hbm.xml, se trouve dans le répertoire cfg.

Fichiers

En résumé, voici les fichiers utilisés pour ce test :

 |   build.xml
 |
 +—- cfg
 |       create_todo.sql
 |       hibernate.properties
 |       log.properties
 |       Todo.hbm.xml
 |
 +—- res
 |       todo-ex.xml
 |
 \—- src
       |   MappingXML.java
       |
       \—- bean
                TodoTask.java

XOM : XML Object Model 1.0

XML est définitivement une affaire de personnalités ! Après Michael Kay et son processeur Saxon, Tim Bray et genX, Daniel Veillard et libxml, Elliotte Rusty Harold annonce un nouveau parseur Java XML : XOM 1.0.

Elliotte Rusty Harold est un expert des technologies XML. Auteur de plusieurs ouvrages sur le sujet, il s’est penché de près sur les avantages et les inconvénients des différentes API permettant de manipuler des documents XML. Sa conclusion est assez sévère : les API XML (comme SAX ou DOM) ont été écrites par des programmeurs experts qui découvraient XML. Ainsi le produit de leurs travaux n’était pas, toujours selon Elliotte Rusty Harold, d’une grande qualité. Cette arrogance, l’auteur la justifie par le fait qu’elle est construite sur une forte expérience du domaine et sur son expertise démontrée au fil des ans.

Ainsi, il a passé en revue les quatre types d’API : événementielles type push (comme SAX), événementielles type pull (comme XMLPull ou StAX), celles à base de représentation arborescente (comme DOM, JDOM, etc) et enfin celles dites de «Data Binding» (comme Castor ou JAXB). De toutes ces observations, Elliotte Rusty Harold en a tiré une conclusion. Toutes présentent suffisamment d’inconvénients pour laisser la place à une nouvelle qui tenterait d’être plus pertinente. Les objectifs qu’il fixe pour XOM sont prometteurs !

  • produire du XML correct. XOM est une implémentation de XML 1.0 focalisée sur l’impossibilité de produire du XML mal formé,
  • facile à utiliser grâce à une API intuitive évitant de consulter fréquemment la documentation,
  • facile à apprendre : un seul paquetage nu.xom pour toutes les fonctionnalités principales. Tout ce qui se trouve en dehors est optionnel et peut-être ignoré par un utilisateur débutant. XOM ne doit pas surprendre, les méthodes ont des noms explicites. Si XOM surprend, la surprise doit venir de XML lui-même et non de cette mise en oeuvre Java,
  • rapidité d’exécution et taille en mémoire acceptable : ces aspects ne sont clairement pas des priorités pour l’auteur qui préfère se concentrer sur les points précédents, pour offrir un ensemble stable qu’il pourra optimiser par la suite.

Pour construire cette API, Elliotte Rusty Harold a conjugué principes de conception objet, principes liés à Java et à la nature intrinsèque de XML. Ainsi les classes (il n’y a pas d’interfaces, l’auteur les jugeant inadaptées pour une librairie efficace) possèdent des pré-conditions et des invariants sur lesquels l’utilisateur ne peut passer outre. Seules les méthodes ne mettant pas en péril la conformité vis-à-vis de XML peuvent être surchargées. Et à l’instar des réflexions sur DOM Traversal, XOM n’implémente pas non plus le design pattern Visiteur (des données d’une classe pouvant être manipulées de l’extérieur sans contrôle). Car l’obsession de l’auteur est bien d’assurer l’impossibilité pour un utilisateur de produire un document XML mal formé.

Contrairement aux idées reçues, XOM n’a rien à voir avec JDOM. L’auteur a participé au développement de ce dernier et reconnaît avoir beaucoup appris techniquement. Cependant, en désaccord avec de nombreux principes de conception dans JDOM, il hésita à s’en servir de base pour en créer une nouvelle version. Finalement, il abandonna l’idée et repartit d’une feuille blanche. Si XOM est écrit en Java, l’API se distingue donc de JDOM ou de DOM4j en laissant certaines fonctionnalités inhérentes au langage Java volontairement de côté. Ainsi les classes sont pas «serializable» car XML est lui-même un format offrant cette fonctionnalité et est nettement plus inter-opérable que celui de la «serialisation» java. La notion de classe «Cloneable» est également laissée de côté au profit du copie constructeur classique. Les listes de noeuds utilisent une représentation interne à XOM et ne se basent pas sur les «List» Java, jugées pas assez performantes (notamment vis-à-vis des threads). Enfin, les principes de programmation objet sont respectés puisque les accesseurs en écriture ne retourne pas l’objet lui-même mais le type «void». Ce qui contraste avec les facilités de JDOM, qui permet notamment d’écrire, en une seule ligne

new Element(”html”).appendChild(new Element(”head”))

Les fonctionnalités de XOM 1.0 sont les suivantes :

  • libre, pure Java
  • un nouveau modèle de document XML 1.0. XOM ne supporte pas XML 1.1 (délibérément), qualifié d’abomination par l’auteur
  • support de XInclude
  • support de XML canonique (traduction française)
  • des ponts vers SAX et DOM
  • support de TrAX pour les transformations XSLT

Elliote Rusty Harold prévoit les améliorations suivantes :

Pour faciliter son utilisation, l’auteur fournit un tutorial. Par ailleurs, l’absence du support de XPath et le besoin de faire des requêtes sur les documents ont poussé Wolfgang Hoschek à développer Nux, une extension permettant d’utiliser XQuery (et donc XPath 2.0) avec XOM. Cette mise en oeuvre utilise Saxon-B comme moteur de requêtes.

Si XOM est un logiciel libre, il n’en reste pas moins qu’il est l’oeuvre d’un développeur déterminé à garder le contrôle de son oeuvre. Elliotte Rusty Harold insiste beaucoup sur ce point. Même s’il est ouvert aux critiques et suggestions, il proclame XOM comme une république bananière : «XOM is a more-or-less benevolent dictatorship, not a democracy. I am the only committer. This is my API, and it reflects my thoughts and desires». Cela a au moins le mérite d’être très clair ! XOM est disponible depuis le site xom.nu sous licence LGPL.

Autres articles :

Statistiques en SVG avec Python

XML a apporté son lot de nouvelles applications. SVG est l’une d’entre elles. SVG permet de faire du dessin vectoriel de façon très simple et sans librairie particulière puisqu’il s’agit d’un format XML. Nous allons voir comment utiliser la puissance de python pour collecter des informations sur la taille des répertoires d’un disque et générer un graphique à base d’histogrammes représentant les résultats.
(Login: n°121, novembre 2004 - Frédéric Laurent)

La figure 1 offre un aperçu du diagramme SVG d’occupation du disque que nous obtiendrons avec notre court exemple Python. Pour un répertoire et une profondeur donnés (ici le répertoire c:\Python et une profondeur 2), le graphique permettra de comprendre quels sont les répartitions en termes de pourcentage des différents répertoires contenus dans le chemin initial.

[fichier SVG]

statistiques
Figure 1: Statistiques de l’occupation de la
distribution python

Pour construire un tel graphique, le programme se divise en deux parties. La première permet d’explorer le système de fichiers et de collecter les informations de tailles des répertoires. La seconde partie met en forme ces données. Pour arriver à nos fins simplement, rien de tel qu’un papier quadrillé et un crayon. Il va nous servir à construire très simplement le repère et l’enchaînement des différents rectangles représentant les valeurs en pourcentage de l’espace occupé sur le disque.

Histoire de repères

Le système de coordonnées de SVG est assez classique en informatique. Le point (0,0) se trouve en haut à gauche. L’axe des abscisses croît de gauche à droite et l’axe des ordonnées croît de haut en bas. La figure 2 illustre ce système.

[fichier SVG]

Système de coordonnées SVG
Figure 2: Système
de coordonnées SVG

S’il est courant de rencontrer cette orientation, elle rentre cependant en opposition avec les habitudes prises sur les bancs de l’école. Ainsi, nos souvenirs de mathématiques nous conduisent à réfléchir avec un système un peu différent. Inventé au 17ème siècle par René Descartes, le système cartésien situe l’origine vers le bas de l’écran et si l’orientation de l’axe des abscisses ne changent pas, celui des ordonnées se retrouve inversé, comme l’illustre la figure 3.

[fichier SVG]

inversion
Figure 3: Système de
coordonnées cartésien

Alors comment passer de l’un à l’autre ? Comment réfléchir avec un repère cartésien et avoir un graphique correct ? Deux solutions sont envisageables. La première consiste à concevoir une fonction au niveau du langage de programmation qui fera la conversion des points exprimés dans le système cartésien en des points corrects dans le système de coordonnées de SVG. La seconde utilise les coordonnées cartésiennes directement dans le document SVG et définit les transformations à appliquer sur les éléments graphiques pour obtenir le résultat attendu. Nous allons opter pour la seconde solution. La première transformation fera donc une translation (fonction translate) de tous les points vers le bas. Nous utilisons une translation (30,130) qui correspond à une première translation de (30,30) pour éloigner le graphique du bord du document, à laquelle s’ajoute une translation de (0,100). 100 étant la valeur maximale des ordonnées.

Ensuite, il faut inverser l’axe des ordonnées en l’orientant de bas en haut. La fonction scale qui permet d’appliquer à chaque point un facteur multiplicatif. scale(1,-1) appliqué à chaque point permet de conserver l’abscisse et inverse l’ordonnée. Au niveau du document SVG, un simple bloc englobant permet d’appliquer les transformations à tous les composants graphiques situés à l’intérieur de ce bloc :

<g transform="translate(30,130) scale(1,-1)">
  <rect .../>
  <line .../>
</g>

 

Scalable Vector Graphics

Scalable Vector Graphics (SVG) est un langage XML, né en 1998 peu après la recommandation XML 1.0. Il est issu d’un groupe de travail du W3C. Il permet de …(lire la suite)

L’attribut transform définit la séquence des transformations. Elles sont définies les unes à la suite des autres en les séparant par un espace.

Simple, mais…

Cette transformation globale a l’avantage d’être simple, mais elle inverse tous les points, y compris ceux des caractères ! Toutes les lettres se retrouvent donc à l’envers, voir figure 4.

[fichier SVG]

Inversion des caractères
Figure 4: Inversion des
ordonnées et des caractères

Il faut donc soit les sortir du bloc de transformation et calculer leurs nouvelles coordonnées, soit leur appliquer de nouvelles transformations : scale(1,-1) permet de remettre à l’endroit les caractères. Mais elle fausse par la même occasion le calcul de coordonnées (x,y). Un caractère positionné sur le point P(20,60) se trouve après la première translation en un point P'(50,190) (grâce à la translation de (30,130)). Or il devrait se trouver à P''(50,70) soit 60 points plus haut que l’axe des abscisses (situé à y=130).

[fichier SVG]

Remise à l'endroit des caractères
Figure 5: Remise à l’endroit
des caractères

Le point se trouve donc deux fois trop bas, voir figure 5. Une translation de -60 permet de le remonter sur l’axe des abscisses (y=0 dans le repère cartésien). Une seconde translation de -60 lui permet de trouver sa place (y=60 dans le répertoire cartésien). Il faut donc effectuer un translation pour tous les textes positionnées à (Xorig,Yorig) de (0, -2*Yorig). Maintenant que ces quelques règles sont établies, toutes les données du graphique résultat pourront être exprimées en coordonnées cartésiennes.

Collecter les informations avec python

La collecte des informations du système peut être réalisée à l’aide d’une fonction récursive. Les paramètres à lui fournir sont le nom de répertoire de base et la profondeur de parcours dans l’arbre du système de fichiers. La fonction va alors calculer le poids d’un répertoire donné et stocker dans une liste un tuple d’informations si le niveau du répertoire est compatible avec ce que veut l’utilisateur. Par exemple, l’appel de la méthode gatherSize(r"d:\monrep", 2), recueillera toutes les informations relatives à l’occupation disque du répertoire d:\monrep. Le second paramètre permet de fixer une limite en profondeur afin de synthétiser l’information. Ainsi, les données d’un répertoire d:\monrep\niv2 seront disponibles alors que les données d’un répertoire d:\monrep\niv2\niv3 ne le seront pas. Pour les avoir, il suffit de fournir le nombre adéquat à la méthode, soit 3.

L’utilisation de Python, de son support des tuples, des listes et des fonctions associées comme la somme, le filtrage ou les fonctions lambda permet d’écrire une méthode relativement courte et simple. La somme des tailles de chaque fichier contenu dans un répertoire donné. Pour cela, la fonction listdir récupère la liste de tous les éléments, fichiers et répertoires. Un filtre permet de ne garder que les éléments de type fichier (à l’aide de la fonction de test os.path.isfile). La fonction sum est utilisée pour calculer le poids de cette liste nouvellement créée.

def gatherSize(self, directory, level, deep=1):
listdir = os.listdir(directory)
filelist = filter(lambda
   f: os.path.isfile(os.path.join(directory, f)), listdir)
weight = sum([os.path.getsize(
   os.path.join(directory, name))
   for name in listdir])

 

Python et les listes

S’il y a bien un concept sur lequel Python est éclatant, c’est bien le support natif des listes. Les listes, les fonctions lambda, …(lire la suite)

Puis la même fonction gatherSize est appelée de façon récursive sur chacun des sous-répertoires. De la même façon que pour la liste des fichiers, la liste de répertoires peut être obtenue très simplement à l’aide d’un filtre. Puis, il suffit de faire la somme de toutes les tailles ainsi calculées pour obtenir le poids de la sous-arborescence. Celui-ci ajouté au poids de l’ensemble des fichiers du répertoire constitue le poids total du répertoire passé en paramètre de gatherSize.

subdir = filter(lambda f: os.path.isdir(os.path.join(directory, f)), listdir)
subdir_w = sum([self.gatherSize(os.path.join(directory,f),
                      level,deep+1) for f in subdir])
total = weight+subdir_w

Enfin, il faut déterminer si la profondeur n’est pas trop importante par rapport au besoin de l’utilisateur, et si les informations sont stockées ou non. Une fois le parcours arborescent terminé, les informations sont disponibles sous la forme d’une liste de couples (nom,taille) qui représente la liste des répertoires trouvés.

Production du SVG

Produire du SVG n’est pas compliqué en soi, une fois le système de représentation des coordonnées choisi. Comme il s’agit d’un format XML, plusieurs approches permettent de générer un tel flux. La première consiste à écrire directement le XML sans utiliser de librairie. Rapide à mettre en oeuvre, du moins au départ, la gestion des guillemets rend vite le code illisible et il faut faire attention à produire du XML bien formé. Seconde solution, utiliser les librairies XML, telle que dom, minidom (fournies en standard) ou une libraire tierce (4Dom ou ElementTree). Cette approche permet de produire un XML bien formé en utilisant un code plus clair. Enfin, il existe des API SVG pour python. Elles permettent de s’abstraire facilement de l’implémentation XML sous-jacente et de se concentrer sur les aspects SVG. Celle choisie dans cet article est SVGDraw. Ce n’est pas la plus complète ni la plus complexe, mais elle a l’avantage d’être très simple et de ne constituer qu’un seul fichier à mettre dans le répertoire site-package. Qui plus est, la version windows s’auto-installe. La création du document SVG se fait en deux étapes. La première va créer l’enveloppe globale. Une section déclarative, définie par l’élément SVG defs, contient trois motifs (éléments SVG pattern). Ils serviront à représenter la graduation des axes et la grille de fond. La figure 6 illustre le motif représentant l’axe des abscisses.

 

[fichier SVG]

Motif pour la représentation des graduations de l'axe des abscisses
Figure 6: Motif pour la représentation des
graduations de l’axe des abscisses

Ce motif, d’une largeur de 20, définit deux traits verticaux. Le plus grand représentera toutes les graduations multiples de 20, le petit permettra d’identifier les graduations multiples de 10. Ces deux traits sont définis par des éléments SVG path. Outre les informations relatives au dimensionnement du motif et aux couleurs des traits, l’attribut le plus intéressant est la définition “d” du chemin. Elle consiste en une suite de commandes séparées par une virgule. Chaque commande est construite à l’aide d’une instruction désignée par une lettre (M,V,L,C,S,Q,T,...) et d’une ou plusieurs coordonnées (absolues ou relatives).

<pattern width="20"
   patternUnits="userSpaceOnUse"
   id="axeX" height="10">
   <path stroke="black"
         stroke-width="0.25"
         d="M 0 0, L 0 10" fill="none"/>
   <path stroke="lightgray"
         stroke-width="0.25"
         d="M 10 10, V 5" fill="none"/>
</pattern>

Le premier chemin est défini comme suit : Aller (M i.e Move) au point 0,0, faire une ligne (L i.e Lineto) jusqu’aux coordonnées absolues 0,10. La seconde ligne est définie par : Aller au point 10,10 et tracer une ligne verticale (V ou Vertical Lineto) jusqu’aux coordonnées absolues x,5 (la valeur de x ne change pas puisqu’il s’agit d’une ligne verticale). La spécification d’un attribut id=”axeX” permet de nommer ce motif et il pourra ensuite être utilisé de nouveau dans le graphique SVG, en faisant simplement référence à son nom. Le dessin de l’axe des x se fait donc ainsi :

<rect y="-10" width="240"
   fill="url(#axeX)" x="0" height="10"/>

Le rectangle est positionné plus bas que l’axe (avec des coordonnées cartésiennes), est large de 240 (le motif sera donc appliqué 12 fois) et est rempli avec le motif dont le nom correspond à “axeX”. Les motifs et les dessins effectifs de l’axe des Y et de la grille de fond sont construits sur le même principe.

Les lignes des axes sont dessinées à l’aide de l’élément SVG line et les deux flèches orientant les axes sont réalisées avec l’élément SVG polygon. Enfin, on affiche les informations générales sur le résultat de la recherche : le répertoire source et la taille globale utilisée. La seconde étape de la production du graphique va analyser chaque élément de la liste constituée dans la phase de collecte (voir ci-dessus) et ajouter un rectangle pour la représentation de la barre, et du texte pour afficher les informations relatives. On commence par trier la liste des couples (nom,taille). La taille occupée par le répertoire constitue le facteur de tri. Avec Python, le tri d’une liste constituée d’éléments complexes comme des tuples, des dictionnaires ou des objets se révèle très simple. Il suffit en effet de fournir une fonction de comparaison pour assurer l’opération :

def tupleCmp(self, a,b):
  (nameA, sizeA) = a
  (nameB, sizeB) = b
  return cmp(sizeB,sizeA)# tri des elements selon la taille occupee
self.infos.sort(self.tupleCmp)

Ici seules les tailles sont importantes, elles constituent donc le facteur de comparaison. Puisque c’est l’ordre décroissant qui nous intéresse, la fonction retournera donc 1 si sizeB>sizeA. Enfin, pour chaque élément de la liste, c’est à dire chaque répertoire, une barre est générée (via l’élément SVG rect) ainsi que deux zones de texte (éléments SVG text) : le pourcentage d’occupation et les informations sur le répertoire à proprement dit. Il suffit d’incrémenter à chaque fois l’axe des X, sans oublier d’ajouter les paramètres de transformation pour que les coordonnées cartésiennes exprimées dans la boucle soient cohérentes avec le système de coordonnées de SVG. Une fois, toutes les informations générées, le document SVG en mémoire est exporté vers un fichier XML temporaire. Le module webbrowser permet de lancer une instance du navigateur Internet avec l’URL du document ainsi construit. Le navigateur affiche alors le document SVG résultat. Il est donc nécessaire qu’il dispose du plugin approprié.

En une centaine de lignes de Python, nous avons pu analyser la structure d’un système de fichiers et produire un graphique vectorielle de haute qualité. Il serait simple de le rendre encore plus attractif en ajoutant d’autres éléments SVG. Par exemple, on pourrait obtenir un effet 3D des barres, ajouter une image dans la grille de fond, travailler les fontes avec des ombres, ou ajouter une dimension dynamique au graphique. Maintenant que les bases sont posées, libre à vous de laisser courir votre imagination…

Les sources de l’article

Recherche rapide d’informations grâce à XPath

Avec l’avènement de XML, de nombreuses informations se retrouvent dans des fichiers au format texte structuré de façon arborescente, qu’il s’agisse de fichiers de configuration, de données à proprement parler ou de résultats de requête. Si la structure XML apporte lisibilité et robustesse, le problème d’accès à l’information demeure. Nous allons voir comment XPath y apporte une réponse vraiment puissante.

Magazine Login: n°120, septembre 2004 - Frédéric Laurent

De nombreuses techniques permettent de retrouver une valeur noyée au plus profond d’un arbre XML, mais elles ne sont pas toutes aisées à mettre en oeuvre. XPath, langage non XML, spécifié par le W3C, permet de déclarer de façon concise l’information recherchée. Le travail du programmeur est allégé en terme de code mais aussi de maintenance. Il peut en effet se concentrer uniquement sur la formulation de sa requête (le quoi) et non sur la façon d’y accéder (le comment).

Pour illustrer l’article, nous définissons deux types d’information à retrouver dans deux fichiers XML différents. Tout d’abord, nous souhaitons connaître la liste des servlets déclarées dans un fichier de configuration d’une application web J2EE (le fichier web.xml). Les noms de servlet sont définis par la balise <servlet-name>. Le fichier ne contient pas d’espace de noms. L’expression sera donc très simple. Le second exemple, en revanche, est plus complexe. A partir du fichier d’actualités du W3C (au format RSS 1.0, c’est à dire avec le support des espaces de noms), nous souhaitons connaître les annonces des nouveaux documents de travail. Ce qui revient à localiser le texte des balises <description> dont les balises adjacentes <title> contiennent le mot “Draft”. Cet exemple utilise donc les concepts d’axe XPath, d’espace de noms et de fonction XPath.

Différents types d’accès

Plusieurs techniques sont envisageables pour accéder à une information contenue dans un fichier XML. On peut citer la recherche de texte à l’aide des expressions régulières, l’API SAX, le modèle DOM, les librairies de correspondance (désigné par le terme anglais “binding”) XML vers des objets de n’importe quel langage de programmation, et bien sûr XPath.

Utilisation des expressions régulières

Un fichier XML est un fichier texte. Pendant longtemps, l’utilisation des expressions régulières a fait le bonheur des développeurs devant trouver des données dans ces fichiers texte. Cette technique est donc parfaitement applicable pour retrouver notre liste de servlets. En python, une première version naïve serait la suivante :

servletname="<servlet-name>(.*?)</servlet-name>"
webxml = open("WEB-INF\\web.xml").read()
print re.findall(servletname, webxml)
['invoker', 'CompressionFilterTestServlet', 'HelloWorldExample',
 'RequestInfoExample', 'RequestHeaderExample', 'RequestParamExample',
 'CookieExample', 'SessionExample', 'CompressionFilterTestServlet',
 'HelloWorldExample', 'RequestInfoExample', 'RequestHeaderExample',
 'RequestParamExample', 'CookieExample', 'SessionExample']

Pour ce cas simple, la solution semble parfaite. Cependant, il faudra penser à traiter les retours à la ligne entre la balise ouvrante et le texte à proprement dit. Le code se complexifie alors. Mais surtout comment repérer que <servlet-name>invoker</servlet-name> est déclaré ou ne l’est pas car compris entre un début et une fin de commentaire (resp. <!-- et -->) ? Complexifier encore l’expression régulière ? Ajouter du code pour contrôler cet aspect ? Faire une première lecture pour supprimer toutes les parties XML contenues dans des commentaires et travailler sur cette version épurée ? Les solutions sont multiples, mais elles présentent toutes de nombreux inconvénients. En occultant la sémantique du langage XML, le travail devient complexe et difficilement maintenable. Et que dire de notre second exemple…

Utilisation de SAX

SAX permet de répondre de façon plus intéressante que les expressions régulières car le format XML est traité de façon adaptée : les problèmes d’espaces entre balise et texte, ou de balises entre commentaires se résolvent d’eux-mêmes. Si SAX fournit un moyen rapide d’accéder à l’information puisqu’il est possible de ne prendre en compte que les données qui nous intéressent, il n’en demeure pas moins qu’il faut construire un programme pour trouver les différents noms de servlet. La classe dédiée peut être relativement simple, elle a cependant le principal inconvénient de fixer dans le programme la façon d’accéder à l’information. Si le format évolue, le programme doit être changé, recompilé, redéployé (selon le cas, et le langage).

Utilisation de DOM

L’API DOM, spécifiée par le W3C, permet également d’accéder aux informations des fichiers XML. Une fois le document lu en mémoire dans une structure de données standard, l’accès se fait par l’appel aux méthodes définies sur les classes Document, Element, Attribute… A l’image de SAX, cette solution exploite pleinement la spécificité du format XML et règle nombre de problèmes. Cependant, elle ne résout pas la dépendance entre le code du programme et le format du fichier XML.

S’il existe des alternatives à DOM, comme JDOM ou DOM4J par exemple, qui rendent le code plus concis et plus lisible, les inconvénients exposés ci-dessus persistent.

Utilisation du binding

Il s’agit d’obtenir une représentation du fichier XML sous forme de classe. L’accès est simple, cependant encore une fois, la consultation d’une information impose la génération de code (Java, Python ou autre), sa compilation éventuelle, son déploiement… Tout cela étant sujet à modification, et donc difficilement maintenable. De plus, pour accéder à la liste des noms de servlet, il faut coder explicitement l’accès par des appels à des accesseurs de la classe générée.

Utilisation de XPath

XPath : un langage pour intérroger les fichiers XML

La spécification XPath est assez simple. Peu de notions permettent de composer une expression qui localisera, dans le document XML, une simple valeur, ou un ensemble de noeuds. Une expression XPath définit …(lire la suite)

Face à tous ces problèmes de couplage fort entre le format XML et le code du programme, XPath apporte une réponse vraiment satisfaisante. La requête d’accès à l’information est la seule chose à définir. Le codage de l’affichage du résultat reste indépendant (des informations recherchées). Si la structure du fichier source XML change, seule l’expression XPath doit évoluer. Qui plus est, les instructions qui exploitent le résultat de l’évaluation sont vraiment simples. Il s’agit d’un parcours d’un ensemble de noeuds pour les résultats multiples (ensembles de noeuds, ou "node-set") ou la consultation d’une valeur. Enfin, l’utilisation de cette technologie permet également d’obtenir le résultat en tant que noeud DOM d’un document. Lui ajouter un nouveau noeud fils, un attribut ou du texte est donc une formalité. XPath ne se cantonne donc pas à la seule consultation d’information, mais fournit un véritable moyen d’accès à une partie du document XML. Libre au programmeur d’utiliser le résultat comme bon lui semble.

XPath et la gestion des espaces de noms

Lors de la formulation d’une requête XPath, chaque espace de noms doit être explicitement nommé. Chaque élément doit pouvoir être préfixé… (lire la suite)

L’apparition d’une spécification claire pour l’utilisation d’API XPath s’est faite attendre. La conséquence immédiate est le développement par chaque librairie XML de sa propre API. Ainsi pour Java, Saxon, JDOM, Xalan, DOM4j,… fournissent ce service de façon propriétaire. Le W3C progresse sur une recommandation (qui n’est encore qu’un document de travail), et les différents projets comblent peu à peu ce manque de cohérence. Nous allons voir comment accéder aux informations désirées en utilisant d’une part Saxon et d’autre part l’API standard XPath (uniquement implémentée par Xalan, à ce jour).

Le premier exemple permet de manipuler une expression XPath triviale, puisqu’il s’agit d’obtenir la valeur textuelle de tous les noeuds <servlet-name>. L’expression //servlet-name/text() convient parfaitement. Le second exemple est plus ardu. Une des expressions XPath utilisable (il est possible de fournir de nombreuses autres solutions pour accéder à la même information) est :

//dns1:description[contains(preceding-sibling::dns1:title,'Draft')]/text()

ce qui peut se traduire en français par : prendre le texte de toutes les balises <description> (dans l’espace de noms dns1) qui contiennent un noeud frère nommé <title> (dans l’espace de noms dns1) et dont le contenu contient le mot ‘Draft’.

XPath avec Saxon

Le listing 1 présente comment utiliser Saxon pour obtenir notre liste de servlets. Le programme se contente de lire un fichier XML et d’évaluer l’expression XPath. Une fois le fichier lu (depuis le système de fichiers ou depuis une URL), l’objet XPathEvaluator de l’API Saxon est créé avec la référence sur le flux XML. Il servira à évaluer les requètes. Ce service est rendu par la méthode evaluate(). Elle renvoie un objet du type Java classique [List][23] qu’il suffit de parcourir pour afficher l’ensemble des résultats. Saxon fournit pour la représentation des noeuds, une classe [NodeInfo][24], qui offre contrairement à la classe [Node][25] du W3C, une méthode getStringValue() permettant d’en avoir une représentation textuelle. L’affichage est donc grandement simplifié.

Le listing 2 correspond au second exemple. Il est plus complexe puisqu’il faut gérer les espaces de noms. Chaque couple (préfixe, URI de l’espace de noms) doit être déclaré au niveau de l’évaluateur XPath. Enfin, les espaces de noms par défaut spécifiés dans le document XML (par une déclaration xmlns="http://...") doivent également posséder un préfixe au niveau XPath. Ainsi, la constante DEFAULT_NS_PREFIX définit la valeur textuelle du préfixe à laquelle un entier, incrémenté automatiquement, est accolé. Il n’existe pas de moyen prédéfini pour collecter les espaces de noms d’un document XML. Deux solutions relativement simples sont envisageables. La première consiste à utiliser la récursivité de la structure XML et les méthodes d’accès aux informations fournies par DOM. Le parcours récursif teste tous les attributs de tous les noeuds Element afin de trouver ceux qui commencent par "xmlns". La seconde solution est basée sur l’analyse syntaxique SAX en se concentrant uniquement sur les espaces de noms. C’est cette solution qui est retenue dans notre exemple. Ainsi, avant de fournir le flux XML à l’objet [XPathEvalutor][26], il est analysé une première fois par une classe dérivant du [DefaultHandler][27] de SAX 2. Seul le signal startPrefixMapping(prefix,uri) est utilisé. Cette méthode voit passer chaque déclaration d’espace de noms, elle se charge de l’enregistrer dans un objet [StandaloneContext][28] prévu, entre autres, à cet effet dans l’API Saxon.

Utilisation de l’API XPath DOM niveau 3

Les exemples suivants se basent sur des abstractions d’API. Le but recherché est bien sûr d’être indépendant de toute implémentation, afin d’offrir une pérennité et une maintenabilité plus grandes. La première abstraction concerne la lecture du document. Les documents XML sont lus en utilisant l’API JAXP. Définie par Sun, elle permet de ne pas se préoccuper de l’analyseur syntaxique sous-jacent. L’évaluation XPath se fait en utilisant l’ensemble des classes spécifiées par le groupe de travail DOM du W3C. Ainsi, même si actuellement seule Xalan implémente ce document de travail, l’utilisation de l’évaluateur XPath est indépendante. Dès qu’une autre librairie supportera XPath DOM niveau 3, il sera trivial de remplacer Xalan. Le code de l’exemple n’aura pas besoin d’évoluer (on notera d’ailleurs que les imports utilisés ne dépendent pas de Xalan). Il reste cependant un bémol à cette indépendance. Le document est très jeune, et l’implémentation de Xalan n’est pas finalisée. Ainsi, la création de l’évaluateur XPath est un peu différente de ce qu’elle devrait être (et de ce qu’elle sera dans les mois à venir). En effet, elle est effective en faisant appel explicitement à une classe de la librairie Xalan.

XPathEvaluator evaluator = new org.apache.xpath.domapi.XPathEvaluatorImpl(this.doc);

Dans la version finale, il faudra utiliser le mécanisme d’interrogation (les méthodes isSupported() et getFeature() de l’interface Node) de l’implémentation afin de choisir la bonne façon de créer l’objet XPathEvaluator.

Interroger une implémentation indirectement…

La recommandation DOM Niveau 3 introduit un mécanisme permettant d’agir selon les réponses d’une implémentation… (lire la suite)

Enfin, l’écriture sur la sortie standard du résultat de l’évaluation est également indépendante de toute librairie, puisque c’est une transformation XSLT identité qui l’effectue (la transformation identité prend en entrée un document XML et produit en sortie le même document XML).

Le listing 3 permet d’illustrer l’évaluation d’expressions simples, sans espaces de noms. La méthode evaluate() de l’XPathEvaluator produit un résultat qui est parcouru élément par élément. Chaque élément est affiché sur la sortie standard, par un simple println dans le cas d’un noeud Texte, ou par la transformation identité s’il s’agit d’un fragment de document.

Le listing 4 se charge de traiter les espaces de noms. L’analyse des déclarations d’espace de noms se fait de façon similaire à celle présente dans le listing 2. Par contre, la résolution des préfixes se fait de façon différente. Lors de la lecture du document source, un nouveau document DOM est créé. Son seul but est de porter l’ensemble des déclarations d’espace de noms. On peut se demander pourquoi créer un nouveau document, alors que le document RSS du W3C porte déjà toutes les déclarations sur son noeud racine (<rdf:RDF>). Pourquoi alors ne pas l’utiliser directement ? La raison est simple et double: le fichier RSS n’est qu’un exemple et il s’agit donc d’un cas particulier qui ne fonctionne que dans la mesure ou toutes les déclarations sont faites au niveau le plus haut. Si un nouvel espace de noms (par défaut ou préfixé) est déclaré dans les profondeurs de l’arbre, il ne sera pas pris en compte. De plus, cette méthode permet d’associer, de façon claire, un préfixe pour chaque espace de noms par défaut.

Un évaluateur XPathNSResolver est créé par la méthode createNSResolver(). Il sera consulté à chaque fois que le moteur d’évaluation rencontrera un préfixe et sera chargé de fournir l’URI correspondante. Cet objet est construit à partir du document portant toutes les déclarations, mais une autre méthode pourrait être employée. Elle est sans doute plus simple, mais la jeunesse de l’implémentation la rend indisponible pour l’instant. Le programmeur pourra fournir lui-même une classe implémentant XPathNSResolver. Elle ne rendra qu’un seul service (lookupNamespaceURI(String prefix)): donner l’URI exacte correspondant au préfixe qu’elle reçoit en paramètre. Pour autant, la phase de collecte des espaces de noms ne sera pas supprimée, mais la création du document transitoire pourra être évitée puisque cette classe fournira le renseignement.

Pour conclure…

L’utilisation de XPath n’est certes pas encore complètement standard, mais l’arrivée de la recommandation du W3C risque d’accélérer encore le processus. Cela dit, il ne s’agit là que de questions d’abstraction. Si l’indépendance vis-à-vis d’une librairie particulière n’est pas rédhibitoire, vous avez un large panel d’outils déjà disponibles vous permettant d’exploiter pleinement XPath dans vos programmes. L’intégrer sera d’autant plus intéressant que le nombre de requêtes sera important. Avec une classe utilitaire (helper class), l’accès aux informations de vos fichiers XML gagne en efficacité, maintenance, compréhension. Plus de code à maintenir mais simplement des chaînes de caractères décrivant les requêtes. Voila tout l’intérêt d’utiliser XPath dans vos programmes.

Les sources de l’article