#!/usr/bin/perl # # http://www.devshed.com/Server_Side/Perl/PerlXML/PerlXML1/page7.html # Using Perl with XML (part 1) # What's For Dinner? # 2002-01-15 # This time, my Perl script won't be using an "if" statement when I parse # the file above; instead, I'm going to be keying tag names to values in # a hash. Each of the tags in the XML file above will be replaced with # appropriate HTML markup. # In this case, I've set up two hashes, one for opening tags and one for # closing tags. When the parser encounters an XML tag, it looks up the # hash to see if the tag exists as a key. If it does, the corresponding # value (HTML markup) is printed. This method does away with the slightly # cumbersome branching "if" statements of the previous example, and is # easier to read and understand. # hash of tag names mapped to HTML markup # "recipe" => start a new block # "name" => in bold # "ingredients" => unordered list # "desc" => list items # "process" => ordered list # "step" => list items use strict; use warnings; # use diagnostics; use XML::Parser; my $title = ''; my %startTags = ( "recipe" => "Content-Type: text/html\n\n", "name" => "Recipe: ", "date" => "<i>(", "author" => "<b>", "servings" => "<i>Serves ", "ingredients" => "<h3>Ingredients:</h3><ul>", "desc" => "<li>", "quantity" => "(", "process" => "<h3>Preparation:</h3><ol>", "step" => "<li>" ); # close tags opened above my %endTags = ( "recipe" => "</blockquote><hr></body></html>", "name" => "
\n

_TITLE_

", "date" => ")", "author" => "", "ingredients" => "", "quantity" => ")", "servings" => "", "process" => "" ); # name of XML file my $file = shift (@ARGV) || die "usage: $0 file\n"; # where we are in XML file. my $state = 'NONE'; # this is called when a start tag is found sub start() { # extract variables my ( $parser, $name, %attr ) = @_; # lowercase element name $name = lc($name); $state = $name; # print corresponding HTML if ( $startTags{$name} ) { print "$startTags{$name}"; } } # this is called when CDATA is found sub cdata() { my ( $parser, $data ) = @_; print "$data"; $title = $data if $state eq 'name'; } # this is called when an end tag is found sub end() { my ( $parser, $name ) = @_; $name = lc($name); if ( $endTags{$name} ) { $_ = "$endTags{$name}"; s/_TITLE_/$title/; print; } } # initialize parser my $xp = new XML::Parser(); # set callback functions $xp->setHandlers( Start => \&start, End => \&end, Char => \&cdata ); # parse XML $xp->parsefile($file); # flush output. print "\n"; # end exit(0);