#! /usr/bin/perl # add_els_ns.pl : diagnostic et ajout de namespaces # pour les fichiers XML elsevier # -------------------------------------------------------------------------- # message /help/ en fin de ce fichier version: 0.1 (03/10/2014) # copyright 2014 INIST-CNRS contact: romain dot loth at inist dot fr # -------------------------------------------------------------------------- use warnings ; use strict ; use Data::Dumper ; # flag interne my $debug = 0 ; # namespaces "ajoutables" : liste de référence # --------------------------------------------- my %ADDABLE_NS = ( 'ja' => 'http://www.elsevier.com/xml/ja/dtd' , 'ce' => 'http://www.elsevier.com/xml/common/dtd' , 'sb' => 'http://www.elsevier.com/xml/common/struct-bib/dtd' , 'xlink' => 'http://www.w3.org/1999/xlink' , 'sa' => 'http://www.elsevier.com/xml/common/struct-aff/dtd' , 'mml' => 'http://www.w3.org/1998/Math/MathML' , 'tb' => 'http://www.elsevier.com/xml/common/table/dtd' , 'cals' => 'http://www.elsevier.com/xml/common/cals/dtd' , 'xocs' => 'http://www.elsevier.com/xml/xocs/dtd' , 'xs' => 'http://www.w3.org/2001/XMLSchema' , 'xsi' => 'http://www.w3.org/2001/XMLSchema-instance', ) ; # lecture XML en entrée # ---------------------- # unique argument attendu : chemin fichier input my $filepath = undef ; if ((not defined ($ARGV[0])) || ($ARGV[0] =~ /--?h(?:elp)?/)) { HELP_MESSAGE() ; } else { $filepath = $ARGV[0] ; } # slurp FILE => $content my $content = "" ; open (FILE, "< $filepath") || die "ERR: impossible d'ouvrir '$filepath'\n" ; while (<FILE>) { $content .= $_ ; } close (FILE) ; # namespaces réellement utilisés # ------------------------------- # hash "checkliste" des ns utilisés my %needed_ns = () ; # match de tous les ns en présence dans le doc # sur forme /<tartampion:/ my @match_ns = ($content =~ m/(<| )([^\/:> ]+):/g) ; # report dans le hash => unicité for my $ns (@match_ns) { $needed_ns{$ns} = "present" ; } # namespaces actuellement déclarés # --------------------------------- # liste des ns déclarés my @declared_ns = () ; # capture de la déclaration root $content =~ m/(<(((?:converted-)?(?:simple-)?article)|serial-issue|book-review|exam)[^>]*+>)/ ; my $root_tag = $1 || die "ERR: je ne trouve pas de balise root du type <article...>, <simple-article...>, <converted-article...>, <serial-issue...>, <book-review...> ou <exam...> dans le document '$filepath'\n" ; # Exemple de match : # <article xmlns="http://www.elsevier.com/xml/ja/dtd" version="5.1" xmlns:ce="http://www.elsevier.com/xml/common/dtd" xmlns:sb="http://www.elsevier.com/xml/common/struct-bib/dtd" xmlns:xlink="http://www.w3.org/1999/xlink" xml:lang="en" docsubtype="fla"> @declared_ns = ($root_tag =~ /xmlns:([^=]+)/g) ; # différence : (utilisés) privé de (déclarés) # -------------------------------------------- for my $ns (@declared_ns) { delete $needed_ns{$ns} || next ; } my @remaining_ns = keys(%needed_ns) ; if ($debug) { warn "à ajouter pour doc '$filepath':\n" ; warn Dumper \@remaining_ns ; } # est-ce qu'il reste quelquechose ? # --------------------------------- if (scalar(@remaining_ns)) { # construction nouvelle balise # ----------------------------- # chaîne avec déclarations à ajouter my $insert_str = "" ; for my $ns (@remaining_ns) { my $uri = $ADDABLE_NS{$ns} ; if (defined $uri) { my $declaration_str = 'xmlns:'.$ns.'="'.$uri.'"' ; $insert_str .= ' '.$declaration_str ; } } # création de la nouvelle balise root my $new_root_tag = $root_tag ; # les déclarations sont ajoutées à la toute fin par substitution du chevron fermant $new_root_tag =~ s/>$/${insert_str}>/ ; warn $new_root_tag if ($debug) ; # remplacement balise root par la nouvelle balise # ------------------------------------------------ # regexp-isation de la chaine à remplacer my $regexp_old_root_tag = quotemeta($root_tag) ; # remplacement dans le contenu du fichier $content =~ s/$regexp_old_root_tag/$new_root_tag/ ; } # SORTIE : # - le doc est resté tel quel si la différence de ns était vide # - sinon on lui a substitué son tag 'root' par un semblable avec # insertion des déclarations ns manquantes open (OUTFILE, "> $filepath") || die "ERR: impossible de réécrire dans '$filepath'\n" ; print (OUTFILE $content) ; close (OUTFILE) ; # renvoie le message d'aide # ------------------------- sub HELP_MESSAGE { print <<EOT; ------------------------------------------------------------ | Ajout des namespaces manquants dans XML Elsevier | |----------------------------------------------------------| | Usage | | ===== | | perl add_els_ns.pl from_elsevier.xml | | | | Principe | | ======== | | Le script liste par regexp les namespaces (NS) utilisés | | réellement dans les balises de ce document. | | Ensuite il compare avec la liste des NS déclarés dans | | la balise racine <article..> ou <converted-article..> | | | | Vitesse sur ma machine : 24 docs /s | | | | Sortie | | ======= | | Le doc est inchangé si tous les NS étaient bien | | déclarés. | | Sinon on lui remplace sa balise racine par une autre | | qui reprend les mêmes infos + les déclarations pour | | les préfixes manquants. | | | |----------------------------------------------------------| | © 2014 Inist-CNRS (ISTEX) romain.loth at inist dot fr | ------------------------------------------------------------ EOT exit 0 ; }