Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1810 connectés 

  FORUM HardWare.fr
  Programmation
  Perl

  supprimer certaines balises d'un fichier xml

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

supprimer certaines balises d'un fichier xml

n°2311141
nafawana
apprentie
Posté le 14-02-2018 à 16:34:52  profilanswer
 

Bonjour
 
J'ai réussi à construire un code permettant d'extraire des infos d'un fichier xml et les écrire dans un fichier texte grâce à la librairie TWIG.
Aujourd'hui, je cherche à adapter ce code pour supprimer certaines lignes et générer un xml allégé. je me suis tournée vers la fonction "twig_print_outside_roots".  
Mon problème est que la sélection des lignes à supprimer ne fonctionne pas, càd que toutes les balises sont supprimées sans distinction.
 
Mon fichier xml d'entrée :

Code :
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <OUT>
  3. <IN>
  4.     <SIMULATION affectation="dynamique" pasdetemps="1" periode_affectation="10801" proc_deceleration="false" seed="1" titre="">
  5.     </SIMULATION>
  6. </IN>
  7.     <INSTANTS>
  8.         <INST nbVeh="0" val="1.00">
  9.             <CREATIONS/>
  10.             <TRAJS/>
  11.             <STREAMS/>
  12.             <SGTS/>
  13.         </INST>
  14.         <INST nbVeh="1" val="2.00">
  15.             <CREATIONS/>
  16.             <TRAJS>
  17.                 <TRAJ abs="650804.90" acc="-1.00" dst="14.41" id="0" ord="6861842.70" tron="TRONROUT0000000000193776" type="VL" vit="13.00" voie="3" z="0.00"/>
  18.             </TRAJS>
  19.         </INST>
  20.         <INST nbVeh="3" val="3.00">
  21.             <CREATIONS/>
  22.             <TRAJS>
  23.                 <TRAJ abs="650804.90" acc="-1.00" dst="14.41" id="0" ord="6861842.70" tron="TRONROUT0000000000193776" type="VL" vit="13.00" voie="3" z="0.00"/>
  24.                 <TRAJ abs="650631.10" acc="0.50" dst="10.42" id="5" ord="6861493.18" tron="TRONROUT0000000000195409INDIRECT" type="VL" vit="9.55" voie="2" z="0.00"/>
  25.                 <TRAJ abs="651309.38" acc="0.50" dst="36.52" id="6" ord="6861503.32" tron="TRONROUT0000000000195361_0" type="VL" vit="10.80" voie="1" z="0.00"/>
  26.             </TRAJS>
  27.         </INST>
  28.     </INSTANTS>
  29. </OUT>


 
 
Le code testé :

Code :
  1. #!/bin/perl -w
  2. use strict;
  3. use XML::Twig;
  4. my $FichierXML = 'test.xml';
  5. my $FichierOUT = 'traj_mini.xml';
  6. open( my $OUT, '>', $FichierOUT )
  7. or die("Impossible d'ouvrir le fichier $FichierOUT\n$!" );
  8. my $line ="TRONROUT0000000000193776";
  9.                                            
  10. my $twig = new XML::Twig(
  11. twig_roots    => { 'TRAJ' => 1 },
  12.  twig_print_outside_roots => $OUT,
  13.  Twig_handlers => {
  14.   'TRAJ' => \&Fonction,},
  15.   PrettyPrint =>'indented',
  16. );
  17.    
  18. $twig->parsefile( $FichierXML);             
  19. sub Fonction
  20. { my( $twig, $TRAJ)= @_; 
  21.     
  22.  if ($TRAJ->att('tron') ne "TRONROUT0000000000193776" )
  23.  {$TRAJ->cut;}
  24. }


 
 
Merci pour votre aide


Message édité par nafawana le 15-02-2018 à 14:40:12
mood
Publicité
Posté le 14-02-2018 à 16:34:52  profilanswer
 

n°2311172
gilou
Modérateur
Modzilla
Posté le 15-02-2018 à 23:32:18  profilanswer
 

Comme ça fait un bon exercice de XSLT, je vais y répondre dans ce langage:
 
A la base, en xslt c'est simple:

Code :
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">    
  3.    <xsl:mode on-no-match="shallow-copy"/>
  4.    <!-- On copie tout sauf les nœuds TRAJ qui n'ont pas la bonne valeur d'attribut -->
  5.    <xsl:template match="TRAJ[@tron ne 'TRONROUT0000000000193776']"/>
  6. </xsl:stylesheet>


 
Si tu veux exactement le même formatage en sortie qu'en entrée, comme tu n'as pas de modèle (dtd, rng...) associé, le parseur xsl ne peut savoir si ton formatage entre les TRAJ consiste en vrai nœuds texte significatifs pour le modèle ou pas. Il faut alors faire a la main le boulot pour ces nœuds texte.
Idem pour le formatage après la déclaration xml.
Ça donne une feuille de style un poil plus complexe, mais à peine:

Code :
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">    
  3.    <xsl:mode on-no-match="shallow-copy"/>
  4.    <xsl:param name="filter-value" select="'TRONROUT0000000000193776'"/>
  5.    <!-- Pour conserver le formatage après la déclaration -->
  6.    <xsl:template match="/">
  7.        <xsl:text>&#10;</xsl:text>
  8.        <xsl:copy>
  9.            <xsl:apply-templates select="*"/>
  10.        </xsl:copy>
  11.    </xsl:template>
  12.    <!-- copie des nœuds avec la bonne valeur d'attribut et des nœuds texte ad-hoc -->
  13.    <!-- ie ceux avant une ligne non effacée et le dernier au cas ou toutes les lignes avec TRAJ seraient effacées -->
  14.    <xsl:template match="TRAJS">
  15.        <xsl:copy>
  16.            <xsl:apply-templates select="TRAJ[@tron=$filter-value]
  17.                |text()[following-sibling::*[1][self::TRAJ[@tron=$filter-value]]]
  18.                |text()[position()=last()]"/>
  19.        </xsl:copy>
  20.    </xsl:template>
  21. </xsl:stylesheet>


Et tant que j'y étais, j'ai passé la valeur d'attribut filtrante comme un paramètre de la feuille de style (donc pouvant être positionné à l'appel) de valeur par défaut celle que tu donnes dans ton exemple.
 
Et sinon, pour ton programme perl, c'est parce que dans ton handler, tu cut les elements avec la mauvaise valeur d'attribut, mais tu ne dis pas ce que tu fais avec ceux qui ont la bonne: $TRAJ->print.
 
Ce qui donne en mettant tout ça au propre:

Code :
  1. #!/usr/bin/env perl
  2. use strict;
  3. use warnings;
  4. use autodie;
  5. use XML::Twig;
  6.  
  7. sub parse_xml {
  8.    my($infile, $outfile, $filter) = @_;
  9.    
  10.    open(my $fhout, '>', $outfile);
  11.    my $twig = XML::Twig->new(
  12.         twig_roots => { 'TRAJ' => 1 },
  13.         twig_print_outside_roots => $fhout,
  14.         twig_handlers => {'TRAJ' => sub{handler(@_, $filter);},},
  15.         PrettyPrint =>'indented',
  16.     )->parsefile($infile);
  17. }
  18.  
  19. sub handler {
  20.    my ($twig, $TRAJ, $filter)= @_;
  21.    ($TRAJ->att('tron') ne $filter)?$TRAJ->cut:$TRAJ->print;
  22. }
  23.  
  24. parse_xml('test.xml', 'traj_mini.xml', 'TRONROUT0000000000193776');


En sortie, c'est identique a ce que donnent mes 5 lignes de xsl du début de mon post.
 
A+,


Message édité par gilou le 16-02-2018 à 14:03:54

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2311207
nafawana
apprentie
Posté le 16-02-2018 à 23:38:09  profilanswer
 

Bonjour Gilou et merci!
 
 :pt1cable: effectivement il ne manquait pas grand chose même avec un code pas très propre!
 
Alors en réalité, il me faut filtrer une liste d'attributs issue d'un fichier texte, par exemple :

Code :
  1. TRONROUT0000000000193776
  2. TRONROUT0000000000195361_0


 
J'avais pensé utiliser la fonction index sur une longue chaine concaténée... et puis j'ai choisi de tester un hash couplé à la fonction exists, une première pour moi! Pas déçue, ça fonctionne bien! :bounce:  
J'ai adapté le fichier d'entrée:

Code :
  1. TRONROUT0000000000193776:mini
  2. TRONROUT0000000000195361_0:mini


 
Et voici le code de Gilou que j'ai adapté :

Code :
  1. #!/usr/bin/env perl
  2.     use strict;
  3.     use warnings;
  4.     use autodie;
  5.     use XML::Twig;
  6.    
  7.    my $FichierTXT = "ListTron.txt";
  8. open( my $TXT, '<', $FichierTXT )
  9. or die "Ouverture impossible de $FichierTXT\n$!";
  10. my %ListTron;
  11. while (<$TXT> ) {
  12.  chomp $_;
  13.  (my $link,my $zone) = split /:/, $_;
  14.  $ListTron{$link} = $zone;
  15. }
  16.  
  17.     sub parse_xml {
  18.         my($infile, $outfile, %ListTron) = @_;
  19.        
  20.         open(my $fhout, '>', $outfile);
  21.         my $twig = XML::Twig->new(
  22.             twig_roots => { 'TRAJ' => 1 },
  23.             twig_print_outside_roots => $fhout,
  24.             twig_handlers => {'TRAJ' => sub{handler(@_, %ListTron);},},
  25.             PrettyPrint =>'indented',
  26.         )->parsefile($infile);
  27.     }
  28.    
  29.     sub handler {
  30.         my ($twig, $TRAJ, %ListTron)= @_;
  31.        
  32.         my $tron = $TRAJ->att('tron'); 
  33.         if (exists ($ListTron{$tron})){$TRAJ->print;}
  34.         else{$TRAJ->cut;}
  35.     }
  36.    
  37.     parse_xml('test.xml', 'traj_mini.xml', %ListTron);


 
Point de détail : mon fichier de sortie comprend des lignes vides, est-ce qu'on peut les retirer?

Code :
  1. <INSTANTS>
  2.         <INST nbVeh="0" val="1.00">
  3.             <CREATIONS/>
  4.             <TRAJS/>
  5.             <STREAMS/>
  6.             <SGTS/>
  7.         </INST>
  8.         <INST nbVeh="1" val="2.00">
  9.             <CREATIONS/>
  10.             <TRAJS>
  11.                
  12.   <TRAJ abs="650804.90" acc="-1.00" dst="14.41" id="0" ord="6861842.70" tron="TRONROUT0000000000193776" type="VL" vit="13.00" voie="3" z="0.00"/>
  13.             </TRAJS>
  14.         </INST>
  15.         <INST nbVeh="3" val="3.00">
  16.             <CREATIONS/>
  17.             <TRAJS>
  18.                
  19.   <TRAJ abs="650804.90" acc="-1.00" dst="14.41" id="0" ord="6861842.70" tron="TRONROUT0000000000193776" type="VL" vit="13.00" voie="3" z="0.00"/>
  20.                
  21.                
  22.   <TRAJ abs="651309.38" acc="0.50" dst="36.52" id="6" ord="6861503.32" tron="TRONROUT0000000000195361_0" type="VL" vit="10.80" voie="1" z="0.00"/>
  23.             </TRAJS>
  24.         </INST>
  25.     </INSTANTS>


Message édité par nafawana le 16-02-2018 à 23:41:29
n°2311216
gilou
Modérateur
Modzilla
Posté le 17-02-2018 à 16:33:52  profilanswer
 

Dans ce cas la on peut faire bien plus simple:
 

Code :
  1. #!/usr/bin/env perl
  2. use strict;
  3. use warnings;
  4. use autodie;
  5. use XML::Twig;
  6.  
  7. sub parse_xml {
  8.    my($infile, $outfile, @filter) = @_;
  9.    
  10.    my $twig = XML::Twig->new(
  11.         twig_handlers => {'TRAJ' => sub{handler(@_, @filter);},},
  12.         PrettyPrint => 'indented',
  13.    )->parsefile($infile);
  14.    open(my $fhout, '>', $outfile);
  15.    $twig->print($fhout);
  16. }
  17.  
  18. sub handler {
  19.    my ($twig, $TRAJ, @filter)= @_;
  20.    my $value = $TRAJ->att('tron');
  21.    $TRAJ->cut unless (grep(/^$value$/, @filter));
  22. }
  23.  
  24. parse_xml('nafawana.xml', 'awanafan.xml', 'TRONROUT0000000000193776', 'TRONROUT0000000000195361_0');


Et je te laisse décider de la meilleure manière de passer ta liste à la fonction qui dorénavant accepte une liste en dernier argument.
 
Les lignes vides, c'est parce que tu avais déclaré TRAJ en root + twig_print_outside_roots.  
twig_print_outside_roots fait qu'il copie jusqu'a une balise TRAJ, saut de ligne inclus, avant d'appeler le handler.
Comme tu veux la même racine, on laisse tomber la déclaration de TRAJ en racine. Un va utiliser twig pour construire un nouvel arbre, sans les éléments TRAJ avec un attribut a une mauvaise valeur (donc plus de print dans le handler) et on imprime tout l'arbre construit, ce qui n'a aucune raison de générer des lignes vides.
 
A+,


Message édité par gilou le 17-02-2018 à 16:46:26

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Perl

  supprimer certaines balises d'un fichier xml

 

Sujets relatifs
[MySQL] Supprimer toutes les contraintes d'une tableAccès fichier local dans une web extension
Cherche personne pour décrypter fichierCréer fiche magasin à partir d'un fichier csv
Extraire certaines parties PDF d'un dossier vers ExcelÉcrire dans un fichier qui est en cours de lecture
Re cherche aide HTML pour corriger un fichier[VBA] Lecture fichier texte
Mise en forme Format CSV "*.cxr"[PERL] remplacer un mot dans un fichier
Plus de sujets relatifs à : supprimer certaines balises d'un fichier xml


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR