#!/usr/bin/perl -w # this script generates an HTML FAQ from an the XML version use strict; use XML::Twig; my $file= shift || die "usage twig_faq "; # those 2 globals are grabed from the xml header and used to # generate the html header my $g_title; # title my $g_version; # version my $qnb=0; # question index my $toc; # the element containing the ToC my $t= XML::Twig->new( twig_handlers => { title => \&title, date => \&date, header => \&header, credits => \§ion, overview => \§ion, 'q' => \&q, question => \&question, answer => \&answer, code => sub { $_->set_gi( 'pre'); $_->remove_cdata; }, copyright => \©right, markup => \&markup, }, pretty_print => 'indented', keep_spaces_in => ['pre'], empty_tags => 'html', error_context => 2, ); $t->parsefile( $file); my $faq= $t->root; $faq->set_gi( 'html'); $faq->insert( 'body'); # create the html header my $title= new XML::Twig::Elt( 'title', "$g_title - version $g_version"); my $html_header= new XML::Twig::Elt( 'header', $title); $html_header->paste( $faq); $faq->print; exit; sub title { my( $t, $title)= @_; $title->set_gi( 'h1'); # title -> h1 $g_title= $title->text; # store the title } sub date { my( $t, $date)= @_; my $version= $date->prev_sibling( 'version'); $version->set_gi( 'h2'); # version -> h2 $g_version= $version->text; # store the version $version->prefix( 'Version '); $version->suffix( ' - ' . $date->text); $date->cut; } sub author { my( $t, $author)= @_; } sub header { my( $t, $header)= @_; $header->set_gi( 'center'); # center the whole header # add the appropriate text around the authors my @author= $header->children( 'author'); my $first_author= shift @author; if( $first_author) { my $by= new XML::Twig::Elt( '#PCDATA', "by "); $by->paste( 'before', $first_author); $first_author->set_gi( 'b'); # author -> b } my $last_author= pop @author; if( $last_author) { my $and= new XML::Twig::Elt( '#PCDATA', " and "); $and->paste( 'before', $last_author); $last_author->set_gi( 'b'); # author -> b } foreach my $author( @author) { my $comma= new XML::Twig::Elt( '#PCDATA', ", "); $comma->paste( 'before', $author); $author->set_gi( 'b'); # author -> b } } sub section { my( $t, $section)= @_; # add an
my $hr= new XML::Twig::Elt( 'hr'); $hr->paste( $section); # add the title my $section_title= ucfirst( $section->gi); my $title= new XML::Twig::Elt( 'h2', $section_title); $title->paste( 'after', $hr); $section->set_gi( 'div'); } sub q { my( $t, $q)= @_; $q->erase; } sub question { my( $t, $question)= @_; # add an
my $hr= new XML::Twig::Elt( 'hr'); $hr->paste( 'before', $question); # create the ToC if need be unless( $toc) { my $q= $question->parent; $toc= XML::Twig::Elt->new( 'ul'); $toc->paste( 'before', $q); my $toc_title= XML::Twig::Elt->new( 'h2', 'Content'); $toc_title->paste( 'before', $toc); my $hr= XML::Twig::Elt->new( 'hr'); $hr->paste( 'before', $toc_title); } # add the question number $qnb++; my $target= "Q$qnb"; my $number= XML::Twig::Elt->new( '#PCDATA', "$target: "); # add a target element (so the ToC can link there) my $a= XML::Twig::Elt->new( 'a'); $a->set_att( name => $target); $a->paste( 'before', $question); # create the toc entry generate_toc_entry( $target, $question->first_child_text( 'p') || $question->text); if( my $p= $question->first_child( 'p')) { $p->set_gi( 'h2'); $question->erase; $number->paste( first_child => $p) } else { $question->set_gi( 'h2'); $number->paste( $question); } } sub answer { my( $t, $answer)= @_; # replace the answer by a 'p' # unless the first child is already a 'p' my $first_child= $answer->first_child; my $prefix= XML::Twig::Elt->new( b => "Answer: "); if( $first_child->gi eq 'p') { $answer->erase; $prefix->paste( first_child => $first_child); } else { $answer->set_gi( 'p'); $prefix->paste( first_child => $answer); } } sub copyright { my( $t, $copyright)= @_; # add an
my $hr= new XML::Twig::Elt( 'hr'); $hr->paste( 'before', $copyright); $copyright->set_gi( 'p'); } sub generate_toc_entry { my( $target, $text)= @_; my $entry= XML::Twig::Elt->parse( "
  • $text
  • "); $entry->paste( 'last_child', $toc); } # replace markup by pre and replace the cdata children by pcdata sub markup { my( $t, $markup)= @_; # replace the CDATA in markup by PCDATA with the same text $markup->set_gi( 'pre'); $markup->remove_cdata; }