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

Hi PerlMonks:

I am using XML::Twig for my XML parsing needs.
I would like to know whether there is a way to catch any error's that is generated in this process.
Say Something like 'file doesn't exist' or 'no such attribute' or 'no such XML tag' or if there is any issues with the XML file.....

I want to stop the execution of this function if something happens. Code
my $Tree = new XML::Twig ( TwigHandlers => { book => sub{ $_ -> set_att( name => $newname); } } ); $Tree -> parsefile( "$BooksFile");
Any input is much appreciated! Thanks.

Replies are listed 'Best First'.
Re: XML::Twig error handling
by marto (Cardinal) on Sep 19, 2005 at 23:00 UTC
    Hi,

    Im about to go to bed but from memory have a look at safe_parsefile and safe_parse from the documentation.

    Hope this helps point you in the right direction.

    Martin
      Hi thanks for pointing me to the documentation!
      I used the safe_parsefile function. Even then the program dies after executing that call. It is not moving forward to the next line where I check the error.
        safe_parsefile is works fine if there is no specified file or directory.
        $tree -> safe_parsefile('c:/temp.xml'); warn $@ if $@;
        Is there a way to handle to the 'no such attribute' or 'no such tag' errors in the TWIG HANDLER?
Re: XML::Twig error handling
by Skeeve (Parson) on Sep 20, 2005 at 04:55 UTC
    Have you tried putting the code into an eval?

    from perldoc -f eval:

           eval EXPR
           eval BLOCK
                   [...]
    
                   In the second form, the code within the BLOCK is parsed only
                   once--at the same time the code surrounding the eval itself was
                   parsed--and executed within the context of the current Perl
                   program.  This form is typically used to trap exceptions more
                   efficiently than the first (see below), while also providing
                   the benefit of checking the code within BLOCK at compile time.
    
                   [...]
    
                   In both forms, the value returned is the value of the last
                   expression evaluated inside the mini-program; a return state-
                   ment may be also used, just as with subroutines.  The expres-
                   sion providing the return value is evaluated in void, scalar,
                   or list context, depending on the context of the eval itself.
                   See "wantarray" for more on how the evaluation context can be
                   determined.
    
                   If there is a syntax error or runtime error, or a "die" state-
                   ment is executed, an undefined value is returned by "eval", and
                   $@ is set to the error message.  If there was no error, $@ is
                   guaranteed to be a null string.  Beware that using "eval" nei-
                   ther silences perl from printing warnings to STDERR, nor does
                   it stuff the text of warning messages into $@.  To do either of
                   those, you have to use the $SIG{__WARN__} facility, or turn off
                   warnings inside the BLOCK or EXPR using "no warnings 'all'".
                   See "warn", perlvar, warnings and perllexwarn.
    
                   Note that, because "eval" traps otherwise-fatal errors, it is
                   useful for determining whether a particular feature (such as
                   "socket" or "symlink") is implemented.  It is also Perl's
                   exception trapping mechanism, where the die operator is used to
                   raise exceptions.
    </pr>
    
    

    $\=~s;s*.*;q^|D9JYJ^^qq^\//\\\///^;ex;print
Re: XML::Twig error handling
by mirod (Canon) on Sep 20, 2005 at 05:43 UTC

    I am not quite sure I understand the behaviour you are looking for. Could you provide an example of XML and what you would like your code to do with it?

    From your post, 'no such attribute' or 'no such XML tag' do not prevent the XML from being well-formed: they would cause the XML not to be valid (against a DTD), but expat is a non-validating parser. So the parser cannot report that kind of error. If the XML is not well-formed, then in any case the parser will stop at the first error. This behaviour is required by the XML spec (fatal error).

      Mirod, Here is an example.
      In the following example I am checking for a tag named 'Filter' and inside the sub I am trying to read 'Name' attribute of the filter tag. What I need is a way to warn the user that the 'Filter' tag that he/she is looking for is not available in the XML provided.... and

      In case the Filter tag is available but not the 'Name' attribute then I need to warn the user about this!
      my $Tree = new XML::Twig ( TwigHandlers => { Filter => sub { my ( $filterTwig, $filter ) = @_; my $filterName = $filter -> att( 'Name' ); $filter -> set_att( Name => "$uniqueFilter" ); } } ); $Tree->safe_parsefile("c:/check.xml"); warn $@ if $@;
      XML
        If I understand correctly (which I'm sure I don't fully), why not set some flag in your handler if the filter name your looking for exists (or save the filter names in a hash?), and then warn or die after the parse if the filter name wasn't there? Or you could warn or die inside the Filter handler if the Name you're looking for isn't there.

        Checking (and warning) that the attribute is missing is easy: add unless( defined $filter->att( 'Name' )) { warn "missing 'Name' attribute\n"; } in the handler.

        To warn that Filter is missing, you will have to set a handler at the next higher level (Filters in this case), and check there that there is a Filter child for the element.

        Alternatively you could write the DTD (or RelaxNg schema) that your tool expects and validate the XML before processing it (using xmllint for example). This way you simplify the code for your tool and it becomes much easier to change the format you expect. Plus having to write the DTD/schema is usually a good thing, it helps getting a proper format.