2nd OSCon Schedule Contribution

Matts on 2002-07-18T13:39:44

Gnat suggested PDF. Well I decided to oblige. This turns it into an 80-odd page PDF. Shame it's not sorted in any reasonable order though :-/

#!/usr/bin/perl -w

use strict; use XML::SAX;

my $writer = XML::SAX::ParserFactory->parser( Handler => OSCon2PDF->new(Output => "oscon.pdf") );

warn("Writer is: $writer\n"); $writer->parse_uri("schedule.xml");

package OSCon2PDF; use PDFLib; use XML::SAX::Writer; use strict;

my %alltags;

sub new { my $class = shift; my $opt = (@_ == 1) ? { %{shift()} } : {@_};

$opt->{Output} ||= *{STDOUT}{IO}; $opt->{gathered_text} = '';

return bless $opt, $class; }

sub start_document { my ($self, $doc) = @_;

warn("start_document\n"); # setup consumer my $ref = ref $self->{Output}; if ($ref eq 'SCALAR') { $self->{Consumer} = XML::SAX::Writer::StringConsumer->new($self->{Output}); } elsif ($ref eq 'ARRAY') { $self->{Consumer} = XML::SAX::Writer::ArrayConsumer->new($self->{Output}); } elsif ($ref eq 'GLOB' or UNIVERSAL::isa($self->{Output}, 'IO::Handle')) { $self->{Consumer} = XML::SAX::Writer::HandleConsumer->new($self->{Output}); } elsif (not $ref) { $self->{Consumer} = XML::SAX::Writer::FileConsumer->new($self->{Output}) ; } elsif (UNIVERSAL::can($self->{Output}, 'output')) { $self->{Consumer} = $self->{Output}; } else { XML::SAX::Writer::Exception->throw({ Message => 'Unknown option for Output' }); }

$self->{Encoder} = XML::SAX::Writer::NullConverter->new;

# create PDF and set defaults $self->{pdf} = PDFLib->new(); $self->{pdf}->papersize("a4"); $self->{pdf}->set_border_style("solid", 0); $self->{bookmarks} = []; $self->{font} = 'Helvetica'; $self->{titlesize} = 24; $self->{textsize} = 12; }

sub end_document { my ($self) = @_; warn("end_document\n"); $self->{pdf}->finish;

$self->{Consumer}->output( $self->{pdf}->get_buffer ); $self->{Consumer}->finalize; }

sub push_bookmark { my $self = shift; # warn("push_bookmark($_[0]) from ", caller, "\n"); push @{$self->{bookmarks}}, shift; }

sub top_bookmark { my $self = shift; return $self->{bookmarks}[-1]; }

sub pop_bookmark { my $self = shift; # warn("pop_bookmark() from ", caller, "\n"); pop @{$self->{bookmarks}}; }

sub start_element { my ($self, $el) = @_; my $name = $el->{LocalName}; delete $self->{current_tag}; if ($name eq 'schedule') { $self->{pdf}->start_page; $self->{pdf}->set_font(face => $self->{font}, size => $self->{titlesize}); $self->push_bookmark($self->{pdf}->add_bookmark(text => "OSCon Sessions")); my $bb = $self->{pdf}->new_bounding_box( x => 5, y => 800, w => 602, h => 50, align => "centre", ); $bb->print("OSCon Sessions"); $bb = undef; $self->{pdf}->set_text_pos(560, 10); $self->{pdf}->set_font(face => $self->{font}, size => 8); $self->{pdf}->print("Page ". ++($self->{pageno})); $self->{pdf}->set_text_pos(50, 770); } elsif ($name eq 'session') { $self->{session} = {}; } else { $alltags{$name}++; $self->{current_tag} = $name; } }

sub new_page { my ($self) = @_; $self->{pdf}->start_page; $self->{pdf}->set_font(face => $self->{font}, size => $self->{titlesize}); my $bb = $self->{pdf}->new_bounding_box( x => 5, y => 800, w => 602, h => 50, align => "centre", ); $bb->print("OSCon Sessions"); $bb = undef; $self->{pdf}->set_text_pos(560, 10); $self->{pdf}->set_font(face => $self->{font}, size => 8); $self->{pdf}->print("Page ". ++($self->{pageno})); $self->{pdf}->set_text_pos(50, 770); }

sub characters { my ($self, $el) = @_; no warnings 'uninitialized'; if ($self->{current_tag}) { $self->{session}->{$self->{current_tag}} .= $el->{Data}; } }

sub end_element { my ($self, $el) = @_; my $name = $el->{LocalName}; my $pdf = $self->{pdf}; if ($name eq 'session') { # process session here use Data::Dumper; foreach my $k (keys %{$self->{session}}) { $self->{session}{$k} =~ s/^\s*//; $self->{session}{$k} =~ s/\s*$//; } my ($x, $y) = $pdf->get_text_pos(); $pdf->set_text_pos(50, $y); my ($lines_left) = $y / 14; # guess? my $desc_lines = ($self->{session}{description} =~ tr/\n//); if ($desc_lines > ($lines_left - 6)) { $self->new_page if $self->{pagedown}++; } $pdf->set_font(face => $self->{font}, size => $self->{textsize}); $pdf->print_line("$self->{session}{date} : $self->{session}{start_time_text} to $self->{session}{end_time_text}"); $pdf->print_line("$self->{session}{title} by $self->{session}{p_firstname} $self->{session}{p_lastname}"); $pdf->print_line("Description: "); ($x, $y) = $pdf->get_text_pos(); my $bb = $self->{pdf}->new_bounding_box( x => ($x + 20), y => $y, w => (552 - $x), h => ($y - 20), align => "left", ); for (split(/\n/, $self->{session}{description})) { $bb->print($_); $bb->print_line(""); } } }


why not use

hfb on 2002-07-18T15:03:28

The Acrobat Webcapture? :) I know, it's not perl, but it works beautifully and I use it for archival docs and such.

Re:why not use

Matts on 2002-07-18T16:19:42

There's multiple things I could use. But what fun would that be? ;-)

Seriously though - I was just mucking about - I'm not actually going to use this. Its just sometimes useful to write this stuff to reveal bugs in your libraries (PDFLib in this case).