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

I beg the indulgence of the Monks. I posted this last week under the heading of XML::Twig->parse() error under CGI and I am resubmitting this issue under the above heading to provide some additional data, and to see if we can have another look at this issue. As mirod has pointed out, XML::Twig is not involved with the problem that I am having except as a messenger of the bad news.

The Situation:

I have written a module that reads in log files (which are in XML) and parses them for various conditions to provide some reporting on my EAI engine (all Perl, all the time). The package uses mirod's XML::Twig to set up handlers for different conditions to report on, and I use it to create a web page that our users can view to see errors and successes, and to post-process the results.
After I developed the module I tested it with a script and everything works just fine. When I call the same package from a CGI program I get an error from XML::Expat

The Problem:

Here is the error message that I am getting from XML::Expat:

Can't use string ('<myXMLString><myElement name="foo"-') as a symbol ref while "strict refs" in use at .../perl5/site_perl/5.6.0/sun4-solaris-thread/XML/Parser/Expat.pm line 456.
If you look at the code at that point, you will see the following:
sub parse { my $self = shift; my $arg = shift; croak "Parse already in progress (Expat)" if $self->{_State_}; $self->{_State_} = 1; my $parser = $self->{Parser}; my $ioref; my $result = 0; if (defined $arg) { if (ref($arg) and UNIVERSAL::isa($arg, 'IO::Handle')) { $ioref = $arg; } elsif (tied($arg)) { my $class = ref($arg); no strict 'refs'; $ioref = $arg if defined &{"${class}::TIEHANDLE"}; } else { eval { $ioref = *{$arg}{IO}; # This is line 456 }; undef $@; } }
So the offending line is where "$ioref = *{$arg}{IO};". In this case, $arg happens to be my XML string, which is the correct thing for it to be. If you push the scripty version of this though the debugger, all values appear correct, and the globbing works fine under use strict.

My thoughts:


If anyone else has any ideas I would appreciate it. Thanks so much to those who have already made suggestions.


Brian - a.k.a. DrSax

Edited 2001-05-29 by Ovid

Replies are listed 'Best First'.
Re: XML::Expat - error from browser
by Anonymous Monk on May 29, 2001 at 20:58 UTC
    If you look closely at the surrounding code, you will see that it is an "if all else fails" condition. Your XML-String is not supposed to go to this code. Rather it should go to line 452 where it only arrives if it is tied to IO::Scalar (I think). I had the same problem before. In my case it was the calling code, which "untied" the string after the first toplevel node was processed. Effectively you could only process XML-Files which had a surrounding <xml>...</xml> structure, which is of course absurd for logfiles.
      I found what the issue here is after further consideration. The parse() method is meant to handle both parsing files and strings. If you look at the code that follows that which I included, it tests $ioref to see if there is some kind of filehandle. The line in question (456) is the final attempt to glob a file. The reason that I was seeing it was due to CGI::Carp considering that a fatal error (which the author of Expat.pm doesn't at all). I had to remove the CGI::Carp from the script and handle all my errors myself in an eval{};.
      Thanks to everyone who has helped.
      BTW, Anonymous Monk, what the heck is absurd about log files being in XML? Works great for me! I can post-process the log file and allow error to be fixed in the browser.
      Brian - a.k.a. DrSax
        Everyone is good:-) There was only me. (All Anonymous posts (before this) belong to me).
        Sorry about the misunderstanding. *If* you could use *only one* node in a file, *then* it would be absurd to use *that* XML-Implementation for logfiles. I hope that comes across as intended.
      I'm not sure that this is an "if all else fails" condition. From what I can see in the calling code (XML::Twig::parse -> XML::Parser::parse -> XML::Expat::parse) the other conditions are there to handle more specialized cases. The first condition handles the case where a filehandle has been passed in as the argument, the second handles a Tied Handle, and the third is there to handle a simple scalar which contains the string to be parsed. Apologies to Larry and Clark if I have misunderstood their code...
      If you read what I wrote closely you will see that this code works fine from the command line. It is in the browser that this error occurs.
        I'm not sure it's commandline vs CGI. I think it's testcase (with 1 node) vs the real thing (with many nodes) in the string.
        The 3rd case handles an open HALLO handle.