Rob,
----- Original Message -----
From: "Rob Dixon" <[EMAIL PROTECTED]>
To: "Perl List" <beginners@perl.org>
Cc: "Mike Blezien" <[EMAIL PROTECTED]>
Sent: Saturday, July 21, 2007 12:12 PM
Subject: Re: Parsing large XML file - Revisited
Mike Blezien wrote:
Rob Dixon wrote:
Mike Blezien wrote:
[snip]
we've run a few test and everything seems to be working as expected,
but got one little problem I haven't been able to figure out, we keep
getting this error (code snipt below)
----
Can't call method "first_child_text" on an undefined value
at .. /sample.cgi line 56 which is this line "my $tracknums =
$tracks->first_child_text('number_of_tracks');
----
a value for the "$tracknums" is returned and all other values are presented
after it parses the XML file. Haven't been able to figure out why I keep
getting this error??
############################################################################
my $twig = new XML::Twig(twig_handlers => { product => \&get_products });
$twig->parsefile("$xmlfile");
$twig->purge();
############################################################################
sub get_products {
my($t,$elt) = @_;
my($track_title,$trackno,$setno,$soundtype,$codec,$file);
# process each product loop.
my $article_number = $elt->first_child_text('article_number');
my $dist_number = $elt->first_child_text('distributor_number');
my $dist_name = $elt->first_child_text('distributor_name');
my $artist = $elt->first_child_text('artist');
my $ean_upc = $elt->first_child_text('ean_upc');
my $set_total = $elt->first_child_text('set_total');
my $tracks = $elt->first_child('tracks');
# LINE 56 here
my $tracknums = $tracks->first_child_text('number_of_tracks');
return unless $tracks;
for my $track ($tracks->children('track'))
{
$track_title = $track->first_child_text('title');
$trackno = $track->first_child_text('trackno');
$setno = $track->first_child_text('setno');
for my $sound ($track->children('sound'))
{
$soundtype = $sound->first_child_text('sound_type');
$codec = $sound->first_child_text('codec');
$file = $sound->first_child_text('file');~;
}
} # close for $track loop
# free up memory
$t->purge();
}
Hello Mike
First of all, your call
$twig->parsefile("$xmlfile");
should properly be
$twig->parsefile($xmlfile);
as there is no point in forcing Perl to interpolate a string when the result
is simply the string itself.
Your code works fine on the sample 000001.xml file that you posted. What must
be happening is that there is a product in your live data that has no <tracks>
element. The line
return unless $tracks;
is meant to protect against this, but you have use the value of $tracks before
the check. If you change your code to:
my $tracks = $elt->first_child('tracks');
return unless $tracks;
my $numtracks = $tracks->first_child_text('number_of_tracks');
for my $track ($tracks->children('track')) {
:
}
then your warning should go away, although you may want to do more than just
ignore any products without a <tracks> tag.
An alternative method, which checks the actual number of tracks instead of
relying on the accuracy of the <number_of_tracks> value is to put the <track>
elements into an array and measure its size before iterating over it:
my $tracks = $elt->first_child('tracks');
return unless $tracks;
my @tracks = $tracks->children('track');
my $numtracks = @tracks;
for my $track (@tracks) {
:
}
Which of these techniques you choose is up to you.
That's exactly what the problem was, some of the XML files do not have the
<tracks> elements, which I wasn't aware of till just now. After making some code
changes, the error has gone away. :)
Again, thank you for your very useful help and information. Save me alot of
head-scratching!
Mike
--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/