Emanuel has asked for the wisdom of the Perl Monks concerning the following question:

Hello

I have two questions, and I hope someone can help me here, i'm quite stuck and haven't found anything yet in the previously asked questions (maybe I didn't dig deep enough though).

The outline: I'm creating an XML, send it somewhere and receive an answer back in XML. I then want to parse the returned XML to check if any error occured (it'd say so in the XML). So far so good, everything works fine until I want to parse the XML. I've taken the code snippets from the XML::Parser article which is posted here (sorry, can't remember the author), and everything worked fine when I had it in it's own script. I've now tried to get it into my main script, and the script breas with an error in XML::Parser : syntax error at line 1, column 0, byte 0 at /usr/local/lib/perl5/site_perl/5.6.1/i686-linux/XML/Parser.pm line 185 The XML it returns looks something like the Following (sorry, I can't include the whole XML here):
<Item> <Phone_no>123456789</Phone_no> <Content>Message Sent</Content> </Item> <Item> <Phone_no>12345</Phone_no> <Content>Error: Incorrect phone number</Content> </Item> </Packet>
the code i use to parse the XML is the following:
sub parse_return_xml { logger("DEBUG","Sub Parse Return XML"); my $message; my $i=0; my @phone; my @content; my @bad; my $xml = @_; logger("DEBUG","$xml"); logger("DEBUG","Creating XML::Parser Object"); my $parser = new XML::Parser(Handlers => { Start => \&start_tag, End => \&end_tag, Char => \&do_char }); $parser->parse($xml); sub start_tag { logger("DEBUG","start_tag"); my ($p, $elt, %atts) = @_; return unless $elt eq 'Content' || $elt eq 'Phone_no'; $atts{'_str'} = ''; $message = \%atts; } sub end_tag { logger("DEBUG","end_tag"); my ($p, $elt) = @_; format_message($message) if ($elt eq 'Content' || $elt + eq 'Phone_no') && $message; } sub do_char { logger("DEBUG","do_char"); my ($p, $str) = @_; $message->{'_str'} .= $str; } sub format_message { logger("DEBUG","Sub Format_message"); logger("DEBUG","\$i = $i"); my $atts = shift; logger("DEBUG",$atts->{'_str'}); if ($atts->{'_str'} =~ /err/i) { $bad[$i] = $phone[$i]; } else { $bad[$i] = 'holymoly'; } if ($atts->{'_str'} =~ /[0..9]/) { $phone[$i] = $atts->{'_str'}; } if ($atts->{'_str'} =~ /[a..zA..Z]/) { $content[$i] = $atts->{'_str'}; $i++; } } }
the script breaks after calling $parser->parse($xml)..

could the problem be that I declare Subs within a sub already, and therefore it is unable to call these subs?

any help here is greatly Appreciated, and I hope I gave enough information to this

Thanks in Advance

Emanuel emanuel@xconnect.ch

Replies are listed 'Best First'.
Re: XML::Parser and Subs in a sub
by Emanuel (Pilgrim) on Oct 03, 2001 at 06:47 UTC
    okay, I found my mistake after digging through the code again.
    my $xml = @_; <br>
    should read:
    my ($xml) = @_;<br>
    *slap*

    sorry for wasting your time, and thanks for the hints/tips towards this! Still got alot of worke to do to tidy up the code, think i was just blind not seeing this in the first place.

    thanks again :)
Re: XML::Parser and Subs in a sub
by mirod (Canon) on Oct 03, 2001 at 11:39 UTC

    Some remarks:

    • you might want to add an ErrorContext => 1 argument to the parser creation. This will output the line where the error occured and make it much easier to debug. In this case you would have seen that the parser wasn't parsing anything.
    • it looks like you have a pretty good idea of the format of the messages, then why don't you use a DTD to check them? You can then use XML::Checker::Parser instead of XML::Parser (it's a plug-in replacement, so all you have to do is use it when you create the parser object, everything else can stay the same. This would give you an extra level of confidence in your data. Just test the performances to make sure it's fast enough for your needs (I have no idea how fast it is).
      Here is a simple DTD that would work for the data you showed:
      <!ELEMENT Packet (Item+) > <!ELEMENT Item (Phone_no,Content) > <!ELEMENT Phone_no (#PCDATA) > <!ELEMENT Content (#PCDATA) >
Re: XML::Parser and Subs in a sub
by Fletch (Bishop) on Oct 03, 2001 at 06:22 UTC

    Perl doesn't do nested subs, so there's nothing to gain by embedding them inside parse_return_xml. In fact, it probably makes it harder to understand and maintain in the long run.

    As for the error, that's from expat itself saying that your XML isn't well formed. Try prepending an ?xml? declaration to your input (if it's not already there) and see if that fixes things.

Re: XML::Parser and Subs in a sub
by jerrygarciuh (Curate) on Oct 03, 2001 at 06:19 UTC
    Is there some compelling reason why you are looking to
    'roll your own' as opposed to calling the module from your script? If you had it working why break it?
    hth
    jg
    _____________________________________________________
    Ain't no time to hate! Barely time to wait! ~RH
      the way I had it working was by loading the xml from a file and do the parsing, so to say a simple test script to get the feel for xml::parser. that's why I then wanted to get it into my main script.
      i don't see why it works 'standalone' but doesn't(with almost the exact same code) inside my script

      emanuel
      emanuel@xconnect.ch