Transférer les styles des fichiers OpenDocument
Le 29 décembre 2008 à 12:04, 2ième version du billet (corrections).

Contrairement à certaines idées reçues, OpenDocument, LE format bureautique normalisé et ouvert, n'est en rien lié à OpenOffice. A l'origine OpenOffice utilisait même un système totalement propriétaire. Ce n'est qu'après que le groupe de travail OASIS ait publié l'Open Document Format (aka ODF), et que ce format ait été démocratiquement normalisé contrairement à certains autres, qu'il est apparu en standard dans la célèbre suite libre. Du coup, l'ODF est aussi disponible pour d'autres logiciels (ex. ABIWord) devenant ainsi le format de prédilection pour toute personne ou organisation qui tient un tant soit peu à ce que ses documents ne soient pas liés aux contingences commerciales d'un éditeur.

Mais outre le fait que ce format soit ouvert et normalisé, il est en plus très simple à manipuler. Nous avions déjà vu comment l'exploiter pour ajouter des vignettes à Nautilus, ici l'objectif est de créer un script PERL très simple dont le but est de permettre la recopie du style d'un document vers un autre.

Le besoin

Généralement, lorsque l'on fabrique régulièrement des documents, on finit toujours par avoir une palanquée de modèles. Ces modèles peuvent être un template (ODT) ou plus simplement un document "vierge" qui a été pré-formaté. Avec Nautilus ce type de documents est très facilement utilisable par un click-droit/Créer un document affichant la liste des modèles présents dans le dossier ~/Modèles (cela peut varier d'une distribution à l'autre, le mieux est de regarder dans le fichier ~/.config/user-dirs.dirs).

Jusque là tout va bien et OpenOffice ouvre un nouveau document créé à partir de la recopie du modèle sélectionné. En revanche cela se corse lorsqu'il s'agit de mettre à jour le modèle. En effet, il n'est pas rare qu'au fil de la rédaction d'un document, on ait tellement fait évolué les styles du modèle d'origine que l'on aimerait bien les y replacer. Alors il est certes possible de faire cela à la main par le menu fichiers/Modèles/Gérer mais s'il s'agit de transferer 20 nouveaux styles et d'en mettre à jour une dizaine d'autre, l'exercice n'est pas des plus marrant. L'idée est donc de créer un script qui va littéralement synchroniser les styles du modèle d'origine à partir de ceux d'un document existant.

Le format ODF

L'opération peut sembler complexe mais fort heureusement l'ODF est très bien conçu. N'importe quel fichier ODF est en effet une simple archive ZIP contenant une série des fichiers XML. Et l'un de ces fichiers XML contient l'ensemble des styles du document. Il suffit donc de transférer ce fichier d'une archive à l'autre pour recopier l'ensemble des styles. Il en va de même pour les réglages liés aux documents (par exemple l'affichage ou la couleur de la grille d'une feuille de calcul). Du coup, la recopie de deux simples fichiers va nous permettre de régler notre problème à un détail prés, les images.

En effet, si vos styles utilisent des graphiques comme par exemple pour les fonds de type "bitmap", il va falloir aussi recopier le dossier Pictures de l'archive avec un effet secondaire plus ou moins gênant : la recopie par la même occasion d'images du document d'origine n'ayant rien à voir avec les styles. Dans une première approximation, nous allons nous dire que ce n'est pas bien gênant car ces images, n'étant liées à rien dans le nouveau document, elles seront automatiquement détruites lors de sa sauvegarde. En somme une recopie brutale ne fera au pire qu'augmenter inutilement la taille du modèle. Il serait certes possible de les filtrer intelligemment à partir du fichier XML contenant les styles mais cela rendrait notre script un peu trop compliqué pour un trop faible intérêt.

Mise en oeuvre

Le script qui suit est écrit en perl et il est, je pense, relativement parlant de lui-même. Il s'agit juste de sélectionner le modèle cible dans une liste grâce à Zenity, de décompresser le document source et le modèle dans deux dossiers distincts, de recopier les fichiers styles.xml, settings.xml et le dossier Pictures, puis de recompresser l'ensemble pour écraser le modèle d'origine. Une copie de sauvegarde du modèle est conservée au cas où dans le dossier le dossier temporaire.

#! /usr/bin/perl

use File::Path;
use File::Basename;
use File::Copy;

sub get_absolute_path {
  my ($source)=@_;

  # conversion des accents nautilus
  $source =~ s/%([0-9A-Fa-f]{2})/chr(hex($source))/eg;

  # si le chemin n'est pas absolu, on va ajouter ce qu'il faut
  if ($source !~ /^\//) {
    # par défaut, on part du principe que c'est le chemin courrant
    my $pwd=$ENV{PWD};

    # On vérifie si variable d'environnement du chemin courrant
    # de Nautilus est présente. Si oui, on extrait la partie de l'URI
    # correspondant au chemin.
    my $nautilus=$ENV{'NAUTILUS_SCRIPT_CURRENT_URI'};
    if ($nautilus && $nautilus =~ /^file:\/\/(.*)$/) {
      $pwd = $1;
      $pwd =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
    }
    # suppression de l'éventuel slash terminal
    $pwd =~ s/\/$//;
    $source="$pwd/$source";
  }
  if ( ! -e "$source") {
    change_status(error=>"Impossible de localiser $source");
  }
  return $source;
}

my $models_path=$ENV{HOME}."/Modèles";
my $workspace="$ENV{TMP}/ooo";
my $source_path="$workspace/source";
my $style_path="$workspace/style";

# ménage
rmtree($workspace);
mkpath($source_path);
mkpath($style_path);

# récupération des sources
my $source=get_absolute_path($ARGV[0]);

# décompression de la source
print "Décompression de la source\n";
`cd $source_path; unzip "$source"`;

# sélection du style
my @files = <$models_path/*>;
my $templates;
foreach $file (@files) {
  if ( -f $file ) {
     $templates.=' "'.basename($file).'"';
  }
}
$template=`zenity --list --column "modèle"  --title="Choisissez votre modèle" $templates`;
chop($template);

print "Décompression du style à modifier\n";
`cd "$style_path"; unzip "$models_path/$template" 2>&1`;
move ("$models_path/$template", $workspace."/".$template);


print "Application du document sur le modèle\n";
`cd $source_path; cp -af styles.xml settings.xml Pictures $style_path`;

print "Recompression du modèle\n";
`cd $style_path; zip -vr9 "$models_path/$template" *`;
Script de sauvegarder des styles d'un document vers un modèle (Sources)

Dans ce script, la liste des modèles est récupérée dans le dossier ~/Modèles, libre à vous de changer ce chemin pour les chercher dans un autre dossier. Ensuite il suffit de lier ce script (ln -s ...) dans le dossier ~/.gnome2/nautilus-scripts pour en bénéficier dans Nautilus par un click droit. La procédure get_absolute_path est d'ailleur avant tout là pour rendre ce script compatible avec ce gestionnaire de documents. En revanche, si vous sélectionnez plusieurs documents, seul le premier sera traité.

Il est aussi possible de faire la même chose dans l'autre sens, c'est à dire en recopiant le style d'un modèle sur un ensemble de documents.

#! /usr/bin/perl

use File::Path;
use File::Basename;
use File::Copy;

sub get_absolute_path {
  my ($source)=@_;

  # conversion des accents nautilus
  $source =~ s/%([0-9A-Fa-f]{2})/chr(hex($source))/eg;

  # si le chemin n'est pas absolu, on va ajouter ce qu'il faut
  if ($source !~ /^\//) {
    # par défaut, on part du principe que c'est le chemin courrant
    my $pwd=$ENV{PWD};

    # On vérifie si variable d'environnement du chemin courrant
    # de Nautilus est présente. Si oui, on extrait la partie de l'URI
    # correspondant au chemin.
    my $nautilus=$ENV{'NAUTILUS_SCRIPT_CURRENT_URI'};
    if ($nautilus && $nautilus =~ /^file:\/\/(.*)$/) {
      $pwd = $1;
      $pwd =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
    }
    # suppression de l'éventuel slash terminal
    $pwd =~ s/\/$//;
    $source="$pwd/$source";
  }
  if ( ! -e "$source") {
    change_status(error=>"Impossible de localiser $source");
  }
  return $source;
}

my $models_path=$ENV{HOME}."/Modèles";
my $workspace="$ENV{TMP}/ooo";
my $source_path="$workspace/source";
my $style_path="$workspace/style";

# ménage
rmtree($workspace);
mkpath($source_path);
mkpath($style_path);

# récupération des sources
foreach (@ARGV) {
  my $source=get_absolute_path($_);

  # décompression de la source
  `cd $source_path; unzip "$source"`;

  # sauvegarde au cas où...
  move ($source, $workspace."/".basename($source));

  # sélection du style
  my @files = <$models_path/*>;
  my $templates;
  foreach $file (@files) {
    if ( -f $file ) {
       $templates.=' "'.basename($file).'"';
    }
  }
  $template=`zenity --list --column "modèle"  --title="Choisissez votre modèle" $templates`;
  chop($template);
  print "Application du modèle '$template' sur $source\n";

  print "Décompression du style associé\n";
  `cd "$style_path"; unzip "$models_path/$template" 2>&1`;

  print "Application du modèle\n";
  `cd "$workspace"; cp -af style/settings.xml style/styles.xml style/Pictures source`;

  print "Recompression du fichier\n";
  `cd "$source_path"; zip -rv9 "$source" * 2>&1`;
}
Script d'application d'un style à une ensemble de documents (Sources)

Pour ce script là, il sera possible de sélectionner un ensemble de documents. Veillez seulement à ne prendre que des items du type du modèle à appliquer (ex. Traitement de texte, tableur, présentation, etc.).

Conclusion

Ici nous synchronisons nos modèles à partir d'un document, il est aussi possible de faire l'inverse pour "relooker" un document existant en lui appliquant un modèle. Ce sera à peu prés le même code mais en inversant le sens de synchronisation. Les sources de ces deux scripts à jour sont disponibles ici.

Commentaires

Dab, le 29 December, 2008 - 14:50

Intéressant, j'avais justement dans l'idée d'ajouter un 'formatter' à Catapulse pour la prise en charge de l'ODF. Suite à ton article j'ai un peu fouillé sur le Net et il semblerai qu' Openoffice 3 dispose de feuille xslt pour une transformation en xhtml1.1. Du coup la forme des documents devient simplement dépendante de CSS.
Sais tu s'il existe un 'plugin' Drupal pour l'importation de document OOO ?

Ulhume, le 1 January, 2009 - 12:48

Non, pas à ma connaissance. C'est un sujet sur lequel je réfléchit pas mal pour un client en utilisation conjointe avec mon module WebDAV. L'idée étant de débarrasser les utilisateurs (des journalistes) de cette calamiteuse interface WEB au profit d'un oo-writer. Mais pour l'instant l'idée est encore sur le papier Smiling

Poster un nouveau commentaire

Si vous avez détecté une erreur, coquille ou bêtises du même ordre, merci de plutôt passer par le formulaire de contact
Pour vous abonner au flux des commentaires sur cet article, clickez ici.
Pour répondre à quelqu'un, utilisez plutôt le lien répondre qui se trouve en haut (ou en bas) à gauche de son commentaire.
Le contenu de ce champ est gardé secret et ne sera pas montré publiquement. If you have a Gravatar account, used to display your avatar.
  • To highlight piece of code, just surround them with <code type="language"> Your code &tl;/code>>. Language can be java,c++,bash,etc... Everything Geshi support.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <blockquote> <div>
  • Les lignes et les paragraphes vont à la ligne automatiquement.
  • Textual smileys will be replaced with graphical ones.
  • Les adresses de pages web et de messagerie électronique sont transformées en liens automatiquement.

Plus d'informations sur les options de formatage


Connexion utilisateur
Les derniers bavardages...