XML, the Perl Way

Processing XML with Perl Michel Rodriguez

Introduction to XML::Twig

Example: Data Base Integration

Example: an HTML converter

Create an HTML document listing all available wines, sorted within each category. The field to sort on is passed as the argument of the script.

#!/bin/perl -w

use strict;
use XML::Twig;
use CGI qw(:standard);

my $sort_on= shift;
die "invalid sort field $sort_on" unless( $sort_on=~/(year|rating|price)/);

my $t= new XML::Twig( TwigHandlers     => { category => \&category},
                      StartTagHandlers => { class    => \&class   }, 
                     );

print start_html( "Wine list");
print h1( "Wine list");
print '<table border="1">';
print Tr( td( 'Winery'), td( 'Type'), td( 'Year'),
          td( 'Rating'), td( 'Price'));

$t->parsefile( "wine.xml");

print '</table>';
print end_html;

exit;

sub class
  { my( $t, $class)= @_;
    # just print the class name in a h2, accross the whole table
    my $name= $class->att( 'name');
    $name= join ' ', map { ucfirst } split / /, $name;
    print Tr( td( {colspan => 5}, h2( $name)));
  }

sub category
  { my( $t, $category)= @_;
    my $name= $category->att( 'name');
    $name= join ' ', map { ucfirst } split / /, $name;
    print Tr( td( {colspan => 5}, b( $name)));

    # get the rows
    my @items= $category->children( 'item');
    my @rows;
    foreach my $item (@items)
      { # skip wines that are not in stock
        next unless(  $item->first_child( 'stock')->text);
        my $row;
        $row->{winery} = $item->first_child( 'winery')->text ;
        $row->{type}   = $item->first_child( 'type')->text   ;
        $row->{type} .= ' (' . $item->first_child( 'type')->att( 'aoc') . ')'
          if( $item->first_child( 'type')->att( 'aoc'));
        $row->{year}   = $item->first_child( 'year')->text   ;
        $row->{rating} = $item->first_child( 'rating')->text ;
        $row->{price}  = $item->first_child( 'price')->text  ;
        push @rows, $row;
      }

    # sort the rows using the Schwartzian transform
    @rows= map  { $_->[1]}
           sort { $b->[0] <=> $a->[0] }
           map  { [$_->{$sort_on}, $_] } @rows;

    # print the table
    foreach my $row (@rows)
      { print Tr( td( $row->{winery}), td( $row->{type}), td( $row->{year}),
                  td( $row->{rating}), td( $row->{price}));
      }
    $t->purge;
  }


Introduction to XML::Twig

Example: Data Base Integration