Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Perl et regexp sur du XML

4 réponses
Avatar
Timothée POISOT
bonjour a tous

je suis en train d'=E9crire un petit script qui me permette de garder
une trace d'observations d'animaux. Le principe est d'attribuer un
identifiant unique =E0 chaque observation (un num=E9ro qui s'incr=E9mente,
6 lettres du nom scientifique, 3 lettres du lieu d'observation) pour
pouvoir ensuite parcourir rapidement les infos.

Je m'appuie sur un fichier XML (nomm=E9 obs.xml) organis=E9 de mani=E8re
suivante :

<observations>
<obs>
<id>NUMERO D'IDENTIFICATION</id>
<lieu>LIEU</lieu>
etc
</obs>

<obs> etc etc
</observations>

j'ai utilis=E9

my $xml =3D new XML::Simple (KeyAttr=3D>'id');
my $base =3D $xml->XMLin('obs.xml');

pour le lire, et utiliser id comme cl=E9 de r=E9f=E9rence

Je suis confront=E9 =E0 un probl=E8me. Je souhaite pouvoir faire des
recherches par identifiant, en utilisant * comme joker. Il faut donc
ecrire une regexp, mais comment faire sur les donn=E9es XML?

Si vous avez des pistes, je suis assez preneur.

4 réponses

Avatar
Mark Clements
Timothée POISOT wrote:
bonjour a tous

je suis en train d'écrire un petit script qui me permette de garder
une trace d'observations d'animaux. Le principe est d'attribuer un
identifiant unique à chaque observation (un numéro qui s'incrémente,
6 lettres du nom scientifique, 3 lettres du lieu d'observation) pour
pouvoir ensuite parcourir rapidement les infos.

Je m'appuie sur un fichier XML (nommé obs.xml) organisé de manière
suivante :

<observations>
<obs>
<id>NUMERO D'IDENTIFICATION</id>
<lieu>LIEU</lieu>
etc
</obs>

<obs> etc etc
</observations>

j'ai utilisé

my $xml = new XML::Simple (KeyAttr=>'id');
my $base = $xml->XMLin('obs.xml');

pour le lire, et utiliser id comme clé de référence

Je suis confronté à un problème. Je souhaite pouvoir faire des
recherches par identifiant, en utilisant * comme joker. Il faut donc
ecrire une regexp, mais comment faire sur les données XML?

Si vous avez des pistes, je suis assez preneur.

Je pense qu'il faut utiliser XML::Path pour faire ça. Malheureusement,

il ne marche pas avec XML::Simple.

:~/Dev/perl$ cat xpath.pl
use strict;
use warnings;

use XML::XPath;
use XML::XPath::XMLParser;

my $xp = XML::XPath->new(filename => 'xpath.xml');

my $nodeset = $xp->find(q(/observations/obs[starts-with(id,'2')])); #
find all paragraphs

foreach my $node ($nodeset->get_nodelist) {
print "FOUNDnn",
XML::XPath::XMLParser::as_string($node), "nn";
}
:~/Dev/perl$ cat xpath.xml
<?xml version="1.0"?>
<observations>
<obs>
<id>1234</id>
<lieu>London</lieu>
</obs>
<obs>
<id>2234</id>
<lieu>Paris</lieu>
</obs>
</observations>
:~/Dev/perl$ perl xpath.pl
FOUND

<obs>
<id>2234</id>
<lieu>Paris</lieu>
</obs>

:~/Dev/perl$

On peut trouver du doc pour xpath à

http://www.w3schools.com/xpath/xpath_functions.asp

Mark

Avatar
Timothée POISOT
Merci pour la réponse. J'ai finalement trouvé comment faire pour
utiliser une regexp, ce qui dans mon cas est beaucoup plus léger à
écrire.


Timothée POISOT wrote:
bonjour a tous

je suis en train d'écrire un petit script qui me permette de garder
une trace d'observations d'animaux. Le principe est d'attribuer un
identifiant unique à chaque observation (un numéro qui s'incrémen te,
6 lettres du nom scientifique, 3 lettres du lieu d'observation) pour
pouvoir ensuite parcourir rapidement les infos.

Je m'appuie sur un fichier XML (nommé obs.xml) organisé de manière
suivante :

<observations>
<obs>
<id>NUMERO D'IDENTIFICATION</id>
<lieu>LIEU</lieu>
etc
</obs>

<obs> etc etc
</observations>

j'ai utilisé

my $xml = new XML::Simple (KeyAttr=>'id');
my $base = $xml->XMLin('obs.xml');

pour le lire, et utiliser id comme clé de référence

Je suis confronté à un problème. Je souhaite pouvoir faire des
recherches par identifiant, en utilisant * comme joker. Il faut donc
ecrire une regexp, mais comment faire sur les données XML?

Si vous avez des pistes, je suis assez preneur.

Je pense qu'il faut utiliser XML::Path pour faire ça. Malheureusement,

il ne marche pas avec XML::Simple.

:~/Dev/perl$ cat xpath.pl
use strict;
use warnings;

use XML::XPath;
use XML::XPath::XMLParser;

my $xp = XML::XPath->new(filename => 'xpath.xml');

my $nodeset = $xp->find(q(/observations/obs[starts-with(id,'2')])); #
find all paragraphs

foreach my $node ($nodeset->get_nodelist) {
print "FOUNDnn",
XML::XPath::XMLParser::as_string($node), "nn";
}
:~/Dev/perl$ cat xpath.xml
<?xml version="1.0"?>
<observations>
<obs>
<id>1234</id>
<lieu>London</lieu>
</obs>
<obs>
<id>2234</id>
<lieu>Paris</lieu>
</obs>
</observations>
:~/Dev/perl$ perl xpath.pl
FOUND

<obs>
<id>2234</id>
<lieu>Paris</lieu>
</obs>

:~/Dev/perl$

On peut trouver du doc pour xpath à

http://www.w3schools.com/xpath/xpath_functions.asp

Mark



Avatar
Mark Clements
Timothée POISOT wrote:
Merci pour la réponse. J'ai finalement trouvé comment faire pour
utiliser une regexp, ce qui dans mon cas est beaucoup plus léger à
écrire.


D'accord. C'est pas la première fois que j'ai trouvée un solution trop
compliqué :) Qu'est-ce que vous avez fait, exactement?


Mark

Avatar
Timothée POISOT

Timothée POISOT wrote:
Merci pour la réponse. J'ai finalement trouvé comment faire pour
utiliser une regexp, ce qui dans mon cas est beaucoup plus léger à
écrire.


D'accord. C'est pas la première fois que j'ai trouvée un solution trop
compliqué :) Qu'est-ce que vous avez fait, exactement?


Mark


J'ai utilisé une solution peut-être moins élégante. Pour la
recherche par code d'accession, soit on utilise un joker *, soit on
n'en utilise pas

if (defined param('accession'))
{
my $accession = param('accession');
if ($accession =~ /*/g)
{
$accession =~ s|*|(.+)|g; #construction du motif d'expression
régulière
print b('Recherche partielle sur ',$accession);
foreach my $obs (keys %{$base->{obs}}) #ici ma structure XML
{
if ($obs =~ m/$accession/g) { affiche_resultat($obs) }
#affiche_resultat est une fonction qui lit le fichier XML et renvoie
les résultats
}
} else {
affiche_resultat($accession);
}
}

Ca tourne bien, et vu que le fichier XML ne va pas contenir 10000
enregistrements (un bon maximum de 2000 amha) ca va me suffire.