<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Christophe Nowicki &#187; MAVISE</title>
	<atom:link href="http://www.csquad.org/tag/mavise/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.csquad.org</link>
	<description>Just for fun</description>
	<lastBuildDate>Fri, 14 Jan 2011 08:32:33 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Système d&#8217;impression PDF &#8220;RESTful&#8221;  pour le Web</title>
		<link>http://www.csquad.org/2009/02/10/systeme-dimpression-pdf-restful-pour-le-web/</link>
		<comments>http://www.csquad.org/2009/02/10/systeme-dimpression-pdf-restful-pour-le-web/#comments</comments>
		<pubDate>Tue, 10 Feb 2009 21:43:13 +0000</pubDate>
		<dc:creator>cscm</dc:creator>
				<category><![CDATA[Work]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[Cocoon]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[MAVISE]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://www.csquad.org/?p=78</guid>
		<description><![CDATA[Le monde du web et celui de l&#8217;impression, ont décidément du mal à se rencontrer.
La prise en charge de l&#8217;impression est bien souvent très problématique dans le cas d&#8217;un projet web. 
Dans la plupart des cas, il est possible de s&#8217;en sortir en utilisant les possiblités offertes par les feuilles de style CSS.
Mais le rendu [...]]]></description>
			<content:encoded><![CDATA[<p>Le monde du web et celui de l&#8217;impression, ont décidément du mal à se rencontrer.<br />
La prise en charge de l&#8217;impression est bien souvent très problématique dans le cas d&#8217;un projet web. </p>
<p>Dans la plupart des cas, il est possible de s&#8217;en sortir en utilisant les possiblités offertes par les feuilles de style CSS.<br />
Mais le rendu final du document n&#8217;est pas garanti, les différents navigateurs interprètent la feuille de style selon leur humeur<br />
et cela ne fonctionne pas dans le cas de documents complexes.</p>
<p>Dans ce cas, l&#8217;unique solution est de produire un document au format PDF, unique garantie pour une impression de qualité.<br />
Je vais donc décrire dans cet article, la solution que nous avons mis en place dans le cadre du projet MAVISE.</p>
<h3>Historique</h3>
<p>La base de données <a href="http://mavise.obs.coe.int/">MAVISE</a> fourni les données sur l’ensemble des chaînes de télévision accessibles dans l’Union européenne.</p>
<p>Elle a été développé par la société Easter-eggs en collaboration avec <a href="http://www.obs.coe.int/">l&#8217;Observatoire européen de l&#8217;audiovisuel</a> (OEA) pour le compte de la <a href="http://ec.europa.eu/dgs/communication/index_en.htm">DG Communication de la Commission Européenne</a>.</p>
<p>Dans la 1ère phase du projet nous avons développé un système d&#8217;impression avec des feuilles de style.<br />
Ce système ne donnait pas entièrement satisfaction au client. </p>
<p>En effet, les pages du projet étant très complexes, le résultat de l&#8217;impression produite par les différents navigateurs était très aléatoire (coupure en plein milieu d&#8217;un tableau, impression sur plusieurs pages et saut de pages inexpliqués).</p>
<p>Le résultat n&#8217;était pas professionnel et il était difficile pour le client d&#8217;alimenter un rapport avec les contenu de la base.<br />
Nous avons donc proposé de mettre en place un export PDF pour l&#8217;ensemble des éléments de l&#8217;application.</p>
<h3>Choix techniques</h3>
<p>Au fils du temps, je suis devenu un expert de la production de document PDF,<br />
en effet, j&#8217;ai été en charge de l&#8217;export PDF dans de nombreux projets. </p>
<p>J&#8217;ai eu le plaisir d&#8217;utiliser plusieurs API pour produire des documents au format PDF, comme par exemple :</p>
<ul>
<li><a href="http://www.reportlab.org/index.html">ReportLab</a> en Python ;</li>
<li><a href="http://www.fpdf.org/">FPDF</a> en PHP ;</li>
<li><a href="http://pdfapi2.sourceforge.net/">PDF::API2</a> en Perl.</li>
</ul>
<p>Le travail pour produire des documents PDF consiste dans la plupart des cas à dessiner avec l&#8217;aide de ces diffèrentes<br />
API, le contenu du document. (texte, tableaux, graphique et mise en page). </p>
<p>Il s&#8217;agit d&#8217;un travail long et fastidieux, qui consiste à fournir une suite d&#8217;instructions pour former le document.<br />
Cette technique montre vite ses limites :</p>
<ul>
<li>les demandes de modification de la mise en page du  document produit, sont lourdes et nécessitent beaucoup de temps ;</li>
<li>le code pour produire le document est difficilement rationalisable ;</li>
<li>elle ne convient pas à des documents de grande taille.</li>
</ul>
<p>Dans le modèle <a href="http://fr.wikipedia.org/wiki/Mod%C3%A8le-Vue-Contr%C3%B4leur">MVC</a>, qu&#8217;utilise la plupart des applications Web, nous utilisons un système de template pour l&#8217;affichage (la vue).  </p>
<p>Alors pourquoi bon &#8220;coder&#8221; la présentation des documents PDF?</p>
<p>Pour cette raison, j&#8217;ai proposé au client de bâtir le système d&#8217;impression des documents PDF sur un système de <em>template</em>.</p>
<p>Ce système repose sur le langage de programmation <a href="http://www.w3.org/TR/xsl/">XSL-FO</a>, les projets <a href="http://xmlgraphics.apache.org/fop/">Apache FOP</a> et  <a href="http://cocoon.apache.org/">Apache Cocoon</a>.</p>
<h3>Architecture du système d&#8217;impression</h3>
<p><img src='/wp-content/mavise_export_pdf_workflow.png' alt='' /></p>
<ol>
<li>Lorsque l&#8217;utilisateur clique sur le lien PDF,  il est redirigé vers Apache Cocoon ;</li>
<li>Cocoon, récupère l&#8217;ensemble des informations directement sur le site web, via l&#8217;API REST ;</li>
<li>Il agrége les informations dans un document XML ;</li>
<li>Ce document est transformé en FO à l&#8217;aide d&#8217;une feuille de style XSLT ;</li>
<li>Le document est produit par Apache FOP ;</li>
<li>L&#8217;utilisateur obtient le document final. </li>
</ol>
<h3>L&#8217;interface entre le Site Web et Apache Cocoon</h3>
<p>L&#8217;architecture du système d&#8217;impression repose sur le fait que l&#8217;ensemble des variables manipulées par notre application sont accessibles à l&#8217;aide d&#8217;URL <a href="http://fr.wikipedia.org/wiki/REST">REST</a>.</p>
<p>En effet, il est possible d&#8217;afficher le contenu des diffèrentes variables manipulées par l&#8217;application à l&#8217;aide d&#8217;adresses URL spécifiques.<br />
Voici un exemple de sortie :<br />
<code><br />
&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;array&gt;<br />
&lt;is_admin /&gt;<br />
&lt;country&gt;<br />
&lt;id&gt;1&lt;/id&gt;<br />
&lt;iso3166&gt;FR&lt;/iso3166&gt;<br />
&lt;name&gt;France&lt;/name&gt;<br />
&lt;enabled&gt;t&lt;/enabled&gt;<br />
&lt;minimal_age_of_audience&gt;4+&lt;/minimal_age_of_audience&gt;<br />
&lt;/country&gt;&lt;/array&gt;<br />
...<br />
</code></p>
<p>Il est donc possible de récupèrer l&#8217;<strong>ensemble</strong> des informations du site à l&#8217;aide du protocol REST.</p>
<p>Nous avons aussi de très nombreux tableaux dans l&#8217;application, pour les récupérer, nous utilisons le format XML natif du contrôleur de tableaux <a href="http://dhtmlx.com/docs/products/dhtmlxGrid/">dhtmlxGrid</a>.<br />
Voici un exemple de sortie : <a href="http://mavise.obs.coe.int/company?id=1&#038;event=get_grid_xml_list_of_channels&#038;presenter=dhtmlXGrid_xml_loader">fichier XML pour dhtmlxGrid</a>.</p>
<h3>Agrégation des données dans un seul fichier</h3>
<p>Pour récupérer l&#8217;ensemble des données du site dans un fichier XML, j&#8217;utilise la directive <em>include</em>, offerte par Cocoon :<br />
<code><br />
$ cat /var/lib/tomcat5/webapps/cocoon/mavise/program/program.xml<br />
&lt;?xml version="1.0"?&gt;</p>
<p>&lt;page name='program' xmlns:i="http://apache.org/cocoon/include/1.0"&gt;<br />
      &lt;i:include src='cocoon:/webui_program'/&gt;<br />
...<br />
</code></p>
<p>Cette directive dit à Cocoon, d&#8217;inclure le contenu qui se trouve à l&#8217;url <em>cocoon:/webui_program</em>, défini dans le fichier<br />
<em>sitemap.xmap</em> :<br />
<code><br />
      &lt;!-- Webui --&gt;<br />
      &lt;map:match pattern="webui_*/*"&gt;<br />
        &lt;map:generate src='http://localhost/{1}?id={2}&amp;presenter=rest&amp;filter=webui'/&gt;<br />
        &lt;map:serialize type="exml"/&gt;<br />
      &lt;/map:match&gt;<br />
</code></p>
<h3>Transformation XSLT</h3>
<p>Pour transformer les données contenues dans ce fichier, nous avons créé notre propre feuille de style XSLT, pour produire un document FO.<br />
Cette feuille de style prend en compte la mise en forme des diffèrentes données du site.</p>
<p>Grâce à ce système, l&#8217;ensemble de la <strong>mise en forme est centralisé</strong> dans un seul fichier.<br />
Il est aussi possible d&#8217;ajouter du contenu statique dans le PDF à l&#8217;aide de balises dédiées.<br />
Comme par exemple, une balise <em>copyright</em>, qui sera transformées en un texte statique dans tous les documents PDF.</p>
<h3>Le pipeline pour les documents PDF</h3>
<p>Voici le <em>pipeline</em> final pour produire des documents PDF :<br />
<code><br />
      &lt;!-- PDF --&gt;<br />
      &lt;map:match pattern="*/*/*.pdf"&gt;<br />
        &lt;map:generate src='{1}/{3}.xml'/&gt;<br />
        &lt;map:transform src="mk_id.xsl" type="xslt"&gt;<br />
                &lt;map:parameter name="val" value="{2}" /&gt;<br />
        &lt;/map:transform&gt;<br />
        &lt;map:transform type="include"&gt;<br />
           &lt;map:parameter name="parallel" value="true"/&gt;<br />
           &lt;map:parameter name="support-caching" value="true"/&gt;<br />
           &lt;map:parameter name="expires" value="600"/&gt;<br />
        &lt;/map:transform&gt;<br />
</code></p>
<p>Le point intéressant à noter dans ce pipeline est l&#8217;encodage des arguments passés via l&#8217;URL pour le document PDF.<br />
En effet,  les URL pour produire les PDF sont formés de la manière suivante :</p>
<p>http://mavise.obs.coe.int/cocoon/mavise/channel/2157/channel.pdf</p>
<p>L&#8217;URL contient, le nom du module et l&#8217;identifiant de la chaîne.<br />
De cette manière, il est possible de passer d&#8217;autres arguments au système d&#8217;impression (comme par exemple, changer l&#8217;orientation du document).</p>
<h3>Performances</h3>
<p>Au niveau des performances du système d&#8217;impression, nous n&#8217;avons pas une charge très importante sur la génération des documents PDF.<br />
La production des documents est  une tâche complexe et nécessite donc de manière génèrale beaucoup de ressources.<br />
Néanmoins, il y a une chose intéressante à noter au niveau de la génération des documents PDF.<br />
Celle-ci est plus rapide que l&#8217;affichage dans un navigateur.<br />
En effet cela est lié au fait que les échanges de données se font en local sur le serveur, il y a donc moins de bande passante utilisée que dans le cas de l&#8217;affichage de cette même page par le navigateur.</p>
<h3>Les petits désagréments du format PDF</h3>
<p>Nous avons rencontré un petit problème, avec la gestion des polices UTF-8, en effet, comme la base contient des données sur des chaînes de télévision et des entreprises Turques, nous avons eu besoin d&#8217;embarquer une police UTF-8 à l&#8217;intérieur du document.<br />
Et visiblement cela pose des problèmes à certains lecteurs.</p>
<h3>Quelques liens utiles</h3>
<p>Voici quelques liens utiles qui nous ont aidé dans la réalisation de ce système d&#8217;impression :</p>
<ul>
<li><a href="http://howto.landure.fr/gnu-linux/debian-4-0-etch/installer-cocoon-2-1-x-et-fop-0-9x-sur-debian-4-0-etch">Le guide d&#8217;installation d&#8217;Apache Cocoon, FOP sur Debian GNU/Linux</a> ;</li>
<li><a href="http://cocoon.apache.org/2.1/introduction.html">Documentation de la version 2.1 d&#8217;Apache Cocoon</a> ;</li>
<li><a href="http://www.zvon.org/xxl/XPathTutorial/General/examples.html">XPath Tutorial</a> ; </li>
<li><a href="http://www.zvon.org/xxl/XSLTutorial/Output_fre/contents.html">XSLT Tutorial</a> ;</li>
<li><a href="http://www.ecrion.com/Support/Resources/XSL-FO-Tutorial-French/toc.xml.html">XSL-FO</a> ;</li>
</ul>
<h3>Conclusion</h3>
<p>En conclusion, j&#8217;aimerais remercié l&#8217;<a href="http://www.obs.coe.int/">Observatoire européen de l&#8217;audiovisuel</a> (OEA), pour nous avoir fait confiance pour la mise en place de cette solution.<br />
Au 1er abord, le schéma de l&#8217;architecture n&#8217;est pas très engageant <img src='http://www.csquad.org/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>J&#8217;espère que cette solution donnera des idées à d&#8217;autres personnes, pour leur système d&#8217;impression.<br />
L&#8217;objectif final est de faire des économies de papier par rapport à une impression faite via Internet Explorer <img src='http://www.csquad.org/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.csquad.org/2009/02/10/systeme-dimpression-pdf-restful-pour-le-web/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Retour sur l&#8217;optimisation des performances  du projet MAVISE</title>
		<link>http://www.csquad.org/2009/02/04/retour-sur-loptimisation-des-performances-du-projet-mavise/</link>
		<comments>http://www.csquad.org/2009/02/04/retour-sur-loptimisation-des-performances-du-projet-mavise/#comments</comments>
		<pubDate>Wed, 04 Feb 2009 20:42:21 +0000</pubDate>
		<dc:creator>cscm</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[MAVISE]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://www.csquad.org/?p=76</guid>
		<description><![CDATA[La base de données MAVISE fournir les données de base sur l’ensemble des chaînes de télévision accessibles dans l’Union européenne.
Elle à été développer par la société Easter-eggs pour le compte de la DG Communication de la Commission européenne.
Je vais décrire dans cet article les diffèrentes méthodes que nous avons mise en place pour optimiser les [...]]]></description>
			<content:encoded><![CDATA[<p>La base de données <a href="http://mavise.obs.coe.int/">MAVISE</a> fournir les données de base sur l’ensemble des chaînes de télévision accessibles dans l’Union européenne.<br />
Elle à été développer par la société Easter-eggs pour le compte de la DG Communication de la Commission européenne.<br />
Je vais décrire dans cet article les diffèrentes méthodes que nous avons mise en place pour optimiser les performances de cette application.</p>
<h3>Problèmatique</h3>
<p>La base de données contiens beaucoups d&#8217;informations :</p>
<ul>
<li>la description du paysage audiovisuele de 30 pays ;</li>
<li>des fiches sur 5000 chaînes de télévision ;</li>
<li>des fiches sur 4000 entreprises ;</li>
<li>des fiches sur 8000 programmes de télévision ;</li>
</ul>
<p>L&#8217;ensemble des ses données ne sont pas accessibles au grand publique.</p>
<p>D&#8217;un point de vu technique, la base de données <a href="http://www.postgresql.org/">PostgreSQL</a> contient :</p>
<ul>
<li>115 tables ;</li>
<li>100 vues ;</li>
<li>220Mo de données.</li>
</ul>
<p>Cela vous donne une petite idées de la taille de l&#8217;application.<br />
La complexitées de l&#8217;application, la quantité de données disponibles et leur affichage nous as posées de nombreux problèmes :</p>
<ul>
<li>Quantité de données très importante à transferer entre le client et le serveur Web ;</li>
<li>Requêtes complexes au niveau de la base de données ;</li>
</ul>
<h3>Optimisation de la base de données</h3>
<p>Pour l&#8217;optimisation de la base de données, il faut faire attention aux points suivants :</p>
<ol>
<li>L&#8217;<a href="http://fr.wikipedia.org/wiki/ORM">ORM</a> (<a href="http://pear.php.net/package/DB_DataObject">DB_DataObject</a> dans notre cas)  ne doit faire aucune opération de jointure .  Il utilise toujours une vue dédier pour chaque fonctionnalitées ;</li>
<li>Chaque vue ne calcule que les champs qui sont nécessaire à l&#8217;affichage ; </li>
<li>Le plan d&#8217;execution de chaque vue est optimiser à l&#8217;aide d&#8217;index. Pour trouver quels sont les indexes à créer, il faut utiliser l&#8217;instruction <em>EXPLAIN ANALYSE</em> , comme décrit sur le wiki de Postgres : <a href="http://wiki.postgresql.org/wiki/Using_EXPLAIN">Using EXPLAIN</a>.</li>
</ol>
<p>Le travail principal consiste donc à éxécuter toutes les vues de l&#8217;application pour optimiser les plans d&#8217;éxécution à l&#8217;aide d&#8217;indexes.<br />
Pour mieux comprendre la sortie de l&#8217;instruction EXPLAIN ANALYSE, j&#8217;utilise l&#8217;outil suivant : <a href="http://explain-analyze.info/">explain-analyze.info</a>.</p>
<p>Pour savoir quelles sont les optimisations les plus pertinantes, il est intéressant d&#8217;analyser les logs du serveur Postgres à l&#8217;aide du logiciel <a href="http://pqa.projects.postgresql.org/">Practical Query Analysis</a>.</p>
<p>Il faut aussi &#8220;tuner&#8221; la configuration du serveur de base de données pour utiliser le maximum de la mémoire disponible sur le serveur. </p>
<h3>Javascript</h3>
<p>Nous avons utilisé le framework Javascript <a href="http://mootools.net/">Mootools</a>, le contrôleur de tableau <a href="http://dhtmlx.com/docs/products/dhtmlxGrid/">dhtmlxGrid</a> et l&#8217;éditeur de contenu <a href="http://tinymce.moxiecode.com/">TinyMCE</a>. </p>
<p>Dans chaque page de l&#8217;application, il faut faire attention à ne charger que les fichiers nécessaire.<br />
En effet, ces outils, bien que très pratiques sont très volumineux et augementent la taille des pages dans des proportions importantes.  </p>
<p>Dans certains cas, nous avons dépasser plus de 640Ko de code Javascript dans une page <img src='http://www.csquad.org/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Les solutions que nous avons mis en place pour réduire la taille de ces fichiers : </p>
<ul>
<li>La compression Gzip, malheureusement nous avons rencontrer de problèmes très importants avec Internet Explorer ;</li>
<li>Nous avons ensuite opter pour <a href="http://www.julienlecomte.net/yuicompressor/">YUI Compressor</a> qui fonctionne bien mieux ;</li>
</ul>
<h3>Systèmes de Cache</h3>
<p>L&#8217;application dispose de nombreux systèmes de caches :</p>
<ul>
<li>Le <a href="http://www.smarty.net/manual/en/caching.php"> système de cache</a> du gestionaire de <em>template</em> <a href="http://www.smarty.net/">Smarty</a> ; </li>
<li>Notre propre système de cache pour le contenu des tableaux, réalisé à l&#8217;aide du module Pear <a href="http://pear.php.net/package/Cache_Lite">Cache_Lite</a> ; </li>
<li>L&#8217;<a href="http://xcache.lighttpd.net/wiki/XcacheApi">API de XCache</a>, pour certains calculs  et <a href="http://xcache.lighttpd.net/">XCache</a> pour les opcodes PHP ;</li>
<li>Le système de cache d&#8217;<a href="http://cocoon.apache.org/">Apache Cocoon</a> pour le système d&#8217;impression ;</li>
<li>La cache du navigateur des utilisateurs. Il est possible de bien contrôler le contenu du navigateur des clients à l&#8217;aide du module <a href="http://httpd.apache.org/docs/2.0/mod/mod_expires.html">mod_expires</a> d&#8217;Apache.</li>
</ul>
<h3>Réduction de la taille des pages</h3>
<p>Nous avons travailler pour réduire au maximum la taille des échanges entre le navigateur web et le serveur.<br />
Pour cela nous avons utilisé la compression <em>Gzip</em> sur :</p>
<ul>
<li>Le contenu des tableaux ;</li>
<li>Les pages produites par le système de tempate ;</li>
</ul>
<p>Celle-ci est réalisé par le gestionnaire de tempon de PHP, à l&#8217;aide de la fonction <a href="http://fr.php.net/ob_gzhandler">ob_gzhandler</a> ;</p>
<h3>Outils utilisés</h3>
<p>L&#8217;optimisation d&#8217;une application est toujours empirique, il est nécessaire d&#8217;avoir de bon outils pour observer les effets des modifications.<br />
Pour cela nous avons utilisé :</p>
<ul>
<li>Le module <a href="http://getfirebug.com/">Firebug</a>  pour Firefox ; </li>
<li>Et son add-ons <a href="http://developer.yahoo.com/yslow/YSlow">YSlow</a>.</li>
</ul>
<h3>Les liens utiles pour l&#8217;optimisation des performances d&#8217;une application Web</h3>
<p>Pour finir, voici quelques liens très interessants sur l&#8217;optimisation d&#8217;une application Web :</p>
<ul>
<li>Le blog <a href="http://performance.survol.fr/">Performance web</a> ;</li>
<li>Sermon de l&#8217;équipe de Yahoo : <a href="http://developer.yahoo.com/performance/index.html#rules">Exceptional Performance</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.csquad.org/2009/02/04/retour-sur-loptimisation-des-performances-du-projet-mavise/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Validation d&#8217;un fichier CSV à l&#8217;aide d&#8217;un Schéma XML</title>
		<link>http://www.csquad.org/2008/06/03/validation-dun-fichier-csv-a-laide-dun-schema-xml/</link>
		<comments>http://www.csquad.org/2008/06/03/validation-dun-fichier-csv-a-laide-dun-schema-xml/#comments</comments>
		<pubDate>Tue, 03 Jun 2008 06:10:49 +0000</pubDate>
		<dc:creator>cscm</dc:creator>
				<category><![CDATA[Work]]></category>
		<category><![CDATA[CSV]]></category>
		<category><![CDATA[MAVISE]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://www.csquad.org/?p=56</guid>
		<description><![CDATA[Malgré tout le mal qu’il est possible de penser ou de dire sur le format de fichier CSV, celui-ci présente beaucoup d’avantages :

il est facilement manipulable pour les utilisateurs à l’aide d’un tableur comme Calc, Gnumeric ou bien Excel ;
il permet d’écrire rapidement et facilement des routines d’import / export ;
il permet d’échanger les données [...]]]></description>
			<content:encoded><![CDATA[<p>Malgré tout le mal qu’il est possible de penser ou de dire sur le format de fichier CSV, celui-ci présente beaucoup d’avantages :</p>
<ul>
<li>il est facilement manipulable pour les utilisateurs à l’aide d’un tableur comme Calc, Gnumeric ou bien Excel ;</li>
<li>il permet d’écrire rapidement et facilement des routines d’import / export ;</li>
<li>il permet d’échanger les données entre des bases et des systèmes hétérogène.</li>
</ul>
<p>Mais ce format de fichier ne dispose pas d’un système de validation. Dans la plupart des cas ce sont les routines d’import / export qui prennent en charge la validation des données et de leur mise en forme.</p>
<p>Ce travail est pénible, répetitif et ennuyeux mais nécessaire si vous ne voulez pas qu’un fichier mal formaté ne corrompe les données de votre base.</p>
<p>L’objectif de cette article est de proposer une solution simple permettant la validation d’un fichier CSV en utilisant les fonctionnalités offertes par les schémas XML.</p>
<p>Les exemples fournis sont écrit à l’aide du language de programmation PHP5.</p>
<h3>Transformation CSV vers XML</h3>
<p>Votre fichier doit contenir sur la 1ère ligne, le nom de chaque cologne :</p>
<p>
<strong>&#8220;CHANNEL&#8221;;&#8221;COMPANY&#8221;;&#8221;BVD_ID_Groupe_1&#8243;;&#8221;BVD_ID_Groupe_2&#8243;;&#8221;GENRE&#8221;;&#8221;URL&#8221;;&#8221;OTHER_URL&#8221;;&#8221;COMPETENT_AUTHORITY&#8221;</strong><br />
&#8220;Canal+ Film 1&#8243;;&#8221;C MORE ENTERTAINMENT AB&#8221;;&#8221;NL33268595&#8243;;&#8221;DE8330261794&#8243;;&#8221;CIN&#8221;;&#8221;http://www.canalplus.se&#8221;;&#8221;http://www.sbsbroadcasting.com/, http://www.prosiebensat1.de/&#8221;;&#8221;RTVV&#8221;<br />
&#8220;Canal+ Film 2&#8243;;&#8221;C MORE ENTERTAINMENT AB&#8221;;&#8221;NL33268595&#8243;;&#8221;DE8330261794&#8243;;&#8221;CIN&#8221;;&#8221;http://www.canalplus.se&#8221;;&#8221;http://www.sbsbroadcasting.com/, http://www.prosiebensat1.de/&#8221;;&#8221;RTVV&#8221;<br />
&#8220;Canal+ Film 2 Sport Weekend&#8221;;&#8221;C MORE ENTERTAINMENT AB&#8221;;&#8221;NL33268595&#8243;;&#8221;DE8330261794&#8243;;&#8221;CIN&#8221;;&#8221;http://www.canalplus.se&#8221;;&#8221;http://www.sbsbroadcasting.com/, http://www.prosiebensat1.de/&#8221;;&#8221;RTVV&#8221;<br />
&#8220;Canal+ Film 3&#8243;;&#8221;C MORE ENTERTAINMENT AB&#8221;;&#8221;NL33268595&#8243;;&#8221;DE8330261794&#8243;;&#8221;CIN&#8221;;&#8221;http://www.canalplus.se&#8221;;&#8221;http://www.sbsbroadcasting.com/, http://www.prosiebensat1.de/&#8221;;&#8221;RTVV&#8221;<br />
&#8220;Canal+ Film HD&#8221;;&#8221;C MORE ENTERTAINMENT AB&#8221;;&#8221;NL33268595&#8243;;&#8221;DE8330261794&#8243;;&#8221;CIN&#8221;;&#8221;http://www.canalplus.se&#8221;;&#8221;http://www.sbsbroadcasting.com/, http://www.prosiebensat1.de/&#8221;;&#8221;RTVV&#8221;
</p>
<p>Pour transformer le fichier CSV en XML, il suffit de lire le fichier CSV avec la fonction fgetcsv et mettre les données dans des balisent XML : <a href="http://svn.csquad.org/misc/csv_xsd/csv_to_xml.php">csv_to_xml.php</a></p>
<p>Une fichier CSV converti en XML ressemble à cela  : <a href="http://svn.csquad.org/misc/csv_xsd/channel.xml">channel.xml</a></p>
<h3>Validation du fichier XML</h3>
<p>Il ne reste plus qu’à écrire le schéma permettant de valider le fichier XML : <a href="http://svn.csquad.org/misc/csv_xsd/channel.xsd">channel.xsd</a></p>
<p>Vous pouvez tester vos schéma en ligne de commande en utilisant la commande <em>xmllint</em> issue du paquet Debian <em>libxml2-utils</em>   :</p>
<blockquote><p><code><br />
$ xmllint --noout --schema channel.xsd channel.xml<br />
channel.xml validates<br />
</code></p></blockquote>
<h3>Validation en PHP</h3>
<p>Une fois que votre schéma est correct et permet de valider le contenu du fichier XML, il faut l’intégrer directement dans votre application : <a href="http://svn.csquad.org/misc/csv_xsd/validate.php">validate.php</a></p>
<h3>Conculsion</h3>
<p>Cette méthode apporte les avantages suivants :</p>
<ul>
<li>Les règles de validation sont décrites directement via le schéma, et celui-ci dispose de nombreuses fonctionnalités tels les types de bases, les expression rationnelle, les séquences, etc…</li>
<li>Les messages d’erreur sont compréhensibles pour l’utilisateur même, s’il faut parfois les traduire (en convertissant les numéros de lignes et certaines notions) ;</li>
<li>La simplicité ;0)</li>
</ul>
<p>Cette technique a été mise en oeuvre dans le cadre du projet <a href="http://mavise.obs.coe.int/">MAVISE</a> pour valider plus d’une vingtaine de formats de fichiers différents.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.csquad.org/2008/06/03/validation-dun-fichier-csv-a-laide-dun-schema-xml/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Système de synchronisation conditionnel  pour PostgreSQL</title>
		<link>http://www.csquad.org/2008/05/30/systeme-de-synchronisation-conditionnel-pour-postgresql/</link>
		<comments>http://www.csquad.org/2008/05/30/systeme-de-synchronisation-conditionnel-pour-postgresql/#comments</comments>
		<pubDate>Fri, 30 May 2008 13:30:33 +0000</pubDate>
		<dc:creator>cscm</dc:creator>
				<category><![CDATA[Work]]></category>
		<category><![CDATA[MAVISE]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[PostgreSQL]]></category>

		<guid isPermaLink="false">http://www.csquad.org/?p=54</guid>
		<description><![CDATA[Il existe des outils tel que SQLSync permettant de synchroniser les données d&#8217;une base PostgreSQL.  Mais cette outil, ne permet pas de faire une copie partiel des données.
Dans la plus part des cas, il faut programmer la synchronisation soit même, l&#8217;objectif de mon article est de vous proposer une solution simple et  élégante.
La [...]]]></description>
			<content:encoded><![CDATA[<p>Il existe des outils tel que <a href="http://silvercoders.com/index.php?page=sqlsync">SQLSync</a> permettant de synchroniser les données d&#8217;une base PostgreSQL.  Mais cette outil, ne permet pas de faire une copie partiel des données.<br />
Dans la plus part des cas, il faut programmer la synchronisation soit même, l&#8217;objectif de mon article est de vous proposer une solution simple et  élégante.</p>
<h3>La problèmatique</h3>
<table>
<tr>
<td><img src='/wp-content/sync.png' alt='' /></td>
<td valign='top'>Des données sensibles se trouvent dans la base principale et il ne faut synchoniser qu&#8217;une partie de ces données vers les autres bases. </p>
<p>L&#8217;architecture dispose des caractèristiques suivantes :</p>
<ul>
<li>Le schèma est identique sur chaque base ;</li>
<li>Les opèrations d&#8217;écriture se font seulement sur la base principale ;</li>
<li>Les bases sont accessibles en réseau.</li>
</ul>
</td>
</tr>
</table>
<h3>La solution</h3>
<p>
Pour résoudre le problème, j&#8217;ai testé plusieurs approches avant de retenir l&#8217;utilisation d&#8217;un fonction de hachage dont voici le principe :</p>
<ul>
<li>chaque table doit disposer d&#8217;un identifiant unique. (champ id de type SERIAL) ;</li>
<li>un programme récupère le couple <em> id</em> et la sum de <em>hachage</em> pour chaque table de chaque base qui doit être synchroniseés ; </li>
<li>il compare le couple et si celui-ci est diffèrent alors les données sont mise à jour.</li>
</ul>
<h3>Implementation au niveau de la base de données</h3>
</p>
<p>
 Le calcul de la somme de hachage se fait un niveau de la base de données à l&#8217;aide d&#8217;un fonction :</p>
<blockquote>
<pre>
SELECT id,md5 FROM get_table_md5('nom_de_la_table');
 id |               md5
----+----------------------------------
  4 | 9f3bcd2fae528244669613ae0466cc3c
  5 | 1f3bcd2fa24528244669613ae66cc3czd
...
(42 row)
</pre>
</blockquote>
<p>Voici le code de la function PL/Perl:</p>
<blockquote>
<pre>
CREATE LANGUAGE plperl;
CREATE TYPE table_md5 AS (id INTEGER, md5 TEXT);
CREATE OR REPLACE FUNCTION get_table_md5(varchar) RETURNS SETOF table_md5 AS $$
    my ($rv, $status, $nrows, $row);
    # Get Table OID
    $rv = spi_exec_query("SELECT c.oid AS oid FROM pg_catalog.pg_class c
        LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
        WHERE c.relname LIKE '$_[0]';");
    $status = $rv->{status};
    $nrows = $rv->{processed};
    return undef if ($nrows != 1);
    my $oid = $rv->{rows}[0]->{oid};
    # Get Table attributs
    $rv = spi_exec_query("SELECT attname,atttypid FROM pg_catalog.pg_attribute a
        WHERE a.attrelid = $oid AND a.attnum > 0 AND NOT a.attisdropped");
    $status = $rv->{status};
    $nrows = $rv->{processed};
    return undef if ($nrows < 1);
    my $atts;
    my $atts_not_null;
    foreach my $rn (0 .. $nrows - 1) {
        if ($rv->{rows}[$rn]->{atttypid} == 16) {
            $atts .= " (CASE WHEN $rv->{rows}[$rn]->{attname} THEN 't' ELSE 'f' END) AS $rv->{rows}[$rn]->{attname}";
        } else {
            $atts .= " $rv->{rows}[$rn]->{attname}::text";
        }
        $atts_not_null .= " (CASE WHEN $rv->{rows}[$rn]->{attname} IS NULL THEN '' ELSE $rv->{rows}[$rn]->{attname} END)";
        $atts .= ',' if ($rn != $nrows - 1);
        $atts_not_null .= ' || ' if ($rn != $nrows - 1);
    }
    # Calc MD5
    my $sql = "SELECT id, MD5($atts_not_null) AS md5 FROM (SELECT $atts FROM $_[0]) AS $_[0];";
    $rv = spi_exec_query($sql);
    $nrows = $rv->{processed};
    foreach my $rn (0 .. $nrows - 1) {
        return_next({
            id  => $rv->{rows}[$rn]->{id},
            md5 => $rv->{rows}[$rn]->{md5}
        });
    }
    return undef;
$$ LANGUAGE plperl;
</pre>
</blockquote>
<p>Pour utiliser cette fonction vous avez besoin du support du language de programmation PL/Perl dans Postgres, celui-ci se trouve dans le paquet Debian :  <em>postgresql-plperl-<version></version></em>
</p>
<h3>La gestion des conditions</h3>
<p>
Le choix des données à synchroniser se fait individuellement pour chaque table à l&#8217;aide de la clause <em>WHERE</em> de la manère suivante :</p>
<blockquote>
<pre>
SELECT id,md5 FROM get_table_md5('nom_de_la_table') WHERE id IN(SELECT id FROM nom_de_la_table WHERE nom_de_la_table.champ LIKE 'sync');
 id |               md5
----+----------------------------------
  1 | fdd56eabd4bb997e453e33f0022d46c1
(1 row)
</pre>
</blockquote>
<h3>Implementation du script de synchronisation</h3>
<p>
La synchronisation des données peut être réalisée à l&#8217;aide de n&#8217;importe quel language de programmation,<br />
il suffit juste de disposer d&#8217;un accèss à la base de données.
</p>
<p>
Voici un <a href="http://svn.csquad.org/misc/synchro_data/synchro_data.php">exemple de script</a> écrit par  <em>Emmanuel Saracco</em> en PHP5 qui se repose sur les modules <a href="http://pear.php.net">PEAR</a> suivants :</p>
<ul>
<li><a href="http://pear.php.net/package/DB">DB</a> : pour l&#8217;accès à la base de donnée.</li>
<li><a href="http://pear.php.net/package/Console_Getopt">Console_Getopt</a> : pour la gestion de la ligne de commande.</li>
</ul>
<p>Ce script nécessite un fichier de configuration, en voici un <a href="http://svn.csquad.org/misc/synchro_data/synchro_data.ini">exemple</a>.<br />
Ce fichier contiens la configuration des diffèrentes base de données et les conditions sous-forme de clauses where.
</p>
<h3>Conclusion</h3>
<p>Cette méthode de synchronisation fonctionne, elle est en production chez un client pour une base de données de plus de 100 tables, elle permet de synchronisé le contenu d&#8217;une base vers deux autres.<br />
Les avantages de cette méthode sont les suivants :</p>
<ul>
<li>le fait de pouvoir choisir le contenu de la clause <em>where</em> permet de réalisé des <em>régles de synchronisation très complexes</em> ;</li>
<li>les performances sont très bonnes car les transfert réseau sont <em>limités</em> ;</li>
<li>il est possible d&#8217;écrire le script de synchronisation avec n&#8217;importe quel language de programmation.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.csquad.org/2008/05/30/systeme-de-synchronisation-conditionnel-pour-postgresql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

