I often find myself generating HTML tables from SQL tables, with some amount of formatting and munging in between. A handy technique that I use often is to put as much of the column description into one place as I can, then have a general loop that I can apply to each row of data. This lets me tweak many settings in one place and avoids lots of redundancy (in both perl and HTML).

# since the order of the columns is significant, we # use an array to hold information about each column. my @COL_INFO = ( { name => 'foo_id', hide => 1 }, { name => 'foo', id => 'foo_id', width => 400, gen => \&gen_foo, title => 'Foo' }, { name => 'bar', width => 200, align => 'right', title => 'Barque' } );

If I need other utility arrays or hashes, I can generate them all from the one central store above:

# now we can derive whichever other hashes or arrays # we might want from the above data. having a list # of column names is always handy: my @COL_NAMES = map $_->{name}, @COL_INFO; # and we might want to look up columns by name: my %COL_BY_NAME; @COL_BY_NAME{ @COL_NAMES } = @COL_INFO; # and to find the index of a column name: my %COL_INDEX; @COL_INDEX{ @COL_NAMES } = 0 .. $#COL_INFO;

This degree of uniformity lets us use very regular loops to print out headers and rows, and do all our checking and formatting in one place:

# ------------------------------------------------------- # the information is centralized for other uses, such as # printing headers: print "<tr>"; foreach my $info ( @COL_INFO ) { # skip hidden fields next if $info->{hide}; # build up opening tag my $header = "<th"; if ( my $width = $info->{width} ) { $header .= qq| width="$width"|; } $header .= ">"; print( $header . escapeHTML( $info->{title} ) . "</th>\n" ); } print "</tr>\n"; # ------------------------------------------------------- # then for each row: while ( my $cur = $sth->fetch() ) { # if necessary, you can construct a hash using # whatever keys you want, not just db column names: my %row; @row{ @COL_NAMES } = @$cur; # or maybe just pick out one value my $foo_id = $cur->[ $COL_INDEX{foo_id} ]; # formatting the output is now easier, too: print qq|<tr valign="top">\n|; foreach my $info ( @COL_INFO ) { my $cell = "<td"; $cell .= qq| align="$info->{align}"| if $info->{align}; $cell .= ">"; if ( my $gen = $info->{gen} ) { $cell .= $gen->( $cur ); } else { my $ix = $COL_INDEX{ $info->{name} }; $cell .= escapeHTML( $cur->[$ix] ); } $cell .= "</td>\n"; print $cell; } print "</tr>\n"; }

I like this centralized mechanism because I only have to change one place to add or remove a column, and I only have to code tricky things (remembering to HTML-entify strings, etc) in one place. Also, the description itself could eventually be extracted from a database, leading to even more dynamic (while still "typesafe") and well-formatted output.

Edit by BazB: added readmore tags.


In reply to One structure to describe multiple arrays or hashes by tkil

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.