• # J'ai !

    Posté par . En réponse au message xml to sql. Évalué à 3.

    J'ai fait un truc dans le genre en Perl - avec les bons modules, c'est assez facile : XML::Parser - pour parser l'xml, oeuf corse - et Template Toolkit - pour transformer les données en bon gros fichier SQL. Modulo quelques erreurs de retranscription, l'idée est de générer une arborescence des données à partir du xml, et de l'utiliser comme données d'entrée d'un template. Le xml :
    <database name="db">
     <table name="foo">
    	<col name="id" type="int(10) unsigned" notnull="yes" ai="yes" pk="yes"/>
    	<col name="label" type="varchar(255)" notnull="yes"/>
     </table>
     <table name="bar">
     ...
    </database">
    
    Le template :
    DROP DATABASE [%database%];
    CREATE DATABASE [%database%];
    USE [%database%];
    [%- FOREACH item = tables; %]
    CREATE TABLE `[%item.name%]` ( 
    [%- sep = ''; FOREACH col = item.cols; sep %]
     `[%col.name%]` [% col.type -%] 
    	[%- IF col.notnull; %] NOT NULL[% END; -%] 
    	[%- IF col.ai;%] auto_increment[% ELSE %] default [% col.default; END; -%]
    [% sep=','; END; -%]
     [%- sep %]
     PRIMARY KEY ([% sep=''; FOREACH pk = item.pks; sep; "`"; pk.name; "`"; sep=', '; END; %])
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
    [% END; %]
    
    Le script :
    use XML::Parser;
    use Template;
    my $data;
    my $tables;
    my $currentTable;
    my @cols;
    my @pks;
    sub database {
     my ($o, $class, %args) = @_;
     $vars->{database} = $args{name};
    }
    sub table {
     my ($o, $class, %args) = @_;
     undef @cols;
     undef %currentTable;
     $currentTable{name} = $args{name};
    }
    sub col { 
     my ($o, $class, %args) = @_;
     $my $col = { name => $args{name},
     type => $args{type},
     default => $args{default},
     auto_increment => $args{ai}, 
     };
     push (@cols, $col);
     push (@pks, $col) if exists $args{pk} and $args{pk} eq "yes";
    }
    sub table_ {
     my @c = @cols;
     $currentTable{cols} = \@c;
     @{$currentTable{pks}} = @pks;
     my %h = %currentTable;
     $tables{$h{name}} = \%h;
     push (@tables, $h{name});
    }
    sub database_ {
     $vars->{tables} = [ map { $tables{$_} } @tables ];
    }
    my $parser = new XML::Parser(Style => 'Subs');
    $parser->parsefile($fichier) or die "Failed\n";
    my $tt = Template->new();
    						
    $tt->process($tmpl, $data, $outfile) || do {
     my $error = $tt->error();
     print $error, "\n";
    };
    
    Le principal intérêt de ce truc c'est de créer plusieurs templates en fonctions des SGBD, ou carrément créer un template pour générer le code en C par ex pour faire quelques requêtes classiques (update/select/delete).