dimanche 4 septembre 2011

Les transformations “XSLT” fournissent toujours de précieux services!

Je me suis retrouvé, il y a quelques mois de cela, avec un fichier “xml” contenant toutes les informations dont j’avais besoin, ou presque, pour pouvoir initialiser ma base de données.

Il ne me restait plus qu’à programmer un petit “wrapper” de XML vers SQL. Et avant de me lancer dans des développements avec mon language préféré C#, je me suis souvenu qu’il existait un language de transformation de XML, appelé XSLT, qui permettait de transformer un fichier “xml” en de nombreuses autres choses dont html, doc, pdf, wml et bien d’autres choses encore.

Alors pourquoi ne pas utiliser XSLT pour transformer mon fichier XML en fichier SQL que je n’aurais alors plus qu’ à importer dans ma base de données préférée.

Pour information, il existe plusieurs languages de requêtage XML dont XQUERY et XPATH.

Pour faciliter nos manipulations de XML nous allons utiliser une version d’évaluation d’un excellent outil appelé Altova XMLSpy qui nous permet de créer et tester nos requêtes avant de les appliquer à notre fichier “xml” source et produire notre fichier “sql” destination.

xmlspyaltova


Description du contexte

En observant le fichier “xml” source on note qu’il contient 2 catégories d’objets qui nous intéressent plus particulièrement: l’objet “Computer” et l’objet “User”. On constate que le champ “computerid” nous manque dans le fichier “xml” source pour permettre la création de l’objet “Computer” dans la table '”Computer” de la base de données. De même un champ “guid” nous manque pour permettre de créer un objet “User” dans la table “User” de la base de données.

Dans le fichier “xml” source, le paramètre “UserID” de l’objet “Computer” correspond au paramètre “UserID” de l’objet “User” auquel il appartient.

Dans la base de données, la valeur du “guid” de l’objet “Computer” doit avoir la valeur du “guid” de l’objet “User” auquel l’objet “Computer” appartient.

Le paramètre “computerid” de la la table “Computer” est initialisé à une valeur unique incrémentée à partir de 200.

Le paramètre “guid” de la la table “User” est initialisé à une valeur unique incrémentée à partir de 100.

Création des fichiers "xsl"


La première étape consiste à créer le(les) fichiers “xsl” décrivant la(les) transformation(s) à effectuer.

Commençons par écrire le fichier “guid_generator.xsl” ci-dessous permettant de créer le champ “guid” pour l’objet “User”:

<xsl:stylesheet version="1.0" xmlns:xsl="
http://www.w3.org/1999/XSL/Transform">

<xsl:variable name="guid" select="100"/>
<xsl:template match="@*node()">
<xsl:copy>
<xsl:apply-templates select="@*node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="User">
<User>
<xsl:apply-templates select="@* *"/>
<guid>
<xsl:choose>
<xsl:when test="not(preceding-sibling::*)">
<xsl:value-of select="$guid"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$guid + count(preceding-sibling::*)"/>
</xsl:otherwise>
</xsl:choose>
</guid>
</User>
</xsl:template>

Le champ “guid” est initialisé à 100. Puis on copie simplement le contenu du fichier source; et si l’objet XML est “User” alors on ajoute aux champs existants, un champ “guid” auquel on donne une valeur initiale (i.e. 100) à laquelle on ajoute le nombre d’objets “User” que l’on vient de parcourir. Simple et efficace!

Il ne nous reste plus qu’à transformer le fichier généré précédemment en fichier “sql” en créant le fichier “insert_generator.xsl” ci-dessous. On profite cependant de cette transformation pour donner une valeur au champ “computerid” nécessaire à la création de la table “Computer” (cette valeur est initialisée à 200):

<xsl:stylesheet version="1.0" xmlns:xsl="
http://www.w3.org/1999/XSL/Transform">

<xsl:output method="text"/>
<xsl:variable name="computerid" select="200"/>
<xsl:template match="/">
<xsl:apply-templates select="//ComputerList"/>
<xsl:apply-templates select="//UserList"/>
</xsl:template>
<xsl:template match="User">
<xsl:text>INSERT INTO USER"("GUID", …, "MODIFDATE")
VALUES(</xsl:text>
<xsl:value-of select="./guid"/>
<xsl:text>,'</xsl:text>
<!—…-->
<xsl:text>SYSDATE);&#xA;</xsl:text>
</xsl:template>
<xsl:template match="Computer">
<xsl:param name="temp"><xsl:value-of select="./UserID"/></xsl:param>
<xsl:text>INSERT INTO COMPUTER"("COMPUTERID","GUID",…, "MODIFDATE")
VALUES(</xsl:text>
<xsl:choose>
<xsl:when test="not(preceding-sibling::*)">
<xsl:value-of select="$computerid"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$computerid + count(preceding-sibling::*)"/>
</xsl:otherwise>
</xsl:choose>
<xsl:text>,</xsl:text>
<xsl:value-of select="//UserList/User[UserID=$temp]/guid"/>
<xsl:text>,'</xsl:text>
<!—…-->
<xsl:value-of select="./ExpirationDate"/>
<xsl:text>');&#xA;</xsl:text>
</xsl:template>
</xsl:stylesheet>

Comme dit précédemment, notons qu’un objet “Computer” est associé à un objet “User” dans le fichier source “xml” au travers du paramètre “UserID”. La valeur du paramètre “UserID” de l’objet “Computer” courant est sauvegardée dans un paramètre appelé “temp” afin de permettre la récupération du “guid” correspondant à l’objet “User” ayant un “UserID” correspondant à “temp”, car c’est ce “guid” là qui doit être associé à l’objet “Computer” courant. Est-ce clair! Oui, bon on continue…

Les fichiers “xsl” nécessaires à nos transformations sont enfin écrits. Il ne nous reste plus qu’à installer notre parseur XML préféré, j’ai nommé Xalan installé sous C:\.

La génération du fichier “sql” se passe en 2 étapes:

cd C:\xalan-j_2_7_1
java -classpath "C:\xalan-j_2_7_1\xalan.jar";"C:\xalan-j_2_7_1\xercesImpl.jar";"C:\xalan-j_2_7_1\serializer.jar";"D:\xalan-j_2_7_1\xml-apis.jar" org.apache.xalan.xslt.Process -IN input.xml -XSL guid_generator.xsl -OUT output.xml
pause
java -classpath "C:\xalan-j_2_7_1\xalan.jar";"C:\xalan-j_2_7_1\xercesImpl.jar";"C:\xalan-j_2_7_1\serializer.jar";"D:\xalan-j_2_7_1\xml-apis.jar" org.apache.xalan.xslt.Process -IN output.xml -XSL sql_insert_generator.xsl -OUT output.sql
pause

La première étape permet de prendre le fichier “xml” source appelé “input.xml” et le transformer en un autre fichier “xml” appelé “output.xml” contenant également un champ “guid” incrémenté. Ce champ est nécessaire pour insérer l’objet “User” dans la table “User”. C’est le fichier “guid_generator.xsl” qui permet cette transformation.

La deuxième étape prend en entrée le fichier “output.xml” et le transforme en “output.sql”. C’est le fichier “insert_generator.xsl” qui permet cette transformation. Il permet également de créer un champ “computerid” et de lui donner une valeur unique pour permettre la création de l’objet “Computer”' dans la table “Computer” de la base de données.

Le tour est joué!

Note
: pour des raisons de confidentialité vous ne trouverez pas les fichiers “input.xml”, “output.xml” et “output.sql”. Mais je suis à votre entière disposition pour répondre à toutes questions!

Aucun commentaire:

Enregistrer un commentaire

Partager avec...