The 2002 Perl Advent Calendar
[about] | [archives] | [contact] | [home]

On the 8th day of Advent my True Language brought to me..
XML::Handler::AxPoint

AxPoint is a Perl module - a Perl application - that can take XML presentations and convert them into a PDF presentation that can be viewed with Adobe's Acrobat reader or xpdf (amongst many other tools). As well as producing an open, cross platform, output file, it looks nice too. It's what I used this year to give my talk at YAPC::Europe, and I was very pleased with the results.

In my eyes however, AxPoint's biggest advantage has nothing to do with the output format that it uses - it's the input format. First of all it's very simple to write. It's just text, so I can use my editor, and I can quickly jot down what I want to say without worry too much about the actual presentation at that point. And since it's in text I can also email it to people and they can send me diffs back again, allowing colaberation on presentations very easily.

Of course, the real power of XML is that it's really easy to manipulate the presentation programatically - with Perl, or indeed with any other langage with an XML processing toolkit. This means it's really easy to extend the AxPoint langauge to add your own tags and extensions, as I'll demonstate below.

AxPoint presentations are pretty simple to write. Here's a really simple one:

  <?xml version="1.0"?>
  <slideshow>
    <metadata>
      <speaker>Mark Fowler</speaker>
      <email>mark@twoshortplanks.com</email>
      <organisation>London Perl Mongers</organisation>
      <background>bg2.png</background>
    </metadata>
    <title>An Example Slideshow</title>
    <slide>
      <title>My Slide</title>
      <point>This is my slide</point>
      <point level="2">There are many like it</subpoint>
      <point level="2">But this is mine</subpoint>
      <point>I'd like to put it on a CD:</point>
      <image>cd.png</image>
    </slide>
  </slideshow>

And this is what it looks like

  • Download Example Presentaion (41K)
  • There a lots more features (you can have sections, inlcude source code, include SVG graphics, tables to layout your text, and much more) all of which is covered at length

  • in the documentation
  • or in
  • Kip's XML.com article
  • .

    Extending AxPoint

    As AxPoint presentations are nothing more than XML then there's nothing to stop you processing them before they get as far as the XML::Handler for AxPoint - as far as AxPoint is concerned as long as it gets XML in the correct format then everything is fine by it.

    Say - for example - you don't like the way that AxPoint forces you to write <point level="2"> and you'd be happier with something that simply called <subpoint>. Well, all you need to do is make a SAX filter that converts all subpoint> tags into <point level="2" tags automatically.

      package XML::Filter::SubPoint;
      # turn on Perl's safety features
      use strict;
      use warnings;
      # use the XML::SAX::Base class so that unhandled events
      # are just passed straight though
      use base qw(XML::SAX::Base);
      # simple constuctor method
      sub new
      {
        my $class = shift;
        my %options = @_;
        return bless \%options, $class;
      }
      # implement a method that catches any start tags
      sub start_element
      {
        my $self = shift; # the sax processor
        my $tag  = shift; # the tag itself
        # is this a subpoint tag?
        if ($tag->{Name} eq "subpoint")
        {
          # rename it 'point' instead of 'subpoint'
          $tag->{Name} = "point";             # qualified name
          $tag->{LocalName} = $tag->{Name};   # unqualified name
          # add an attribute for the level and set the properties
          $tag->{Attributes}{'{}level'} = {
    				       LocalName => 'level',
    				       Prefix => '',
    				       Value => '2',
    		  		       Name => 'level',
    	  			       NamespaceURI => ''
                                          };
        }
        # return the tag (following pipeline conventions)
        return $self->SUPER::start_element($tag);
      }
      # and a simliar one that catches end tags
      sub end_element
      {
        my $self = shift; # the sax processor
        my $tag  = shift; # the tag itself
        # is this a subpoint tag?
        if ($tag->{Name} eq "subpoint")
        {
          # rename it 'point' instead of 'subpoint'
          $tag->{Name} = "point";             # qualified name
          $tag->{LocalName} = $tag->{Name};   # unqualified name
        }
        # return the tag (following pipeline conventions)
        return $self->SUPER::end_element($tag);
      }
      1; # all perl modules need to return "true"     

    This filter can then be placed in a XML::SAX::Pipeline with a script like this:

      #!/usr/bin/perl
      # turn on perl's safety features
      use strict;
      use warnings;
      # load machines, including the Pipeline functiion
      use XML::SAX::Machines qw(:all);
      # set up a xml pipeline to run the xml though
      my $machine = Pipeline(
       "XML::Filter::SubPoint",  # first through our code
       "XML::Handler::AxPoint",  # then though axpoint, out to STDOUT
      );
      # check we got the correct command line arguments
      die "didn't specify a xml file to parse" unless @ARGV;
      # parse the url (probably just the file) we were
      # passed on the command line
      $machine->parse_uri($ARGV[0]);

    And voila! There we have it an extension to AxPoint. Now this is a simple example, but there's nothing to stop you going further with your preprocesssing. For example, you could have something that automatically extended entities into full blown text. You could have something that inserted source files. If you're really trying you could create a SVG graph from a table of figures.

  • PDF Presentations Using AxPoint article on xml.com
  • XML::SAXMachines