Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Matts (1087)

Matts
  (email not shown publicly)

I work for MessageLabs [messagelabs.com] in Toronto, ON, Canada. I write spam filters, MTA software, high performance network software, string matching algorithms, and other cool stuff mostly in Perl and C.

Journal of Matts (1087)

Thursday July 18, 2002
08:39 AM

2nd OSCon Schedule Contribution

[ #6448 ]

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("");
        }
    }
}

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • The Acrobat Webcapture? :) I know, it's not perl, but it works beautifully and I use it for archival docs and such.

    • 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).