perl et fichier XML

perl et fichier XML - Perl - Programmation

Marsh Posté le 19-02-2017 à 10:37:45    

Bonjour à tous,
 
j'ai un fichier xml à parti du quel je vais extraire quelques champs:  
 
j'ai fait le code suivant:

Code :
  1. use strict;
  2. use warnings;
  3. use XML::Simple;
  4. my $parser = XML::Simple->new( KeepRoot => 1 );
  5.  
  6.  
  7.            
  8. # Création du fichier résultat
  9. my $FichierResulat = '/result';
  10.  
  11.  
  12. open( my $FhResultat, '>', $FichierResulat )or die("Impossible d'ouvrir le fichier $FichierResulat\n$!" );
  13.  
  14.  
  15. my $doc = $parser->XMLin('/essai.xml');
  16.      
  17.  
  18. foreach my $words ( @{ $doc->{dict}->{word} } ) {
  19. my $word=  $words->{value};
  20.  
  21.        $word =~ s/^\s+|\s+$//g;
  22. if($word eq "استمارة" )
  23. {
  24. print {$FhResultat} "$word";
  25. print "ok";
  26. }
  27. else
  28. {print "not ok";}
  29. print {$FhResultat} "$word:\n";
  30.  
  31. foreach my $senses (@{ $words->{'sense'} }) {
  32. my $gloss= $senses->{def};
  33. print {$FhResultat} "$gloss\n";
  34. }
  35. }
  36.  
  37. }


 
voici un extrait de mon fichier xml :
<dict>
<word value="استمارة">
<sense>
<ids>1</ids>
<def>استمارة ورقة تتضمّن بيانات معيّنة خاصَّة بمن يقوم بملئها وتقدَّم عند الالتحاق بمدرسة أو وظيفة أو أي أغراض أخرى ملأ استمارة الشهادة الثانويَّة استمارة قبول استمارة خاصّة تقدَّم للالتحاق بمعهد </def>
</sense>
<sense>
<ids>2</ids>
<def>استمارة ورقة تتضمّن بيانات معيّنة خاصَّة بمن يقوم بملئها وتقدَّم عند الالتحاق بمدرسة أو وظيفة أو أي أغراض أخرى ملأ استمارة الشهادة الثانويَّة استمارة قبول استمارة خاصّة تقدَّم للالتحاق بمعهد </def>
</sense>
</word>
<word value="استوديو">
<sense>
<ids>1</ids>
<def> أُسْتُوديو إسْتُوديو ستوديو مكتب الرسَّام والنحّات أو المصوّر الفوتوغرافيّ أخذت صوري من الاستوديو </def>
</sense>
<sense>
<ids>2</ids>
<def> مكتب لدراسة فنّ من الفنون كالرقص والغناء والتمثيل تدرّب على الغناء في الاستوديو </def>
</sense>
</word>        
</dict>
 
 
J'ai rencontré le problème suivant:  
 

  • pourquoi si mon fichier xml contient seulement un seul élement dans <word> il m'affiche l'erreur suivante : Not an ARRAY reference at /home/lenovo


 
Merci d'avance..


Message édité par mouda le 19-02-2017 à 11:04:19
Reply

Marsh Posté le 19-02-2017 à 10:37:45   

Reply

Marsh Posté le 19-02-2017 à 14:52:32    

Parce que XML::Simple, quand il trouve parse un element, s'il a plusieurs fils, il fabrique un array (de hashes) mais s'il y a qu'un fils, il mets directement le hash.
 
Moi, je n'utilise pas XML::Simple, j'utilise XML::LibXML, qui est certes un peu plus compliqué, mais bien plus utilisable.
Un exemple pour t'inspirer, a adapter a tes besoins:

Code :
  1. #!/usr/bin/env perl
  2. use strict;
  3. use warnings;
  4. use autodie;
  5.  
  6. use XML::LibXML;
  7.  
  8. my $dom = XML::LibXML->load_xml(location => 'data-in.xml');
  9. my $FichierResulat = 'data-out.txt';
  10. open( my $FhResultat, '>:utf8', $FichierResulat );
  11.  
  12. foreach my $entry ($dom->findnodes('/dict/word')) {
  13.    my $word = $entry->getAttribute('value');
  14.    $word =~ s/^\s+|\s+$//g;
  15.    print $FhResultat "$word";
  16.    if ($word eq "استمارة" ) {
  17.     print $FhResultat " ok\n";
  18.    }
  19.    else {
  20.     print $FhResultat " not ok\n";
  21.    }
  22.    
  23.    foreach my $gloss ($entry->findnodes('sense/def/text()')) {
  24.     print $FhResultat $gloss->data, "\n";
  25.    }
  26. }
  27. close $FhResultat;


 
 
A+,


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

Marsh Posté le 19-02-2017 à 15:21:34    

Re-Bonjour,
Je vais voir donc avec libXml :)

Reply

Marsh Posté le 19-02-2017 à 15:58:31    

Noter aussi que ce genre de manip sur du xml pourrait se faire avec une feuille de style xslt:

Code :
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  3.  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  4.  exclude-result-prefixes="xs"
  5.  version="2.0">
  6.  
  7.  <xsl:output method="text"/>
  8.  
  9.  <xsl:template match="/">
  10.    <xsl:for-each select="dict/word">
  11.      <xsl:variable name="word" select="@value" as="xs:string"/>
  12.      <xsl:value-of select="normalize-space($word)"/>
  13.      <xsl:value-of select="if ($word = 'استمارة') then ' not Ok' else ' Ok'"/>
  14.      <xsl:text>&#xa;</xsl:text> <!-- new line -->
  15.      <xsl:for-each select="sense/def">
  16.        <xsl:value-of select="."/>
  17.        <xsl:text>&#xa;</xsl:text>
  18.      </xsl:for-each>
  19.    </xsl:for-each>
  20.  </xsl:template>
  21.  
  22. </xsl:stylesheet>


 
A+,


Message édité par gilou le 19-02-2017 à 16:03:24

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

Marsh Posté le 19-02-2017 à 19:28:17    

Bonsoir gilou,  
alors comment par exemple je peux extraire la définition ayant un sens particulier , j'ai fait ça :  

Code :
  1. foreach my $ids ($entry->findnodes('sense/ids/text()')) {
  2.   # print $FhResultat $gloss->data, "\n";
  3.  
  4. my $ind= $ids->data;
  5. $ind =~ s/^\s+|\s+$//g;
  6. $sens_indice =~ s/^\s+|\s+$//g;
  7.  
  8. if($ind eq $sens_indice )
  9. {#comment savoir la def convenable à ids= $sense_indice print $FhResultat $gloss->data, "\n";}
  10.    }
  11.    }
  12. }


par exemple dans cet extrait je veux savoir la <def> ayant un <sens> dont <ids> = 1  
voici l'extrait:
<dict>
<word value="استمارة">
<sense>
<ids>1</ids>
<def>استمارة ورقة تتضمّن بيانات معيّنة خاصَّة بمن يقوم بملئها وتقدَّم عند الالتحاق بمدرسة أو وظيفة أو أي أغراض أخرى ملأ استمارة الشهادة الثانويَّة استمارة قبول استمارة خاصّة تقدَّم للالتحاق بمعهد </def>
</sense>
<sense>
<ids>2</ids>
<def>غادر القطار المحطة</def>
</sense>
</word>      
</dict>

Reply

Marsh Posté le 19-02-2017 à 21:41:11    

J'ai pas testé, mais ca devrait ressembler a ceci:  
 
foreach my $sense ($entry->findnodes('sense')) {
    foreach my $id ($sense->findnodes('id')) {
        my $num = $id->textContent;
        if ($num eq "1" ) {
            my @def = $id->findnodes('following-sibling::def')
            print $FhResultat $def[1]->textContent, "\n";
        }
    }
}
 
A+,


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

Marsh Posté le 19-02-2017 à 21:58:53    

[quotemsg=2296624,6,19304]J'ai pas testé, mais ca devrait ressembler a ceci:  
 
foreach my $sense ($entry->findnodes('sense')) {
    foreach my $id ($sense->findnodes('id')) {
        my $num = $id->textContent;
        if ($num eq "1" ) {
            my @def = $id->findnodes('following-sibling::def')
            print $FhResultat $def[1]->textContent, "\n";
        }
    }
}
ça me donne cet erreur :Can't call method "textContent" on an undefined value  

Reply

Marsh Posté le 20-02-2017 à 01:07:20    

$sense->findnodes('ids')
 
A+,


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

Marsh Posté le 20-02-2017 à 11:15:43    

gilou a écrit :

$sense->findnodes('ids')
 
A+,


Merci gilou pour tous vos remarques, pour vos réponses et votre aide, sincèrement  j'ai beaucoup appris dans la programmation perl grâce à  vous, maintenant je suis même capable de programmer qqe programmes +- difficiles, bien sure je suis pas assez compétente en perl mais je souhaite la devenir un jour et c'est toujours cause de vos remarques et vos corrections... Merci beaucoup "le Roi" du perl  :jap:


Message édité par mouda le 20-02-2017 à 11:16:39
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed