![]() | Le SGBD-XML eXist est un système open-source sous licence GNU LGPL qui existe depuis quelques années (Wolfgang Meier en 2000) qui est actif et souvent utilisé. Il est utilisable sur toutes les plate-formes courantes (Linux, Mac OS ou Windows). Il exploite de nombreux standard tels que XQuery, XSLT, XPath, XUpdate, etc. Facile à installer, il supporte l'accès concurrent et optimise l'accès aux données par une indexation automatique des données. |
eXist propose une documentation riche. Aussi, dans ce cours, nous n'évoquerons que quelques caractéristiques. Une des caractéristiques essentielles de ce SGBD-XML est le grand nombre de modes d'utilisations qu'il propose, en particulier la possibilité de faire des RIA en ayant XQuery côté serveur !
Une des utilisations les plus intéressantes de ce SGBD est sous forme de service Web. En effet, il propose un serveur d'application ("Jetty") qui permet d'utiliser la base de données XML par l'intermédiaire d'un ensemble de services Web, selon des protocoles différents.
eXist donne la possibilité de créer des applications Web sur la base de XQuery. En effet, le serveur J2EE, couplé à une extension de XQuery permet de gérer aussi bien les requêtes HTML (GET, POST…) que les sessions. Plusieurs modules permettent d'étendre les fonctions standard de XQuery (dans ce qui suit, l'espace de nom associé est entre parenthèses) :
Une "webapp" du serveur permet de traiter les requêtes concernant des fichiers XQuery positionnés dans le répertoire "webapp/xquery". Avec XQuery étendu des modules ci-dessus, couplé avec Javascript (et ses frameworks), CSS, XUpdate et XHTML, il est donc possible de proposer des applications web riches (RIA), comme avec PHP ou Java.
En pratique, mettre en place une "application XQuery" est assez simple. Il suffit de se placer dans le répertoire "/.../eXist/webapp/xquery/" de eXist et d'y créer le répertoire de l'application. Ensuite, il est possible d'y accéder par "http://url:8080/exist/xquery/" (en supposant que le port attribué à Jetty est 8080). Plus concrètement, prenons notre exemple fil-rouge et le tableau de bord.
L'idée est de proposer une application Web. L'essentiel de la tâche est accompli, car le code présenté dans la section sur XQuery génère déjà du XHTML. Il reste donc à le placer dans un répertoire "votation". L'accès au tableau de bord se fait alors par : "http://localhost:8080/exist/xquery/votation/tdb.xquery" par exemple. Maintenant, améliorons un peu cette micro-application. Pour chaque vote clos, l'administrateur veut pouvoir avoir la description détaillée du vote. Il suffit alors de proposer un nouveau "programme XQuery" qui, à partir d'un code de vote, propose sa description. Des liens sont donc positionnés sur chaque vote clos : "
Pour l'affichage d'un vote, il faut inclure le module de gestion des requêtes HTTP. Ensuite, le paramètre est récupéré (avec une valeur par défaut possible). Le reste du code est très classique. Notons tout de même l'exploitation du contexte (en html).
xquery version "1.0" encoding "utf-8"; import module namespace vot = "fr:nantes:univ:votation" at "./moduleVotation.xquery"; import module namespace request = "http://exist-db.org/xquery/request"; declare namespace html = "http://www.w3.org/1999/xhtml"; declare option exist:serialize "method=xhtml media-type=application/xhtml+xml indent=yes encoding=utf-8 omit-xml-declaration=no doctype-public=-//W3C//DTD XHTML 1.0 Transitional//EN doctype-system=http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"; declare variable $code-vote := request:request-parameter("code","v01"); declare variable $vote := collection("maVotation")/Ma-votation/Internaute /Membre/Vote[@Numéro-v eq $code-vote]; document { processing-instruction xml-stylesheet { "href='./section.css'", "type='text/css'" }, <html:html> <html:head><html:title>Tableau de bord des votations</html:title> </html:head> <html:body><html:p>Date : {$vot:now}</html:p> <html:h1><html:center>{xs:string($vote/@Titre)}</html:center> </html:h1> <html:p><html:b>Question</html:b> : {xs:string($vote/@Question)} </html:p> <html:p><html:b>Auteur</html:b> : {fn:concat($vote/../@Prénom-p,' ',$vote/../@Nom-p)} </html:p> <html:p><html:b>Décision</html:b> : {vot:décision($vote)} </html:p> <html:hr/> <html:p><html:b>Oui</html:b> : {fn:count($vote/Bulletin[@Choix eq 'oui'])} </html:p> <html:p><html:b>Non</html:b> : {fn:count($vote/Bulletin[@Choix eq 'non'])} </html:p> <html:p><html:b>Abstention</html:b> : {fn:count($vote/Bulletin[@Choix eq 'abs'])} </html:p> <html:h1><html:center>Description</html:center></html:h1> <html:hr/><html:hr/> {$vote/Contexte/html/body} <html:hr/><html:hr/> <html:p><html:a href='./tdb.xquery'>Retour </html:a></html:p> </html:body></html:html> }
Un exemple d'application Web en XQuery est l'application d'administration de la base qui est accessible une fois le serveur eXist lancé sur "http://localhost:8080/exist/admin/admin.xql".
D'autres API sont aussi disponibles pour exploiter les données dans un SGBD-XML eXist. Parmi celles-ci, l'API REST permet de passer des requêtes à eXist. Plusieurs modes sont disponibles : GET, POST, PUT, etc.
Pour le mode GET, il faut positionner quelques variables dans l'URL étendue. Ces variables sont nombreuses. On trouve, par exemple :
Pour le mode POST, les informations envoyées vers le serveur sont sous la forme soit d'un document XUpdate dans l'espace de noms "http://www.xmldb.org/xupdate" (pour des mises à jours de la base) soit d'un document XML dans l'espace de nom "http://exist.sourceforge.net/NS/exist" dont la forme est décrite ci-desous.
<query xmlns="http://exist.sourceforge.net/NS/exist" start="[first item to be returned]" max="[maximum number of items to be returned]" cache="[yes|no: create a session and cache results]" session-id="[session id as returned by previous request]"> <text>[XQuery expression]</text> <properties> <property name="[name1]" value="[value1]"/> … <property name="[namen]" value="[valuen]"/> </properties> </query>
Bien évidemment, cette solution peut être utilisée par un programme Javascript avec la fonction XMLHTTPRequest.
Pour terminer les services Web, un autre accès à eXist peut être le protocole majeur des services Web : SOAP. Pour cela, eXist propose une description de service en WSDL à l'url "http://localhost:8080/exist/services/Query?wsdl".
remarque : il existe des bibliothèques pour interroger eXist en SOAP, comme par exemple PheXist d'Oscar Celma (en GPL - version archivée). Cette dernière propose une classe PHP "eXist" dont les principales méthodes et variables sont :
eXist peut aussi être interrogée plus directement par une application en utilisant XML-RPC (http://www.xmlrpc.com/). En utilisant cette approche, eXist propose un client pour administrer les données.
eXist propose une API Java dont voici quelques unes des fonctions disponibles :
Remarque : il existe aussi une bibliothèque pour PHP nommée XML-RPC for PHP (Edd Dumbill (C) 1999-2002 - version archivée). Il existe aussi des bibliothèques pour simplifier (un peu) le code (toutes basées sur la bibliothèque XML-RPC for PHP), comme par exemple eXist XML database library d'Eric Hanson (Feb 2005 - version archivée). Elle propose une classe spécifique "eXist", avec comme principales méthodes :
Pour terminer, il est aussi possible d'intégrer eXist à une application Java. Pour cela, eXist propose l'utilisation de l'API XML:DB.
Cet environnement pour accéder à eXist propose nombre de services et de fonctions comme XPathQueryService, XQueryService, XUpdateQueryService… Pour cela, il est nécessaire d'intégrer à l'application Java (et donc dans le classpath) un certain nombre de bibliothèques : exist.jar, start.jar, exist-optional.jar, xmldb.jar...
eXist propose un XQuery avec un grand nombre de fonctions et d'extensions. Ci-dessus, nous avons évoqué le traitement de requêtes HTTP (sessions, POST, paramètres GET...) et l'utilisation de l'API xmldb pour traiter du XUpdate et effectuer d'autres manipulations de la base). Sur ce dernier point, ce SGBD n'intègre pas encore le XQuery Update Facility. Plus ancien que ce standard, eXist propose néanmoins une extension de XQuery qui s'y approche. Il propose les expressions suivantes :
Voici trois exemple d'expressions utilisant cette extension :
- update insert <email type="office">andrew@gmail.com</email> into //address[fname="Andrew"] - update replace //fname[. = "Andrew"] with <fname>Andy</fname> - for $city in //address/city return update delete $city
De même, eXist propose des expressions étendues pour des recherches et manipulations de textes qui ne sont pas XQuery Full-Text, mais qui s'en approchent. De plus, elle utilise une recherche "Full text" en indexant les ressources avec Lucene (outil d'indexation de textes très efficace proposé par la fondation Apache)
Et bien d'autres modules sont proposés que nous en développerons pas ici : manipulation d'images, de courriels…
![]() |
Sedna est un SGBD-XML open-source sous licence Apache License 2.0 développé à l'Institute for System Programming of the Russian Academy of Sciences (ISPRAS) en Russie. Implémentée en C/C++, elle possède des API pour de très nombreux langages (PHP, Java, C, Scheme, Python, etc.). Plus ouverte en API, elle ne permet pas de construire aussi facilement des applications Web comme la précédente, même si elle peut s'intégrer sur un serveur Apache. |
Elle est disponible sur tous les systèmes courants (Linux, Mac OS, Windows...). Elle se manipule à l'aide de commandes en ligne pour lancer le serveur, lancer un client en ligne, installer les bases de données, etc.
Intégrant évidemment XQuery, elle propose une extension pour effectuer les modifications de la base très similaire à celle d'eXist. Elle traite aussi les requêtes XUpdate. De même, Sedna utilise sa propre extension pour les indexations et recherches "plein-texte". Il est aussi possible d’importer des modules, d’indexer les ressources, de mettre en place de "trigger"…
Comme exemple d'utilisation, prenons notre fil-rouge. L'objectif est de faire un petit programme Java permettant de recenser les adresses IP présentes dans la base. Après avoir récupéré la bibliothèque Sedna pour l'API Java dédiée "sednadriver.jar", voici le code développé :
import ru.ispras.sedna.driver.*; public class AccesMaVotation { final static String url = "localhost"; //par défaut, port='5050' final static String dbname = "maVotation"; final static String user = "SYSTEM"; final static String password = "MANAGER"; final static String requete = "<liste-ip>{" + " for $ip in collection('maVotation')/Ma-votation/ Internaute/xs:string(@ip)" + " return <ip>{$ip}</ip>" + "}</liste-ip>"; public static void main(String args[]) { boolean call_res; SednaConnection connection = null; System.out.println("Client lancé ..."); try { connection = DatabaseManager.getConnection(url, dbname, user, password); connection.begin(); SednaStatement st = connection.createStatement(); System.out.println("Exécution de la requête"); call_res = st.execute(requete); if (call_res) printQueryResults(st); connection.commit(); } catch(DriverException e) {e.printStackTrace();} finally { try {if(connection != null) connection.close();} catch(DriverException e) {e.printStackTrace();} } } private static void printQueryResults(SednaStatement st) throws DriverException { int count = 1; String item; System.out.println("Résultat :"); SednaSerializedResult pr = st.getSerializedResult(); while ((item = pr.next()) != null) { System.out.println(count + " item : "); System.out.println(item); System.out.println("================================"); count += 1; } } }
Il donnera comme résultat :
Client lancé ... Exécution de la requête Résultat : 1 item : <liste-ip> <ip>193.52.122.18</ip> <ip>168.155.0.128</ip> <ip>250.157.12.201</ip> <ip>193.34.56.1</ip> <ip>168.102.79.34</ip> <ip>145.111.2.23</ip> <ip>168.134.122.3<</ip> <ip>168.115.056.10</ip> </liste-ip> ================================
Cette même requête peut être lancée directement dans l'outil en ligne :
ed:bin ed$ se_gov GOVERNOR has been started in the background mode ed:bin ed$ se_sm maVotation Starting database recovery or hot-backup restoration... Database is in consistent state. Starting... SM has been started in the background mode ed:bin ed$ se_term maVotation Welcome to term, the SEDNA Interactive Terminal. Type \? for help. maVotation> <liste-ip>{ > for $ip in collection('maVotation')/Ma-votation/Internaute/xs:string(@ip) > return <ip>{$ip}</ip> > }</liste-ip> > & <liste-ip> <ip>193.52.122.18</ip> <ip>168.155.0.128</ip> <ip>250.157.12.201</ip> <ip>193.34.56.1</ip> <ip>168.102.79.34</ip> <ip>145.111.2.23</ip> <ip>168.134.122.3</ip> <ip>168.115.056.10</ip> </liste-ip> maVotation>
Il existe aussi une API XML:DB pour Sedna pour utiliser les protocoles : SOAP, REST...
![]() |
BaseX est un autre SGBD-XML open-source en licence BSD développé par Christian Grün et Alexander Holupirek au DBIS Research Group, université de Kronstanz en Allemagne. En Java comme eXist, il est proposé pour les systèmes classiques (Linux, Mac OS, Windows…). BaseX possède des API aussi bien propriétaires que "classiques" (REST, XML:DB), toujours en Java. Ce SGBD-XML respecte de nombreux standard XML récents dont XQuery Full-Text et XQuery Update Facility. |
Il brille aussi par son client graphique original. La requête est saisie et compilée en temps réel. Le résultat est immédiatement affiché. Ci-dessous, une copie d'écran présente le traitement de la même requête que celle utilisée pour présenter Sedna. Cette copie montre une zone de saisie de la requête, une zone d'affichage du résultat en texte XML et une zone donnant des informations sur le traitement de la requête. La quatrième zone est présenté plus loin. D'autres zones sont possibles (données en tableau par exemple).
Il possède deux outils graphiques intéressants. Le premier consiste en une carte permettant de visualiser l'ensemble des données de la base et d'y naviguer. Cette visualisation, sous forme de rectangles imbriqués, est intéressante, mais pas toujours facile à exploiter directement surtout quand les données sont très nombreuses. L'autre outil intéressant consiste à proposer un graphique 2D sur les données de la base. Il se réfère à un type d'élément XML et propose de choisir les valeurs (élément ou attribut) pour chacun des axes. Les éléments sont alors placés selon ces deux axes. Sélectionner un point sur l'axe permet de sélectionner l'élément dans la partie carte et d'afficher sa forme textuelle.
Tous ces outils sont même intégrés (liés). Prenons la recherche illustrée ci-dessous : "collection('maVotation')/Ma-votation/Internaute/Membre/Vote[@Numéro-v eq 'v01']". On note que le vote sélectionné est en rouge dans la Carte, donné en texte XML et les données concernées dans le diagramme sont aussi en points rouges.
Bien évidemment, il ne faut pas "réduire" BaseX à son seul client graphique. Il peut fonctionner en mode Client/Serveur en Java comme les autres outils.
Dans cette section, nous avons présenté trois SGBD-XML : eXist, Sedna et BaseX. Il en existe d'autres open-sources (XIndice d'Apache, DB-XML d'Oracle) ou non (Tamino de Software AG, IPedo XML, etc.). Les trois outils présentés sont représentatifs, faciles à installer, multi-plate-formes, open-sources et proches des standard. De plus, ils ont des licences permettant une évaluation gratuite de l'ensemble du logiciel et ont des communautés actives (pour les trois, les mises à jours sont très régulières).