Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

XML::Parser Style=>Subs and undefined subroutines

by rkg (Hermit)
on Oct 01, 2003 at 01:16 UTC ( [id://295488]=perlquestion: print w/replies, xml ) Need Help??

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

Hi -- I am new to XML::Parser.

Question: what the heck does XML::Parser Style=>'Subs' do the function namespace?

It appears the  Subs sets something or other that lets you choose not to define any sub tag {} or  sub tag_{}. That's sort of convenient and cool.

But in the code below, why doesn't perl die on the "subroutine that does not exist" call? It seems Very Dangerous if XML::Parser turns off checking for missing subs. Any way to ask XML::Parser to maintain customary perl behavior -- eg calling a non-existent sub throws a fatal error?

Befuddled --

rkg

use strict; use XML::Parser; my $p1 = new XML::Parser(Style => 'Subs'); $p1->parse('<foo id="me">Hello World</foo>'); sub foo { my ($expat, $tag, %a) = @_; print "entering foo\n"; &i_am_a_subroutine_that_does_not_exist(); } sub foo_ { my ($expat, $tag, %a) = @_; print "leaving foo\n"; }

Replies are listed 'Best First'.
Re: XML::Parser Style=>Subs and undefined subroutines
by mirod (Canon) on Oct 01, 2003 at 07:11 UTC
    I am new to XML::Parser.

    May I suggest that you stay this way? ;--)

    Seriously, XML::Parser is well on its way to deprecation, so you should really try other options: XML::LibXML, XML::Twig or a SAX-based module. XMl;;LibXML will be faster, XML::Twig more convenient, and SAX is a pain but at least it is a standard.

      Wow.

      I am blown away by the power and ease-of-learning of XML::Twig.

      I jumped in without studying the docs carefully... and it seemed whenever I needed something ("Wouldn't it be great to call 'parent' here to get the parent?", and "Wouldn't it be great if 'att' generalized to 'atts', to give me all of them?" and "Wouldn't it be nice if 'first_child' generalized to 'children', to get all the kids?") and lo and behold they were all right there, with the API I'd expect.

      High praise for XML::Twig, and thanks, Mirod.

      (Likely this is a RTFM question, but how hard is it to get Twig to validate as well as parse...?)

      rkg

        First, thanks for the comments :--) You can also have a look at the tutorial, which seems to be the easiest way to grok the module for most people, as the POD is really more of a reference, at 2500 lines.

        how hard is it to get Twig to validate as well as parse?

        Rather hard actually. I could add (yet another!) option to use XML::Checker instead of XML::Parser, but I am not sure I trust it completely. So the easiest way is probably to install libxml2 and to use xmllint --valid on the output file.

      sorry, but what's wrong in using it like this...

      $xs = new XML::Parser; die ("Can't find file: $completePathFile $!") unless -f($completePat +hFile); $xs->setHandlers( Start => \&openElem, End => \&closElem, Char => \&heresTheData, Default => \&forgetit ); $xs->parsefile($completePathFile); ##now, parses and logic sub openElem{ } sub closElem{ } sub heresTheData{ } sub forgetit{ }
      You have to activate a flipflop variable when you open the desired tag. And deactivate it when this tag closes.

      In between, you are able to process the data that is received. Or waiting for other(s) flipflop(s) before processing the incoming data. You could leave it like this, and the file is going to parse perfectly ('though without any profit :).

      For me, this module is a great masterpiece. But I only know this one, because it is the one more easyly found at any WWW site.

        Nothing wrong here, there are just easier ways to code most XML processing than this.

        BTW you don't have to use a flipflop variable, you can just call current_element on the parser object to get the element in which you are (and context will give you the stack of open elements), man XML::Expat::Parser is an oft-overlooked resource that will give you the list of methods you can use on the parser object.

        But really, try using XML::LibXML or XML::Twig, have a look at the various comparisons at xmltwig.com (look at the bottom 3 articles), and you will see what a difference XPath can make.

Re: XML::Parser Style=>Subs and undefined subroutines
by rkg (Hermit) on Oct 01, 2003 at 01:27 UTC
    Ack! Even worse:
    use strict; use XML::Parser; my $p1 = new XML::Parser(Style => 'Subs'); $p1->parse('<foo id="me">Hello World</foo>'); sub foo { my ($expat, $tag, %a) = @_; print "foo before death\n"; die "i cannot die"; print "foo after death\n"; } sub foo_ { my ($expat, $tag, %a) = @_; print "i am alive and running foo_\n"; }
    On my system the output is
    foo before death i am alive and running foo_
    • Why isn't the die fatal?
    • Why did  foo_ get called?
    ???

      Check out XML::Parser::Style::Subs within the Start and End subs, the following is executed:

      my $sub = $expat->{Pkg} . "::$tag"; eval { &$sub($expat, $tag, @_) };

      All that happens is the dies are captured into $@ and the Start and/or End subs return undef.

      Update: Btw, for the behavior you seek, try this instead:

      package XML::Parser::Style::DieSubs; sub Start { no strict 'refs'; my $expat = shift; my $tag = shift; my $sub = $expat->{Pkg} . "::$tag"; $sub->($expat,$tag,@_) if defined &{$sub}; } sub End { no strict 'refs'; my $expat = shift; my $tag = shift; my $sub = $expat->{Pkg} . "::${tag}_"; $sub->($expat,$tag) if defined &{$sub}; } 1;

      It doesn't die if the sub doesn't exist, though. It does, however, allow your subroutines to die. If you wish for it to die if the subroutines don't exist, this is fairly trivial given the above code.

      Hope this helps.

      antirice    
      The first rule of Perl club is - use Perl
      The
      ith rule of Perl club is - follow rule i - 1 for i > 1

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://295488]
Approved by Thelonius
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (7)
As of 2024-04-23 12:40 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found