| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | ###################################################################### | 
| 2 |  |  |  |  |  |  | package AnyData::Format::HTMLtable; | 
| 3 |  |  |  |  |  |  | ###################################################################### | 
| 4 |  |  |  |  |  |  | # by Jeff Zucker | 
| 5 |  |  |  |  |  |  | # copyright 2000 all rights reserved | 
| 6 |  |  |  |  |  |  | ###################################################################### | 
| 7 |  |  |  |  |  |  |  | 
| 8 |  |  |  |  |  |  | =head1 NAME | 
| 9 |  |  |  |  |  |  |  | 
| 10 |  |  |  |  |  |  | HTMLtable - tied hash and DBI/SQL access to HTML tables | 
| 11 |  |  |  |  |  |  |  | 
| 12 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | use AnyData; | 
| 15 |  |  |  |  |  |  | my $table = adHash( 'HTMLtable', $filename ); | 
| 16 |  |  |  |  |  |  | while (my $row = each %$table) { | 
| 17 |  |  |  |  |  |  | print $row->{name},"\n" if $row->{country} =~ /us|mx|ca/; | 
| 18 |  |  |  |  |  |  | } | 
| 19 |  |  |  |  |  |  | # ... other tied hash operations | 
| 20 |  |  |  |  |  |  |  | 
| 21 |  |  |  |  |  |  | OR | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | use DBI | 
| 24 |  |  |  |  |  |  | my $dbh = DBI->connect('dbi:AnyData:'); | 
| 25 |  |  |  |  |  |  | $dbh->func('table1','HTMLtable', $filename,'ad_catalog'); | 
| 26 |  |  |  |  |  |  | my $hits = $dbh->selectall_arrayref( qq{ | 
| 27 |  |  |  |  |  |  | SELECT name FROM table1 WHERE country = 'us' | 
| 28 |  |  |  |  |  |  | }); | 
| 29 |  |  |  |  |  |  | # ... other DBI/SQL operations | 
| 30 |  |  |  |  |  |  |  | 
| 31 |  |  |  |  |  |  |  | 
| 32 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 33 |  |  |  |  |  |  |  | 
| 34 |  |  |  |  |  |  | This module allows one to treat the data contained in an HTML table as | 
| 35 |  |  |  |  |  |  | a tied hash (using AnyData.pm) or as a DBI/SQL accessible database | 
| 36 |  |  |  |  |  |  | (using DBD::AnyData.pm).  Both the tiedhash and DBI interfaces allow | 
| 37 |  |  |  |  |  |  | one to read, modify, and create HTML tables from perl data or from local or | 
| 38 |  |  |  |  |  |  | remote files. | 
| 39 |  |  |  |  |  |  |  | 
| 40 |  |  |  |  |  |  | The module requires that CGI, HTML::Parser and HTML::TableExtract are installed. | 
| 41 |  |  |  |  |  |  |  | 
| 42 |  |  |  |  |  |  | When reading the HTML table, this module is essentially just a pass | 
| 43 |  |  |  |  |  |  | through to Matt Sisk's excellent HTML::TableExtract module. | 
| 44 |  |  |  |  |  |  |  | 
| 45 |  |  |  |  |  |  | If no flags are specified in the adTie() or ad_catalog() calls, then TableExtract is called with depth=0 and count=0, in other words it finds the first row of the first table and treats that as the column names for the entire table.  If a flag for 'cols' (column names) is specified in the adTie() or ad_catalog() calls, that list of column names is passed to TableExtract as a headers parameter.  If the user specifies flags for headers, depth, or count, those are passed directly to TableExtract. | 
| 46 |  |  |  |  |  |  |  | 
| 47 |  |  |  |  |  |  | When exporting to an HTMLtable, you may pass flags to specify properties | 
| 48 |  |  |  |  |  |  | of the whole table (table_flags), the top row containing the column names | 
| 49 |  |  |  |  |  |  | (top_row_flags), and the data rows (data_row_flags).  These flags follow | 
| 50 |  |  |  |  |  |  | the syntax of CGI.pm table constructors, e.g.: | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | print adExport( $table, 'HTMLtable', { | 
| 53 |  |  |  |  |  |  | table_flags    => {Border=>3,bgColor=>'blue'}; | 
| 54 |  |  |  |  |  |  | top_row_flags  => {bgColor=>'red'}; | 
| 55 |  |  |  |  |  |  | data_row_flags => {valign='top'}; | 
| 56 |  |  |  |  |  |  | }); | 
| 57 |  |  |  |  |  |  |  | 
| 58 |  |  |  |  |  |  | The table_flags will default to {Border=>1,bgColor=>'white'} if none | 
| 59 |  |  |  |  |  |  | are specified. | 
| 60 |  |  |  |  |  |  |  | 
| 61 |  |  |  |  |  |  | The top_row_flags will default to {bgColor=>'#c0c0c0'} if none are | 
| 62 |  |  |  |  |  |  | specified; | 
| 63 |  |  |  |  |  |  |  | 
| 64 |  |  |  |  |  |  | The data_row_flags will be empty if none are specified. | 
| 65 |  |  |  |  |  |  |  | 
| 66 |  |  |  |  |  |  | In other words, if no flags are specified the table will print out with | 
| 67 |  |  |  |  |  |  | a border of 1, the column headings in gray, and the data rows in white. | 
| 68 |  |  |  |  |  |  |  | 
| 69 |  |  |  |  |  |  | CAUTION: This module will *not* preserve anything in the html file except | 
| 70 |  |  |  |  |  |  | the selected table so if your file contains more than the selected table, | 
| 71 |  |  |  |  |  |  | you will want to use adTie() or $dbh->func(...,'ad_import') to read the | 
| 72 |  |  |  |  |  |  | table and then adExport() or $dbh->func(...,'ad_export') to write | 
| 73 |  |  |  |  |  |  | the table to a different file.  When using the HTMLtable format, this is the | 
| 74 |  |  |  |  |  |  | only way to preserve changes to the data, the adTie() command will *not* | 
| 75 |  |  |  |  |  |  | write to a file. | 
| 76 |  |  |  |  |  |  |  | 
| 77 |  |  |  |  |  |  | =head1 AUTHOR & COPYRIGHT | 
| 78 |  |  |  |  |  |  |  | 
| 79 |  |  |  |  |  |  | copyright 2000, Jeff Zucker | 
| 80 |  |  |  |  |  |  | all rights reserved | 
| 81 |  |  |  |  |  |  |  | 
| 82 |  |  |  |  |  |  | =cut | 
| 83 |  |  |  |  |  |  |  | 
| 84 | 1 |  |  | 1 |  | 4 | use strict; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 28 |  | 
| 85 | 1 |  |  | 1 |  | 2 | use warnings; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 27 |  | 
| 86 | 1 |  |  | 1 |  | 3 | use AnyData::Format::Base; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 15 |  | 
| 87 | 1 |  |  | 1 |  | 2 | use AnyData::Storage::File; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 23 |  | 
| 88 | 1 |  |  | 1 |  | 4 | use vars qw( @ISA $VERSION); | 
|  | 1 |  |  |  |  | 0 |  | 
|  | 1 |  |  |  |  | 348 |  | 
| 89 |  |  |  |  |  |  | @AnyData::Format::HTMLtable::ISA = qw( AnyData::Format::Base ); | 
| 90 |  |  |  |  |  |  |  | 
| 91 |  |  |  |  |  |  | $VERSION = '0.05'; | 
| 92 |  |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  | sub new { | 
| 94 | 1 |  |  | 1 | 0 | 2 | my $class = shift; | 
| 95 | 1 |  | 50 |  |  | 4 | my $self  = shift ||  {}; | 
| 96 | 1 |  |  |  |  | 2 | $self->{export_on_close} = 1; | 
| 97 | 1 |  |  |  |  | 3 | $self->{slurp_mode} = 1; | 
| 98 | 1 |  |  |  |  | 3 | return bless $self, $class; | 
| 99 |  |  |  |  |  |  | } | 
| 100 |  |  |  |  |  |  |  | 
| 101 | 1 |  |  | 1 | 0 | 6 | sub storage_type { 'RAM'; } | 
| 102 |  |  |  |  |  |  |  | 
| 103 |  |  |  |  |  |  | sub import { | 
| 104 | 0 |  |  | 0 |  | 0 | my $self = shift; | 
| 105 | 0 |  |  |  |  | 0 | my $data = shift; | 
| 106 | 0 |  |  |  |  | 0 | my $storage = shift; | 
| 107 | 0 |  |  |  |  | 0 | return $self->get_data($data,$self->{col_names}); | 
| 108 |  |  |  |  |  |  | } | 
| 109 |  |  |  |  |  |  | sub get_data { | 
| 110 | 0 |  |  | 0 | 0 | 0 | my $self = shift; | 
| 111 | 0 | 0 |  |  |  | 0 | my $str       = shift or return undef; | 
| 112 | 0 |  |  |  |  | 0 | my $col_names = shift; | 
| 113 | 0 |  |  |  |  | 0 | require HTML::TableExtract; | 
| 114 | 0 |  | 0 |  |  | 0 | my $count   = $self->{count} || 0; | 
| 115 | 0 |  | 0 |  |  | 0 | my $depth   = $self->{depth} || 0; | 
| 116 | 0 |  | 0 |  |  | 0 | my $headers = $self->{headers} || $self->{col_names} || undef; | 
| 117 | 0 |  |  |  |  | 0 | my %flags; | 
| 118 | 0 | 0 | 0 |  |  | 0 | if (defined $count or defined $depth or defined $headers) { | 
|  |  |  | 0 |  |  |  |  | 
| 119 | 0 | 0 |  |  |  | 0 | $flags{count} = $count if defined $count; | 
| 120 | 0 | 0 |  |  |  | 0 | $flags{depth} = $depth if defined $depth; | 
| 121 | 0 | 0 |  |  |  | 0 | $flags{headers} = $headers if defined $headers; | 
| 122 |  |  |  |  |  |  | } | 
| 123 |  |  |  |  |  |  | else { | 
| 124 | 0 | 0 |  |  |  | 0 | %flags = $col_names | 
| 125 |  |  |  |  |  |  | ? ( headers => $col_names ) | 
| 126 |  |  |  |  |  |  | : (count=>$count,depth=>$depth); | 
| 127 |  |  |  |  |  |  | } | 
| 128 | 0 |  |  |  |  | 0 | my $te = new HTML::TableExtract( | 
| 129 |  |  |  |  |  |  | %flags | 
| 130 |  |  |  |  |  |  | ); | 
| 131 | 0 |  |  |  |  | 0 | $te->parse($str); | 
| 132 | 0 |  |  |  |  | 0 | my $table; | 
| 133 | 0 |  |  |  |  | 0 | @$table = $te->rows; | 
| 134 | 0 | 0 |  |  |  | 0 | $self->{col_names} = shift @$table if !$col_names; | 
| 135 | 0 |  |  |  |  | 0 | return $table, $self->{col_names}; | 
| 136 |  |  |  |  |  |  | } | 
| 137 |  |  |  |  |  |  |  | 
| 138 |  |  |  |  |  |  | sub export { | 
| 139 |  |  |  |  |  |  | #print "EXPORTING!"; | 
| 140 | 1 |  |  | 1 | 0 | 6 | my $self      = shift; | 
| 141 | 1 |  |  |  |  | 1 | my $storage   = shift; | 
| 142 | 1 |  |  |  |  | 2 | my $col_names = $storage->{col_names}; | 
| 143 | 1 |  |  |  |  | 1 | my $table     = $storage->{records}; | 
| 144 |  |  |  |  |  |  | #use Data::Dumper; print Dumper $table; print "###"; exit; | 
| 145 | 1 |  |  |  |  | 1 | my $fh        = $storage->{fh}; | 
| 146 | 1 |  |  | 1 |  | 841 | use CGI; | 
|  | 1 |  |  |  |  | 30833 |  | 
|  | 1 |  |  |  |  | 6 |  | 
| 147 | 1 |  | 50 |  |  | 2 | my $table_flags = shift || {Border=>1,bgColor=>'white'}; | 
| 148 | 1 |  | 50 |  |  | 5 | my $top_row_flags = shift || {bgColor=>'#c0c0c0'}; | 
| 149 | 1 |  | 50 |  |  | 3 | my $data_row_flags = shift || {}; | 
| 150 |  |  |  |  |  |  | @$table = map { | 
| 151 | 1 |  |  |  |  | 2 | my $row = $_; | 
|  | 6 |  |  |  |  | 3 |  | 
| 152 | 6 | 100 |  |  |  | 4 | @$row = map { $_ || ' ' } @$row; | 
|  | 11 |  |  |  |  | 23 |  | 
| 153 | 6 |  |  |  |  | 7 | $row; | 
| 154 |  |  |  |  |  |  | } @$table; | 
| 155 | 1 |  |  |  |  | 3 | my $str = | 
| 156 |  |  |  |  |  |  | CGI::table( | 
| 157 |  |  |  |  |  |  | $table_flags, | 
| 158 |  |  |  |  |  |  | CGI::Tr( $top_row_flags, CGI::th($col_names) ), | 
| 159 |  |  |  |  |  |  | map CGI::Tr( $data_row_flags, CGI::td($_) ), @$table | 
| 160 |  |  |  |  |  |  | ); | 
| 161 | 1 | 50 |  |  |  | 606 | $fh->write($str,length $str) if $fh; | 
| 162 | 1 |  |  |  |  | 86 | return $str; | 
| 163 |  |  |  |  |  |  | } | 
| 164 |  |  |  |  |  |  |  | 
| 165 |  |  |  |  |  |  | sub exportOLD { | 
| 166 | 0 |  |  | 0 | 0 |  | my $self      = shift; | 
| 167 | 0 |  |  |  |  |  | my $table     = shift; | 
| 168 | 0 |  |  |  |  |  | my $col_names = shift; | 
| 169 | 1 |  |  | 1 |  | 237 | use CGI; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 3 |  | 
| 170 | 0 |  | 0 |  |  |  | my $table_flags = shift || {Border=>1,bgColor=>'white'}; | 
| 171 | 0 |  | 0 |  |  |  | my $top_row_flags = shift || {bgColor=>'#c0c0c0'}; | 
| 172 | 0 |  | 0 |  |  |  | my $data_row_flags = shift || {}; | 
| 173 |  |  |  |  |  |  | return | 
| 174 | 0 |  |  |  |  |  | CGI::table( | 
| 175 |  |  |  |  |  |  | $table_flags, | 
| 176 |  |  |  |  |  |  | CGI::Tr( $top_row_flags, CGI::th($col_names) ), | 
| 177 |  |  |  |  |  |  | map CGI::Tr( $data_row_flags, CGI::td($_) ), @$table | 
| 178 |  |  |  |  |  |  | ); | 
| 179 |  |  |  |  |  |  | } | 
| 180 |  |  |  |  |  |  | 1; | 
| 181 |  |  |  |  |  |  |  | 
| 182 |  |  |  |  |  |  |  | 
| 183 |  |  |  |  |  |  |  | 
| 184 |  |  |  |  |  |  |  | 
| 185 |  |  |  |  |  |  |  | 
| 186 |  |  |  |  |  |  |  | 
| 187 |  |  |  |  |  |  |  | 
| 188 |  |  |  |  |  |  |  |