Klaus
2010-04-27 19:29:07 UTC
Bonjour,
je viens de publier le module XML::Reader, version 0.34:
http://search.cpan.org/~keichner/XML-Reader-0.34/lib/XML/Reader_fr.pod
Pour expliquer le fonctionnement du module XML::Reader, j'ai écrit un
programme
de "démonstration" qui extrait (sans consommer beaucoup de mémoire)
des éléments XML
(par exemple extractions des éléments '/.../a').
Un document XML entier est souvent très gros (plusieurs giga octets).
Par contre, une seule sous-structure XML
(l'unité de traitement XML) est souvent assez petit (quelques kilo
octets en général). Le programme de "démonstration" ci-dessous traite
des sous-structures XML, une après l'autre.
La consommation mémoire est limité à une sous-structure à la fois.
Ensuite, pour traiter une telle sous-structure,
on peut utiliser des expressions régulières (ou même des modules XML
de votre choix, comme par exemple XML::Simple).
Les modules XML classiques (comme par exemple XML::Parser) sont
souvent piloté par les événements (ils utilisent des fonctions
"callback"). XML::Reader, par contre, n'utilise pas les événements.
Avec XML::Reader, on travaille avec sa propre boucle (..."while ($rdr-
propositions !
Voici mon programme de "démonstration":
use strict;
use warnings;
use XML::Reader 0.34;
use LWP::Simple;
use XML::Simple;
use Data::Dumper;
my $addr = 'http://www.w3.org/TR/xhtml1';
print "reading $addr...\n";
my $content = get $addr
or die "Error-0010: Can't get address '$addr'";
print "\n";
{
my $rdr = XML::Reader->newhd(\$content,
{ filter => 5 },
{ root => '/html/body/dl/dt', branch => '*' },
) or die "Error-0030: Can't X::R->new() because $!";
my $i;
while ($rdr->iterate) { $i++;
my $xml = $rdr->rval;
printf "<dt1> %3d. %s\n", $i, $xml;
}
print "\n";
}
{
my $rdr = XML::Reader->newhd(\$content,
{ filter => 5 },
{ root => '/html/body/dl/dt', branch => '*' },
) or die "Error-0020: Can't X::R->new() because $!";
my $i;
while ($rdr->iterate) { $i++;
my $xml = $rdr->rval;
my $ref = XMLin($xml);
my $dmp = Dumper($ref);
$dmp =~ s{\s}''xmsg;
$dmp =~ s{\$VAR1=}''xms;
printf "<dt2> %3d. %s\n", $i, $dmp;
}
print "\n";
}
{
my $rdr = XML::Reader->newhd(\$content,
{ filter => 5 },
{ root => '//a', branch => ['/', '/@href'] },
) or die "Error-0040: Can't X::R->new() because $!";
my $i;
while ($rdr->iterate) {
my ($text, $href) = $rdr->rval;
next unless defined $href;
my $stem = $rdr->rstem;
$i++;
for ($text, $href) {
$_ = '' unless defined $_;
}
printf "<a> %3d. %-35s: %-18.18s href=%s\n",
$i, $stem, $text, $href;
}
print "\n";
}
{
my $rdr = XML::Reader->newhd(\$content,
{ filter => 5 },
{ root => '//img',
branch => ['/@src', '/@height', '/@width'] },
) or die "Error-0040: Can't X::R->new() because $!";
my $i;
while ($rdr->iterate) {
my ($src, $height, $width) = $rdr->rval;
$i++;
for ($src, $height, $width) {
$_ = '' unless defined $_;
}
printf "<img> %3d. src=%-40s h=%-4s w=%s\n",
$i, $src, $height, $width;
}
print "\n";
}
...et voici une partie du résultat:
reading http://www.w3.org/TR/xhtml1...
[...]
<dt1> 20. <dt><code class='tag'>a</code></dt>
<dt1> 21. <dt><code class='tag'>pre</code></dt>
<dt1> 22. <dt><code class='tag'>button</code></dt>
<dt1> 23. <dt><code class='tag'>label</code></dt>
[...]
<dt2> 20. {'code'=>{'content'=>'a','class'=>'tag'}};
<dt2> 21. {'code'=>{'content'=>'pre','class'=>'tag'}};
<dt2> 22. {'code'=>{'content'=>'button','class'=>'tag'}};
<dt2> 23. {'code'=>{'content'=>'label','class'=>'tag'}};
[...]
<a> 43. /html/body/div/ul/li/a : Acknowledgements
href=#acks
<a> 44. /html/body/div/ul/li/a : References
href=#refs
<a> 45. /html/body/div/ul/li/a : What is XHTML?
href=#xhtml
<a> 46. /html/body/div/ul/li/ul/li/a : What is HTML 4?
href=#html4
<a> 47. /html/body/div/ul/li/ul/li/a : What is XML?
href=#xml
[...]
<img> 1. src=http://www.w3.org/Icons/w3c_home h=48 w=72
<img> 2. src=Loading Image... h=32 w=88
je viens de publier le module XML::Reader, version 0.34:
http://search.cpan.org/~keichner/XML-Reader-0.34/lib/XML/Reader_fr.pod
Pour expliquer le fonctionnement du module XML::Reader, j'ai écrit un
programme
de "démonstration" qui extrait (sans consommer beaucoup de mémoire)
des éléments XML
(par exemple extractions des éléments '/.../a').
Un document XML entier est souvent très gros (plusieurs giga octets).
Par contre, une seule sous-structure XML
(l'unité de traitement XML) est souvent assez petit (quelques kilo
octets en général). Le programme de "démonstration" ci-dessous traite
des sous-structures XML, une après l'autre.
La consommation mémoire est limité à une sous-structure à la fois.
Ensuite, pour traiter une telle sous-structure,
on peut utiliser des expressions régulières (ou même des modules XML
de votre choix, comme par exemple XML::Simple).
Les modules XML classiques (comme par exemple XML::Parser) sont
souvent piloté par les événements (ils utilisent des fonctions
"callback"). XML::Reader, par contre, n'utilise pas les événements.
Avec XML::Reader, on travaille avec sa propre boucle (..."while ($rdr-
iterate)...") et on récupère les éléments XML par la fonction $rdr-
rval.
Je serais content de recevoir vos questions, commentaires etrval.
propositions !
Voici mon programme de "démonstration":
use strict;
use warnings;
use XML::Reader 0.34;
use LWP::Simple;
use XML::Simple;
use Data::Dumper;
my $addr = 'http://www.w3.org/TR/xhtml1';
print "reading $addr...\n";
my $content = get $addr
or die "Error-0010: Can't get address '$addr'";
print "\n";
{
my $rdr = XML::Reader->newhd(\$content,
{ filter => 5 },
{ root => '/html/body/dl/dt', branch => '*' },
) or die "Error-0030: Can't X::R->new() because $!";
my $i;
while ($rdr->iterate) { $i++;
my $xml = $rdr->rval;
printf "<dt1> %3d. %s\n", $i, $xml;
}
print "\n";
}
{
my $rdr = XML::Reader->newhd(\$content,
{ filter => 5 },
{ root => '/html/body/dl/dt', branch => '*' },
) or die "Error-0020: Can't X::R->new() because $!";
my $i;
while ($rdr->iterate) { $i++;
my $xml = $rdr->rval;
my $ref = XMLin($xml);
my $dmp = Dumper($ref);
$dmp =~ s{\s}''xmsg;
$dmp =~ s{\$VAR1=}''xms;
printf "<dt2> %3d. %s\n", $i, $dmp;
}
print "\n";
}
{
my $rdr = XML::Reader->newhd(\$content,
{ filter => 5 },
{ root => '//a', branch => ['/', '/@href'] },
) or die "Error-0040: Can't X::R->new() because $!";
my $i;
while ($rdr->iterate) {
my ($text, $href) = $rdr->rval;
next unless defined $href;
my $stem = $rdr->rstem;
$i++;
for ($text, $href) {
$_ = '' unless defined $_;
}
printf "<a> %3d. %-35s: %-18.18s href=%s\n",
$i, $stem, $text, $href;
}
print "\n";
}
{
my $rdr = XML::Reader->newhd(\$content,
{ filter => 5 },
{ root => '//img',
branch => ['/@src', '/@height', '/@width'] },
) or die "Error-0040: Can't X::R->new() because $!";
my $i;
while ($rdr->iterate) {
my ($src, $height, $width) = $rdr->rval;
$i++;
for ($src, $height, $width) {
$_ = '' unless defined $_;
}
printf "<img> %3d. src=%-40s h=%-4s w=%s\n",
$i, $src, $height, $width;
}
print "\n";
}
...et voici une partie du résultat:
reading http://www.w3.org/TR/xhtml1...
[...]
<dt1> 20. <dt><code class='tag'>a</code></dt>
<dt1> 21. <dt><code class='tag'>pre</code></dt>
<dt1> 22. <dt><code class='tag'>button</code></dt>
<dt1> 23. <dt><code class='tag'>label</code></dt>
[...]
<dt2> 20. {'code'=>{'content'=>'a','class'=>'tag'}};
<dt2> 21. {'code'=>{'content'=>'pre','class'=>'tag'}};
<dt2> 22. {'code'=>{'content'=>'button','class'=>'tag'}};
<dt2> 23. {'code'=>{'content'=>'label','class'=>'tag'}};
[...]
<a> 43. /html/body/div/ul/li/a : Acknowledgements
href=#acks
<a> 44. /html/body/div/ul/li/a : References
href=#refs
<a> 45. /html/body/div/ul/li/a : What is XHTML?
href=#xhtml
<a> 46. /html/body/div/ul/li/ul/li/a : What is HTML 4?
href=#html4
<a> 47. /html/body/div/ul/li/ul/li/a : What is XML?
href=#xml
[...]
<img> 1. src=http://www.w3.org/Icons/w3c_home h=48 w=72
<img> 2. src=Loading Image... h=32 w=88