File Coverage

blib/lib/HTML/TableParser.pm
Criterion Covered Total %
statement 132 141 93.6
branch 52 74 70.2
condition 36 52 69.2
subroutine 13 13 100.0
pod 1 1 100.0
total 234 281 83.2


line stmt bran cond sub pod time code
1             package HTML::TableParser;
2              
3             # ABSTRACT: HTML::TableParser - Extract data from an HTML table
4              
5             require 5.8.1;
6 7     7   374325 use strict;
  7         49  
  7         158  
7 7     7   28 use warnings;
  7         7  
  7         202  
8              
9             our $VERSION = '0.43';
10              
11 7     7   39 use Carp ();
  7         16  
  7         153  
12 7     7   3012 use HTML::Parser;
  7         33501  
  7         197  
13              
14 7     7   2757 use HTML::TableParser::Table;
  7         17  
  7         11557  
15              
16             ## no critic ( ProhibitAccessOfPrivateData )
17              
18              
19             our @ISA = qw(HTML::Parser);
20              
21             # Preloaded methods go here.
22              
23             our %Attr = ( Trim => 0,
24             Decode => 1,
25             Chomp => 0,
26             MultiMatch => 0,
27             DecodeNBSP => 0,
28             );
29             our @Attr = keys %Attr;
30              
31             our $Verbose = 0;
32              
33             sub new
34             {
35 93     93 1 5720 my $class = shift;
36              
37 93         151 my $reqs = shift;
38              
39 93         374 my $self = $class->SUPER::new
40             (
41             api_version => 3,
42             unbroken_text => 1,
43             start_h => [ '_start', 'self, tagname, attr, line' ],
44             end_h => [ '_end', 'self, tagname, attr, line' ],
45             );
46              
47 93 50 33     5012 Carp::croak( __PACKAGE__, ": must specify a table request" )
48             unless defined $reqs and 'ARRAY' eq ref $reqs;
49              
50 93   100     238 my $attr = shift || {};
51              
52 93         217 my @notvalid = grep { ! exists $Attr{$_} } keys %$attr;
  51         153  
53 93 50       182 Carp::croak ( __PACKAGE__, ": Invalid attribute(s): '",
54             join(" ,'", @notvalid ), "'" )
55             if @notvalid;
56              
57 93         340 my %attr = ( %Attr, %$attr );
58              
59 93         245 $self->{reqs} = _tidy_reqs( $reqs, \%attr );
60              
61 93         352 $self->{Tables} = [ HTML::TableParser::Table->new() ];
62              
63             # by default we're not processing anything
64 93         213 $self->_process(0);
65              
66 93         231 $self;
67             }
68              
69              
70             our @ReqAttr = ( qw( cols colre id idre class obj start end
71             hdr row warn udata ),
72             keys %Attr );
73             our %ReqAttr = map { $_ => 1 } @ReqAttr;
74              
75             # convert table requests into something that HTML::TableParser::Table can
76             # handle
77             sub _tidy_reqs
78             {
79 93     93   166 my ( $reqs, $attr ) = @_;
80              
81 93         108 my @reqs;
82              
83 93         110 my $nreq = 0;
84 93         170 for my $req ( @$reqs )
85             {
86 95         127 my %req;
87              
88 95         129 $nreq++;
89              
90 95         189 my @notvalid = grep { ! exists $ReqAttr{$_} } keys %$req;
  493         757  
91 95 50       186 Carp::croak (__PACKAGE__, ": table request $nreq: invalid attribute(s): '",
92             join(" ,'", @notvalid ), "'" )
93             if @notvalid;
94              
95 95         120 my $req_id = 0;
96              
97              
98             # parse cols and id the same way
99 95         158 for my $what ( qw( cols id ) )
100             {
101 190         341 $req{$what} = [];
102              
103 190 100 66     514 if ( exists $req->{$what} && defined $req->{$what} )
104             {
105 78         99 my @reqs;
106              
107 78         131 my $ref = ref $req->{$what};
108              
109 78 100 100     295 if ( 'ARRAY' eq $ref )
    50 66        
110             {
111 34         41 @reqs = @{$req->{$what}};
  34         68  
112             }
113             elsif ( 'Regexp' eq $ref ||
114             'CODE' eq $ref ||
115             ! $ref )
116             {
117 44         88 @reqs = ( $req->{$what} );
118             }
119             else
120             {
121 0         0 Carp::croak( __PACKAGE__,
122             ": table request $nreq: $what must be a scalar, arrayref, or coderef" );
123             }
124              
125             # now, check that we have legal things in there
126 78         120 my %attr = ();
127              
128 78         122 for my $match ( @reqs )
129             {
130 81         110 my $ref = ref $match;
131 81 50 66     318 Carp::croak( __PACKAGE__,
      100        
      66        
132             ": table request $nreq: illegal $what `$match': must be a scalar, regexp, or coderef" )
133             unless defined $match && ! $ref || 'Regexp' eq $ref
134             || 'CODE' eq $ref ;
135              
136 81 100 100     283 if ( ! $ref && $match eq '-' )
137             {
138 1         2 %attr = ( exclude => 1 );
139 1         2 next;
140             }
141              
142 80 100 100     225 if ( ! $ref && $match eq '--' )
143             {
144 1         3 %attr = ( skip => 1 );
145 1         2 next;
146             }
147              
148 79 50 66     208 if ( ! $ref && $match eq '+' )
149             {
150 0         0 %attr = ();
151 0         0 next;
152             }
153              
154 79         101 push @{$req{$what}}, { %attr, match => $match };
  79         230  
155 79         121 %attr = ();
156 79         181 $req_id++;
157             }
158             }
159             }
160              
161             # colre is now obsolete, but keep backwards compatibility
162             # column regular expression match?
163 95 100       195 if ( defined $req->{colre} )
164             {
165 17         25 my $colre;
166              
167 17 50       44 if ( 'ARRAY' eq ref $req->{colre} )
    0          
168             {
169 17         29 $colre = $req->{colre};
170             }
171             elsif ( ! ref $req->{colre} )
172             {
173 0         0 $colre = [ $req->{colre} ];
174             }
175             else
176             {
177 0         0 Carp::croak( __PACKAGE__,
178             ": table request $nreq: colre must be a scalar or arrayref" );
179             }
180              
181 17         36 for my $re ( @$colre )
182             {
183 17         27 my $ref = ref $re;
184              
185 17 50 66     41 Carp::croak( __PACKAGE__, ": table request $nreq: colre must be a scalar" )
186             unless ! $ref or 'Regexp' eq $ref;
187 17 100       20 push @{$req{cols}}, { include => 1,
  17         151  
188             match => 'Regexp' eq $ref ? $re : qr/$re/ };
189 17         39 $req_id++;
190             }
191             }
192              
193              
194 95 50       177 Carp::croak( __PACKAGE__,
195             ": table request $nreq: must specify at least one id method" )
196             unless $req_id;
197              
198             $req{obj} = $req->{obj}
199 95 100       185 if exists $req->{obj};
200              
201             $req{class} = $req->{class}
202 95 100       170 if exists $req->{class};
203              
204 95         148 for my $method ( qw( start end hdr row warn new ) )
205             {
206 570 100 100     1696 if ( exists $req->{$method} && 'CODE' eq ref $req->{$method} )
    100 66        
    50          
207             {
208 310         480 $req{$method} = $req->{$method};
209             }
210              
211             elsif ( exists $req{obj} || exists $req{class})
212             {
213 78 100       113 my $thing = exists $req{obj} ? $req{obj} : $req{class};
214              
215 78 100       100 if ( exists $req->{$method} )
216             {
217 2 50       5 if ( defined $req->{$method} )
218             {
219             Carp::croak( __PACKAGE__,
220             ": table request $nreq: can't have object & non-scalar $method" )
221 0 0       0 if ref $req->{$method};
222              
223 0         0 my $call = $req->{$method};
224              
225             Carp::croak( __PACKAGE__,
226             ": table request $nreq: class doesn't have method $call" )
227 0 0 0     0 if ( exists $req->{obj} && ! $req->{obj}->can( $call ) )
      0        
228             || !UNIVERSAL::can( $thing, $call );
229             }
230              
231             # if $req->{$method} is undef, user must have explicitly
232             # set it so, which is a signal to NOT call that method.
233             }
234             else
235             {
236 76 100       221 $req{$method} = $method
237             if UNIVERSAL::can( $thing, $method );
238             }
239             }
240             elsif( exists $req->{$method} )
241             {
242 0         0 Carp::croak( __PACKAGE__, ": invalid callback for $method" );
243             }
244             }
245              
246             # last minute cleanups for things that don't fit in the above loop
247             Carp::croak( __PACKAGE__, ": must specify valid constructor for class $req->{class}" )
248 95 50 66     200 if exists $req{class} && ! exists $req{new};
249              
250              
251 95         143 $req{udata} = undef;
252 95 100       180 $req{udata} = exists $req->{udata} ? $req->{udata} : undef;
253              
254 95         192 $req{match} = 0;
255              
256 95         280 @req{@Attr} = @Attr{@Attr};
257              
258             $req{$_} = $attr->{$_}
259 95         169 foreach grep { defined $attr->{$_} } @Attr;
  475         859  
260              
261             $req{$_} = $req->{$_}
262 95         133 foreach grep { defined $req->{$_} } @Attr;
  475         691  
263              
264 95         202 push @reqs, \%req;
265             }
266              
267 93         191 \@reqs;
268             }
269              
270              
271             sub _process
272             {
273 337     337   505 my ($self, $state) = @_;
274              
275 337   100     812 my $ostate = $self->{process} || 0;
276              
277 337 100       542 if ( $state )
278             {
279 123         569 $self->report_tags( qw( table th td tr ) );
280 123         495 $self->handler( 'text' => '_text', 'self, text, line' );
281             }
282              
283             else
284             {
285 214         733 $self->report_tags( qw( table ) );
286 214         580 $self->handler( 'text' => '' );
287             }
288              
289 337         504 $self->{process} = $state;
290 337         844 $ostate;
291             }
292              
293              
294             our %trans = ( tr => 'row',
295             th => 'header',
296             td => 'column' );
297              
298             sub _start
299             {
300 53261     53261   79654 my $self = shift;
301 53261         58899 my $tagname = shift;
302              
303 53261 50       77121 print STDERR __PACKAGE__, "::start : $_[1] : $tagname \n"
304             if $HTML::TableParser::Verbose;
305              
306 53261 100       75562 if ( 'table' eq $tagname )
307             {
308 122         232 $self->_start_table( @_ );
309             }
310              
311             else
312             {
313 53139         74748 my $method = 'start_' . $trans{$tagname};
314              
315 53139         101068 $self->{Tables}[-1]->$method(@_);
316             }
317             }
318              
319              
320             sub _end
321             {
322 9954     9954   14610 my $self = shift;
323 9954         10744 my $tagname = shift;
324              
325 9954 50       14047 print STDERR __PACKAGE__, "::_end : $_[1]: $tagname \n"
326             if $HTML::TableParser::Verbose;
327              
328 9954 100       14103 if ( 'table' eq $tagname )
329             {
330 123         250 $self->_end_table( @_ );
331             }
332              
333             else
334             {
335 9831         13730 my $method = 'end_' . $trans{$tagname};
336              
337 9831         18719 $self->{Tables}[-1]->$method(@_);
338             }
339             }
340              
341              
342             sub _start_table
343             {
344 122     122   209 my ( $self, $attr, $line ) = @_;
345              
346             my $tbl = HTML::TableParser::Table->new( $self,
347             $self->{Tables}[-1]->ids,
348 122         351 $self->{reqs}, $line );
349              
350 122 50       272 print STDERR __PACKAGE__, "::_start_table : $tbl->{id}\n"
351             if $HTML::TableParser::Verbose;
352              
353 122         253 $self->_process( $tbl->process );
354              
355 122         144 push @{$self->{Tables}}, $tbl;
  122         937  
356             }
357              
358              
359             sub _end_table
360             {
361 123     123   192 my ( $self, $attr, $line ) = @_;
362              
363              
364 123         136 my $tbl = pop @{$self->{Tables}};
  123         202  
365              
366 123 50       215 print STDERR __PACKAGE__, "::_end_table : $tbl->{id}\n"
367             if $HTML::TableParser::Verbose;
368              
369             # the first table in the list is our sentinel table. if we're about
370             # to delete it, it means that we've hit one too many
tags 371             # we delay the croak until after the pop so that the verbose error 372             # message prints something nice. no harm anyway as we're about to 373             # keel over and croak. 374               375             Carp::croak( __PACKAGE__, 376             ": $line: unbalanced and
tags; too many tags" ) 377 123 100       142 if 0 == @{$self->{Tables}};   123         380   378               379 122         323 undef $tbl; 380               381 122         4793 $self->_process( $self->{Tables}[-1]->process ); 382             } 383               384               385             sub _text 386             { 387 62098     62098   145638 my ( $self, $text, $line ) = @_; 388               389 62098         111474 $self->{Tables}[-1]->text( $text ); 390             } 391               392             1; 393               394             # 395             # This file is part of HTML-TableParser 396             # 397             # This software is Copyright (c) 2018 by Smithsonian Astrophysical Observatory. 398             # 399             # This is free software, licensed under: 400             # 401             # The GNU General Public License, Version 3, June 2007 402             # 403               404             =pod 405               406             =head1 NAME 407               408             HTML::TableParser - HTML::TableParser - Extract data from an HTML table 409               410             =head1 VERSION 411               412             version 0.43 413               414             =head1 SYNOPSIS 415               416             use HTML::TableParser; 417               418             @reqs = ( 419             { 420             id => 1.1, # id for embedded table 421             hdr => \&header, # function callback 422             row => \&row, # function callback 423             start => \&start, # function callback 424             end => \&end, # function callback 425             udata => { Snack => 'Food' }, # arbitrary user data 426             }, 427             { 428             id => 1, # table id 429             cols => [ 'Object Type', 430             qr/object/ ], # column name matches 431             obj => $obj, # method callbacks 432             }, 433             ); 434               435             # create parser object 436             $p = HTML::TableParser->new( \@reqs, 437             { Decode => 1, Trim => 1, Chomp => 1 } ); 438             $p->parse_file( 'foo.html' ); 439               440               441             # function callbacks 442             sub start { 443             my ( $id, $line, $udata ) = @_; 444             #... 445             } 446               447             sub end { 448             my ( $id, $line, $udata ) = @_; 449             #... 450             } 451               452             sub header { 453             my ( $id, $line, $cols, $udata ) = @_; 454             #... 455             } 456               457             sub row { 458             my ( $id, $line, $cols, $udata ) = @_; 459             #... 460             } 461               462             =head1 DESCRIPTION 463               464             B uses B to extract data from an HTML 465             table. The data is returned via a series of user defined callback 466             functions or methods. Specific tables may be selected either by a 467             matching a unique table id or by matching against the column names. 468             Multiple (even nested) tables may be parsed in a document in one pass. 469               470             =head2 Table Identification 471               472             Each table is given a unique id, relative to its parent, based upon its 473             order and nesting. The first top level table has id C<1>, the second 474             C<2>, etc. The first table nested in table C<1> has id C<1.1>, the 475             second C<1.2>, etc. The first table nested in table C<1.1> has id 476             C<1.1.1>, etc. These, as well as the tables' column names, may 477             be used to identify which tables to parse. 478               479             =head2 Data Extraction 480               481             As the parser traverses a selected table, it will pass data to user 482             provided callback functions or methods after it has digested 483             particular structures in the table. All functions are passed the 484             table id (as described above), the line number in the HTML source 485             where the table was found, and a reference to any table specific user 486             provided data. 487               488             =over 8 489               490             =item Table Start 491               492             The B callback is invoked when a matched table has been found. 493               494             =item Table End 495               496             The B callback is invoked after a matched table has been parsed. 497               498             =item Header 499               500             The B callback is invoked after the table header has been read in. 501             Some tables do not use the BthE> tag to indicate a header, so this 502             function may not be called. It is passed the column names. 503               504             =item Row 505               506             The B callback is invoked after a row in the table has been read. 507             It is passed the column data. 508               509             =item Warn 510               511             The B callback is invoked when a non-fatal error occurs during 512             parsing. Fatal errors croak. 513               514             =item New 515               516             This is the class method to call to create a new object when 517             B is supposed to create new objects upon table 518             start. 519               520             =back 521               522             =head2 Callback API 523               524             Callbacks may be functions or methods or a mixture of both. 525             In the latter case, an object must be passed to the constructor. 526             (More on that later.) 527               528             The callbacks are invoked as follows: 529               530             start( $tbl_id, $line_no, $udata ); 531               532             end( $tbl_id, $line_no, $udata ); 533               534             hdr( $tbl_id, $line_no, \@col_names, $udata ); 535               536             row( $tbl_id, $line_no, \@data, $udata ); 537               538             warn( $tbl_id, $line_no, $message, $udata ); 539               540             new( $tbl_id, $udata ); 541               542             =head2 Data Cleanup 543               544             There are several cleanup operations that may be performed automatically: 545               546             =over 8 547               548             =item Chomp 549               550             B the data 551               552             =item Decode 553               554             Run the data through B. 555               556             =item DecodeNBSP 557               558             Normally B changes a non-breaking space into 559             a character which doesn't seem to be matched by Perl's whitespace 560             regexp. Setting this attribute changes the HTML C character to 561             a plain 'ol blank. 562               563             =item Trim 564               565             remove leading and trailing white space. 566               567             =back 568               569             =head2 Data Organization 570               571             Column names are derived from cells delimited by the BthE> and 572             B/thE> tags. Some tables have header cells which span one or 573             more columns or rows to make things look nice. B 574             determines the actual number of columns used and provides column 575             names for each column, repeating names for spanned columns and 576             concatenating spanned rows and columns. For example, if the 577             table header looks like this: 578               579             +----+--------+----------+-------------+-------------------+ 580             | | | Eq J2000 | | Velocity/Redshift | 581             | No | Object |----------| Object Type |-------------------| 582             | | | RA | Dec | | km/s | z | Qual | 583             +----+--------+----------+-------------+-------------------+ 584               585             The columns will be: 586               587             No 588             Object 589             Eq J2000 RA 590             Eq J2000 Dec 591             Object Type 592             Velocity/Redshift km/s 593             Velocity/Redshift z 594             Velocity/Redshift Qual 595               596             Row data are derived from cells delimited by the BtdE> and 597             B/tdE> tags. Cells which span more than one column or row are 598             handled correctly, i.e. the values are duplicated in the appropriate 599             places. 600               601             =head1 METHODS 602               603             =over 8 604               605             =item new 606               607             $p = HTML::TableParser->new( \@reqs, \%attr ); 608               609             This is the class constructor. It is passed a list of table requests 610             as well as attributes which specify defaults for common operations. 611             Table requests are documented in L. 612               613             The C<%attr> hash provides default values for some of the table 614             request attributes, namely the data cleanup operations ( C, 615             C, C ), and the multi match attribute C, 616             i.e., 617               618             $p = HTML::TableParser->new( \@reqs, { Chomp => 1 } ); 619               620             will set B on for all of the table requests, unless overridden 621             by them. The data cleanup operations are documented above; C 622             is documented in L. 623               624             B defaults to on; all of the others default to off. 625               626             =item parse_file 627               628             This is the same function as in B. 629               630             =item parse 631               632             This is the same function as in B. 633               634             =back 635               636             =head1 Table Requests 637               638             A table request is a hash used by B to determine 639             which tables are to be parsed, the callbacks to be invoked, and any 640             data cleanup. There may be multiple requests processed by one call to 641             the parser; each table is associated with a single request (even if 642             several requests match the table). 643               644             A single request may match several tables, however unless the 645             B attribute is specified for that request, it will be used 646             for the first matching table only. 647               648             A table request which matches a table id of C will be used as 649             a catch-all request, and will match all tables not matched by other 650             requests. Please note that tables are compared to the requests in the 651             order that the latter are passed to the B method; place the 652             B method last for proper behavior. 653               654             =head2 Identifying tables to parse 655               656             B needs to be told which tables to parse. This can 657             be done by matching table ids or column names, or a combination of 658             both. The table request hash elements dedicated to this are: 659               660             =over 8 661               662             =item id 663               664             This indicates a match on table id. It can take one of these forms: 665               666             =over 8 667               668             =item exact match 669               670             id => $match 671             id => '1.2' 672               673             Here C<$match> is a scalar which is compared directly to the table id. 674               675             =item regular expression 676               677             id => $re 678             id => qr/1\.\d+\.2/ 679               680             C<$re> is a regular expression, which must be constructed with the 681             C operator. 682               683             =item subroutine 684               685             id => \&my_match_subroutine 686             id => sub { my ( $id, $oids ) = @_ ; 687             $oids[0] > 3 && $oids[1] < 2 } 688               689             Here C is assigned a coderef to a subroutine which returns 690             true if the table matches, false if not. The subroutine is passed 691             two arguments: the table id as a scalar string ( e.g. C<1.2.3>) and the 692             table id as an arrayref (e.g. C<$oids = [ 1, 2, 3]>). 693               694             =back 695               696             C may be passed an array containing any combination of the 697             above: 698               699             id => [ '1.2', qr/1\.\d+\.2/, sub { ... } ] 700               701             Elements in the array may be preceded by a modifier indicating 702             the action to be taken if the table matches on that element. 703             The modifiers and their meanings are: 704               705             =over 8 706               707             =item C<-> 708               709             If the id matches, it is explicitly excluded from being processed 710             by this request. 711               712             =item C<--> 713               714             If the id matches, it is skipped by B requests. 715               716             =item C<+> 717               718             If the id matches, it will be processed by this request. This 719             is the default action. 720               721             =back 722               723             An example: 724               725             id => [ '-', '1.2', 'DEFAULT' ] 726               727             indicates that this request should be used for all tables, 728             except for table 1.2. 729               730             id => [ '--', '1.2' ] 731               732             Table 2 is just plain skipped altogether. 733               734             =item cols 735               736             This indicates a match on column names. It can take one of these forms: 737               738             =over 8 739               740             =item exact match 741               742             cols => $match 743             cols => 'Snacks01' 744               745             Here C<$match> is a scalar which is compared directly to the column names. 746             If any column matches, the table is processed. 747               748             =item regular expression 749               750             cols => $re 751             cols => qr/Snacks\d+/ 752               753             C<$re> is a regular expression, which must be constructed with the 754             C operator. Again, a successful match against any column name 755             causes the table to be processed. 756               757             =item subroutine 758               759             cols => \&my_match_subroutine 760             cols => sub { my ( $id, $oids, $cols ) = @_ ; 761             ... } 762               763             Here C is assigned a coderef to a subroutine which returns 764             true if the table matches, false if not. The subroutine is passed 765             three arguments: the table id as a scalar string ( e.g. C<1.2.3>), the 766             table id as an arrayref (e.g. C<$oids = [ 1, 2, 3]>), and the column 767             names, as an arrayref (e.g. C<$cols = [ 'col1', 'col2' ]>). This 768             option gives the calling routine the ability to make arbitrary 769             selections based upon table id and columns. 770               771             =back 772               773             C may be passed an arrayref containing any combination of the 774             above: 775               776             cols => [ 'Snacks01', qr/Snacks\d+/, sub { ... } ] 777               778             Elements in the array may be preceded by a modifier indicating 779             the action to be taken if the table matches on that element. 780             They are the same as the table id modifiers mentioned above. 781               782             =item colre 783               784             B 785             An arrayref containing the regular expressions to match, or a scalar 786             containing a single reqular expression 787               788             =back 789               790             More than one of these may be used for a single table request. A 791             request may match more than one table. By default a request is used 792             only once (even the C id match!). Set the C 793             attribute to enable multiple matches per request. 794               795             When attempting to match a table, the following steps are taken: 796               797             =over 8 798               799             =item 1 800               801             The table id is compared to the requests which contain an id match. 802             The first such match is used (in the order given in the passed array). 803               804             =item 2 805               806             If no explicit id match is found, column name matches are attempted. 807             The first such match is used (in the order given in the passed array) 808               809             =item 3 810               811             If no column name match is found (or there were none requested), 812             the first request which matches an B of C is used. 813               814             =back 815               816             =head2 Specifying the data callbacks 817               818             Callback functions are specified with the callback attributes 819             C, C, C, C, and C. They should be set to 820             code references, i.e. 821               822             %table_req = ( ..., start => \&start_func, end => \&end_func ) 823               824             To use methods, specify the object with the C key, and 825             the method names via the callback attributes, which should be set 826             to strings. If you don't specify method names they will default to (you 827             guessed it) C, C, C, C, and C. 828               829             $obj = SomeClass->new(); 830             # ... 831             %table_req_1 = ( ..., obj => $obj ); 832             %table_req_2 = ( ..., obj => $obj, start => 'start', 833             end => 'end' ); 834               835             You can also have B create a new object for you 836             for each table by specifying the C attribute. By default 837             the constructor is assumed to be the class B method; if not, 838             specify it using the C attribute: 839               840             use MyClass; 841             %table_req = ( ..., class => 'MyClass', new => 'mynew' ); 842               843             To use a function instead of a method for a particular callback, 844             set the callback attribute to a code reference: 845               846             %table_req = ( ..., obj => $obj, end => \&end_func ); 847               848             You don't have to provide all the callbacks. You should not use both 849             C and C in the same table request. 850               851             B automatically determines if your object 852             or class has one of the required methods. If you wish it I 853             to use a particular method, set it equal to C. For example 854               855             %table_req = ( ..., obj => $obj, end => undef ) 856               857             indicates the object's B method should not be called, even 858             if it exists. 859               860             You can specify arbitrary data to be passed to the callback functions 861             via the C attribute: 862               863             %table_req = ( ..., udata => \%hash_of_my_special_stuff ) 864               865             =head2 Specifying Data cleanup operations 866               867             Data cleanup operations may be specified uniquely for each table. The 868             available keys are C, C, C. They should be 869             set to a non-zero value if the operation is to be performed. 870               871             =head2 Other Attributes 872               873             The C key is used when a request is capable of handling 874             multiple tables in the document. Ordinarily, a request will process 875             a single table only (even C requests). 876             Set it to a non-zero value to allow the request to handle more than 877             one table. 878               879             =head1 BUGS 880               881             Please report any bugs or feature requests on the bugtracker website 882             L or by 883             email to 884             L. 885               886             When submitting a bug or request, please include a test-file or a 887             patch to an existing test-file that illustrates the bug or desired 888             feature. 889               890             =head1 SOURCE 891               892             The development version is on github at L 893             and may be cloned from L 894               895             =head1 AUTHOR 896               897             Diab Jerius 898               899             =head1 COPYRIGHT AND LICENSE 900               901             This software is Copyright (c) 2018 by Smithsonian Astrophysical Observatory. 902               903             This is free software, licensed under: 904               905             The GNU General Public License, Version 3, June 2007 906               907             =cut 908               909             __END__