Gestione degli avvisi di seminario tramite XML

Attenzione: questo documento risale al 2002 e non è stato più aggiornato. Nella sostanza è ancora valido ma sia il codice HTML usato nel documento stesso, che alcuni link e soprattutto alcuni concetti espressi sono superati. Usare con cautela!






Descrizione generale dell'applicazione

Il sistema di gestione degli avvisi di seminario si presta naturalmente ad essere realizzato utilizzando la tecnologia XML, in quanto si tratta di replicare le stesse informazioni in diversi formati di presentazione. Quindi una volta raccolte le informazioni relative al calendario delle conferenze in un apposito documento XML tutti gli avvisi nei diversi formati vengono generati automaticamente tramite dei fogli di stile secondo le specifiche del linguaggio XSLT. L'applicazione illustrata pur essendo estremamente semplice consente di mettere a fuoco numerosi aspetti di XML, come verra' mostrato in dettaglio nel seguito di questo documento. Goldfarb e Prescod nel loro testo "The XML Handbook" dividono tutte le applicazioni XML in due grandi categorie:
MOM
Message Oriented Middleware
POP
Presentation Oriented Publishing
Schematizzando al massimo i documenti di tipo MOM sono generati da macchine per essere processati automaticamente da altre macchine. Interscambio di documenti tra applicazioni diverse e protocolli di comunicazione sono le applicazioni tipiche. I documenti di tipo POP invece sono creati da essenzialmente per la presentazione dello stesso contenuto su media diversi. Le applicazioni reali si collocano generalmente in un qualche punto intermedio tra i due estremi dello spettro XML. La presente applicazione sembra essere, al contrario, esclusivamente di tipo POP , considerato che l'obbiettivo e' di presentare lo stesso avviso in diversi formati, a seconda del medium utilizzato.



                                            +--------------+  
  +----------+                              |              |  
  |          |        +------------+        | Vari         |  
  | lista    |        |            |        | documenti    |  
  | dei      |     \  |            |      \ | in formato   |  
  | seminari |------\ |"Processori"|-------\| latex, HTML  |  
  | del mese |------/ |    XML     |-------/| o plain text |  
  | in       |     /  |            |      / | tutti        |  
  | formato  |        |            |        | derivati     |  
  | XML      |        |            |        | dal "master" |  
  |          |        +------------+        | XML          |  
  +----------+                              |              |  
                                            +--------------+  


                            Figura 1
La Figura 1 schematizza il processo. L'utente crea un documento XML che viene processato in vari modi da applicazioni XML aware ciascuna delle quali genera un nuovo documento che a seconda del formato può essere stampato su carta, visualizzato da un browser o inviato via posta elettronica. Nella figura sono mostrati tre blocchi che corrispondono alle tre fasi di creazione , elaborazione e presentazione del processo. Le prime due fasi contengono elementi specifici di tecnologia XML. Per quanto riguarda la creazione di un documento XML, si deve innanzitutto creare il file DTD , ovvero il Document Type Definition, che serve a definire la grammatica e il vocabolario del nostro linguaggio di markup. Dopodiche' per la creazione dei singoli documenti XML si può usare un editor XML che guida l'utente nella creazione del file garantendo la conformita' al DTD utilizzato. Nella fase di elaborazione e' stato utilizzato un processore XSLT che trasforma i documenti XML in base alle dichiarazioni contenute in un foglio di stile. Dove il processore XSLT non era sufficiente sono state scritte delle procedure ad hoc utilizzando un modulo Perl per il parsing di documenti XML. I documenti derivati, nei vari formati latex, HTML e testo sono stati trattati con le consuete procedure.

Il DTD

La maggior parte dei documenti XML appartengono ad un tipo, e all'inizio del documento si trova la dichiarazione "di appartenenza"
( <!DOCTYPE lista_seminari ...> ). Un tipo di documento può essere creato ex-novo oppure ci si può riferire a tipi che gia' esistono. Per applicazioni particolari occorre creare il proprio tipo. E' evidente che la fase di creazione del tipo di documento, cioè la redazione del file DTD e' cruciale, in quanto determina la struttura dei nostri file XML che si rifaranno a questo tipo. Corrisponde in qualche modo alla progettazione delle tabelle e dei campi di un archivio.


<!ELEMENT lista_seminari (seminario)*>


<!ATTLIST lista_seminari 
anno CDATA #REQUIRED
mese (Gennaio|Febbraio|Marzo|Aprile|Maggio|Giugno|\
Luglio|Agosto|Settembre|Ottobre|Novembre|Dicembre) #REQUIRED >


<!ELEMENT seminario (luogo,autore,istituto,titolo,note?,abstract,responsabile)>


<!ATTLIST seminario tipo (normale|specialistico|dottorato) "normale" >
<!ATTLIST seminario giorno_settimana (Lunedi|Martedi|Mercoledi|\
Giovedi|Venerdi|Sabato|Domenica) #REQUIRED>
<!ATTLIST seminario giorno_mese CDATA #REQUIRED>
<!ATTLIST seminario ora CDATA #REQUIRED>
<!ELEMENT luogo (#PCDATA)>
<!ELEMENT autore (#PCDATA)>
<!ELEMENT istituto (#PCDATA)>
<!ELEMENT titolo (#PCDATA)>
<!ELEMENT note (#PCDATA)>
<!ELEMENT responsabile EMPTY>
<!ATTLIST responsabile nome CDATA #REQUIRED>
<!ELEMENT abstract EMPTY>
<!ATTLIST abstract url CDATA #REQUIRED>

           
                            Figura 2
In figura 2 si riporta il DTD usato per l'applicazione. Per i dettagli della sintassi del DTD consiglio di leggere il documento Introduction to XML for Web developers (3rd part-DTD) . Il file si chiama lista_seminari.dtd e la URL a questo associata viene utizzata nei file XML che si rifanno a questo tipo. Si dice che un documento XML e' valido quando e' conforme alle specifiche del DTD associato. Nel DTD si cerca di definire le caratteristiche del file XML nella maniera più stringente possibile rispetto alle proprie esigenze, in modo che i vari applicativi che lo devono processare si trovino a lavorare con un documento con certe caratteristiche precise. Purtroppo la sintassi del DTD non e' sufficientemente espressiva a questo scopo. Per esempio non possibile specificare che l'attributo anno dell'elemento lista_seminari sia un numero a quattro cifre compreso in un certo range. L'utente per l'attributo anno potrebbe tranquillamente inserire un valore come millenovecentonovantanove , se non addirittura una stringa qualunque. Il documento XML risulterebbe ugualmente valido, ma l'applicazione che processa il file non troverebbe il valore che si aspetta di trovare. Per ovviare agli inconvenienti della sintassi dei DTD il W3C si sta orientando verso l'adozione di un altro strumento che si chiama XML Schema . In fase di messa a punto del file DTD e' molto utile avere a disposizione un cosiddetto "XML validator", ovvero un programma che controlla che l'aderenza di un documento XML al DTD associato. I validator esistono appunto per validare i documenti XML a partire da un DTD che si considera "definitivo". Tuttavia si può fare anche l'operazione inversa. Si crea un documento XML e si verifica se certi costrutti sono o no aderenti al DTD che stiamo costruendo. Se per esempio vogliamo proibire un certo costrutto, lo si mette nel file XML e si verifica che il DTD sia fatto in modo da tale da non consentire la validazione del documento. Viceversa nel caso che si voglia ammettere o forzare un certo costrutto. Un XML validator molto comodo e' disponibile on line. Basta passargli la URL del documento e si ottiene un responso in pochi attimi.

Il file XML



<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE lista_seminari SYSTEM "http://www.arcetri.astro.it/Seminari/lista_seminari.dtd" >

<lista_seminari anno="2000" mese="Dicembre">

  <seminario giorno_mese="1" giorno_settimana="Venerdi" ora="10" tipo="dottorato">
    <luogo>Aula A</luogo>
    <autore>Gianni Corti</autore>
    <istituto>Dipartimento di Astronomia e Scienza dello Spazio, Firenze</istituto>
    <titolo>Il polarimetro UV di ASCE</titolo>
    <abstract url="corti.abs"/>
    <responsabile nome="XYZ"/>
  </seminario>

  <seminario giorno_mese="1" giorno_settimana="Venerdi" ora="11" tipo="dottorato">
    <luogo>Aula A</luogo>
    <autore>Roberto Gilli</autore>
    <istituto>Dipartimento di Astronomia e Scienza dello Spazio, Firenze</istituto>
    <titolo>Modelli di sintesi del fondo cosmico di raggi X tramite i Nuclei Galattici Attivi</titolo>
    <abstract url="gilli.abs"/>
    <responsabile nome="XYZ"/>
  </seminario>

  <seminario giorno_mese="7" giorno_settimana="Giovedi" ora="11.30" >
    <luogo>Aula A</luogo>
    <autore>Franca D'Antona</autore>
    <istituto>Osservatorio Astronomico di Roma</istituto>
    <titolo>Problemi aperti dell'evoluzione stellare: dalle Brown Dwarfs alle AGBs</titolo>
    <abstract url="dantona.abs"/>
    <responsabile nome="XYZ"/>
  </seminario>

</lista_seminari>


                              Figura 3

La figura 3 riporta un documento XML che aderisce al DTD lista_seminari . E' facile verificare la validita' del documento data la sua estrema semplicita'. Un altro modo per verificare la validita' di un documento è di editarlo con un editor XML che si chiama xeena. xeena infatti va lanciato con il riferimento del file ".dtd", in modo che possa verificare la validita' del file xml sia in apertura che durante l'editing. xeena evidenzia le parti del documento che non si attengono alle specifiche.

Trasformare XML con XSL(T)

I documenti XML possono essere trasformati in altri documenti XML o in documenti che hanno un formato NON XML adatto alla presentazione del contenuto del documento stesso. Queste trasformazioni vengono generate da un apposito programma "processore" che applica le regole definite in un foglio di stile associato. Il foglio di stile associato e' scritto in XSL, ovvero eXtensible Stylesheet Language . Il linguaggio XSL consta di due parti: E' importante rendersi conto che XSL in generale si occupa sia della trasformazione (XSLT) di un documento XML che della sua presentazione (rendition) in un formato specifico (FO) L'aspetto che probabilmente può ingenerare un po' di confusione e' dato dal fatto che la trasformazione più diffusa, cioè da XML a HTML, viene intesa come rendition mentre in realta' si tratta proprio di una trasformazione da un formato XML ad un altro. Praticamente, se voglio generare un documento HTML a partire dal mio documento XML devo scrivere un foglio di stile usando XSL e darlo in pasto ad un processore XSL come per esempio xalan dell'Apache Foundation. L'argomento XSL e' molto più complesso di quanto possa sembrare da quanto detto. Per gli approfondimenti si rimanda ai link elencati nella sezione Resources. Qui mi limitero' a mostrare il file di stile usato per la conversione da XML a HTML, anche se, proprio grazie alla complessita' di cui sopra, XSLT può fare molto più che semplicemente trasformare un documento XML in uno HTML!


<?xml version="1.0" ?>

 
<xsl:stylesheet
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
        xmlns:html="http://www.w3.org/TR/REC-html40" >

  <xsl:template match="lista_seminari">
     <HTML>
     <HEAD>
        <TITLE>
           Seminari <xsl:value-of select="@mese" />  <xsl:value-of select="@anno" />
        </TITLE>
     </HEAD>
     <BODY BACKGROUND="fond-b.jpg" TEXT="darkgreen">
     <HR SIZE="3"/>
     <BR/>
     <H1 ALIGN="CENTER">
        <FONT COLOR="brown">
        Seminari 
        <xsl:value-of select="@mese" />
        <xsl:text>    </xsl:text>
        <xsl:value-of select="@anno" />
        </FONT>
     </H1>
     <HR SIZE="3"/>
     <BR/>
     <BR/>
     <BR/>
     <xsl:apply-templates select="seminario" />
     </BODY>
     </HTML>
  </xsl:template>

  <xsl:template match="seminario">
     <BR/>
     <CENTER>
     <FONT SIZE="+1">
     <STRONG>
     <xsl:value-of select="@giorno_settimana"/>
     <xsl:text> </xsl:text>
     <xsl:value-of select="@giorno_mese"/>
     ore <xsl:value-of select="@ora"/><BR/>
     </STRONG>
     </FONT>
     <xsl:value-of select="luogo"/><BR/>
     <xsl:if test="@tipo='specialistico'">
         (Seminario specialistico)<BR/>     
     </xsl:if>
     <xsl:if test="@tipo='dottorato'">
         (Seminario di Dottorato)<BR/>     
     </xsl:if>
     </CENTER>
     <FONT SIZE="+1">
     <xsl:value-of select="autore"/><BR/>
     </FONT>
     <EM>
     <xsl:value-of select="istituto"/><BR/>
     </EM>
     <A HREF="/cgi-bin/show_abstract.pl?file={abstract/@url};title={titolo};author={autore}">
     <FONT SIZE="+1" COLOR="brown">
     <xsl:value-of select="titolo"/>
     </FONT><BR/>
     </A>
     <EM>
     Referente locale: <xsl:value-of select="responsabile/@nome"/><BR/>
     </EM>
     <P/>
     <BR/>
     <BR/>
     <BR/>
     <BR/>
  </xsl:template> 


</xsl:stylesheet>

                              Figura 4

La figura 4 contiene il file di stile per convertire da XML a HTML. Nel file di stile vengono definiti dei costrutti base detti template rules . Durante la trasformazione ogni parte del documento XML e' processato in base a qualche template rule, sia esplicita che implicita ( built-in nel processore XSLT). Ogni template rule consta di due parti : pattern e template . Il pattern definisce quale elemento del documento XML deve essere processato dalla template rule. Il template descrive il costrutto XML da generare quando uno o più elementi XML combaciano con il pattern. I pattern sono espressi in XPath , ovvero il linguaggio pensato appositamente per individuare porzioni di un documento XML. (Consultare la sezione Resources per i dettagli su XPATH). XSLT è un linguaggio dichiarativo nel senso che si devono solo dichiarare le regole e non l'ordine di svolgimento del programma. Una volta definito il file di stile, il comando per generara la trasformazioni tramite xalan e':

java org.apache.xalan.xslt.Process -IN seminari.xml -OUT seminari.html -XSL lista_seminari2html.xsl -HTML
Per quanto riguarda la trasformazione in un file "LaTeX", il foglio di stile è anche più semplice in quanto dal punto di vista di XML si tratta di un puro file di testo. La figura 5 comunque riporta per comodita' anche questo foglio di stile.

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

  <xsl:template match="lista_seminari">
     \documentclass[italian]{article}
     \usepackage{babel}
     \setlength{\parindent}{0pt}
     \setlength{\oddsidemargin}{0pt}
     \setlength{\textwidth}{18cm}
     \setlength{\textheight}{26cm}
     \hoffset=-0.5cm
     \begin{document}
     \pagestyle{empty}
     \hbox{}
     \vskip -3.5cm
     \normalsize{
     {\scshape Osservatorio Astrofisico di Arcetri}\\
     Largo E. Fermi, 5\\
     50125 Firenze\\
     Tel: 055 27521 Fax: 055 220039\\
     }
     
     \vskip 0.4cm
     \large
     \begin{center}\huge{\bfseries Seminari <xsl:value-of select="@mese" />
        <xsl:text>    </xsl:text>
        <xsl:value-of select="@anno" />}\end{center}
        \vskip 1.0cm
     \begin{tabular}{p{7cm}p{1cm}p{8cm}}
     <xsl:apply-templates select="seminario" />
     \end{tabular}
     \end{document}
  </xsl:template>


  <xsl:template match="seminario">
     {\bfseries
     <xsl:value-of select="@giorno_settimana"/> 
     \hskip 3pt 
     <xsl:value-of select="@giorno_mese"/> }
     \ ore <xsl:value-of select="@ora"/> 
     \ <xsl:value-of select="luogo"/>
     &
     &
     {\bfseries
     <xsl:value-of select="autore"/>}\\
     &
     &
     <xsl:value-of select="istituto"/>\\


     <xsl:if test="@tipo='specialistico'">
          (Seminario specialistico)
     </xsl:if>
     <xsl:if test="@tipo='dottorato'">
          (Seminario di Dottorato)
     </xsl:if>

     &
     &
     {\itshape <xsl:value-of select="titolo"/>}\\

     &\\
     &\\
  </xsl:template> 


</xsl:stylesheet>


                                 Figura 5
In questo caso il comando per xalan e':

java org.apache.xalan.xslt.Process -IN seminari.xml -OUT seminari.tex -XSL lista_seminari2tex.xsl -TEXT
Da notare lo switch "-TEXT" che comunica al processore che l'output e' puro testo e quindi non scrive l'intestazione <?xml...?> e non pretende che l'output sia un file XML well-formed. La trasformazione in LaTeX pone un problema complicato che non sono riuscito a risolvere con XSLT. LaTeX usa per i caratteri accentati delle sequenze particolari, per esempio è si scrive \`e in LaTeX. Per ottenere i caratteri accentati dovrei quindi riuscire a specificare una regola che mi intercetti, all'interno di nodo testo , una entity particolare, tipo &egrave; , e la trasformi nella sequenza richiesta da LaTeX.

Parsing di un documento XML

Il parsing, come ho gia' detto, consiste nello scomporre un documento nelle sue componenti sintattiche. L'applicazione una volta effettuato il parsing ha il completo controllo di tutti gli elementi del documento per ulteriori elaborazioni. Ovviamente anche XSLT ha bisogno di fare il parsing di un documento, tant'e' vero che xalan utilizza in gran parte le classi di xerces che e' il parser di Apache foundation. In generale si deve ricorrere al parsing di un documento quando non si riesce ad ottenere il risultato voluto con XSLT. Per quanto riguarda questa applicazione, per esempio, ho usato un XML::Parser perché non riuscivo, con XSLT, a creare un file separato per ogni singolo seminario, cosa che invece è ovviamente banale da una procedura Perl. Un'ultima parola riguarda Java. La maggior parte degli sviluppatori quando parla di parsing di XML si riferisce a qualche parser Java (ce ne sono diversi in circolazione, fra cui xerces, che ho gia' citato). Credo tuttavia che per una piccola applicazione come questa Perl abbia dei vantaggi, tra cui la maggiore semplicita' di sviluppo e la maggiore velocita' di esecuzione. Probabilmente applicazioni di più vasto respiro devono invece ricorrere ad un linguaggio più strutturato come e' Java. Ecco lo script Perl che fa il parsing di un documento di tipo "lista_seminari" e crea un file di testo per ogni seminario da inviare come mail agli utenti interessati.

#!/usr/local/bin/perl

use XML::Parser;

$|=1;
$xmlfile=pop;

if ( ! $xmlfile ) {
   print "Usage: process.pl file.xml\n";
   exit;
}


my ($current_element, $giorno_settimana, $giorno, 
    $autore, $istituto, $ora, $tipo, $abstract,
    $semfile, $absfile, $tmp, $abstracts_dir);


$l1=<DATA>;
$l2=<DATA>;
$header=$l1 . $l2 . $l1;
$line=$l1;
$tmp = "./tmp/";
$abstracts_dir="./abstracts/";


%mesi2num = qw( Gennaio 01 Febbraio 02  Marzo 03 Aprile 04
              Maggio 05 Giugno 06 Luglio 07 Agosto 08
              Settembre 09 Ottobre 10 Novembre 11
              Dicembre 12);

$p2 = new XML::Parser(Handlers => {Start => \&handle_start,
                                   End   => \&handle_end,
                                   Char  => \&handle_char});


$p2->parsefile($xmlfile);
exit;



sub handle_start {
  my ($pkg,$element,%attr) = @_;

  $current_element = $element;
  if ( $element =~ /lista_seminari/i ) {
      $anno=$attr{anno};
      $mese=$attr{mese};
      if (! -e $tmp ) {
          mkdir $tmp, 0755 ;
      }
      system "rm -f $tmp/mail_$mesi2num{$mese}_\*";
  } elsif ( $element =~ /seminario/i ) {
      $tipo=$attr{tipo};
      $ora=$attr{ora};
      $giorno=sprintf("%02d",$attr{giorno_mese});
      $giorno_settimana=$attr{giorno_settimana};
      $mailfile= "$tmp/mail_" . $mesi2num{$mese} . "_" .  $giorno;
      open (OUT, ">>$mailfile");
      print OUT $header,"\n\n";
  } elsif ( $element =~ /abstract/i) {
      $abs_url="$abstracts_dir/$attr{url}";
      $abstract = "";
      open (ABSIN, $abs_url);
      while (<ABSIN>) {
         $abstract .= $_ unless /^#/;
      }
      close ABSIN;
  } 
}



sub handle_end {
  my ($pkg,$element,%attr) = @_;

  if ( $element =~ /seminario/i ) {
      print OUT " " x  22;
      print OUT "$giorno_settimana $giorno $mese - ";
      print OUT "ore $ora $luogo\n";
      if (  $tipo =~ /\w+/ ) {
         print OUT " " x 28;
         print OUT "(Seminario $tipo)\n";
      }
      print OUT "\n\n";
      print OUT $line,"\n";
      print OUT $autore,"\n";
      print OUT $titolo,"\n";
      print OUT $abstract;


      close (OUT);

  }
}


sub handle_char {
   $text = $_[1];
   if ( $current_element =~ /autore/i ) {
      ($text !~ /^\s*$/) && ($autore = $text);
   } elsif ( $current_element =~ /titolo/i ) {
      ($text !~ /^\s*$/) && ($titolo = $text);
   } elsif ( $current_element =~ /istituto/i ) {
      ($text !~ /^\s*$/) && ($istituto = $text);
   } elsif ( $current_element =~ /luogo/i ) {
      ($text !~ /^\s*$/) && ($luogo = $text);
   }
}

__DATA__
--------------------------------------------------------------------------
! SEMINARIO ! SEMINARIO ! SEMINARIO ! SEMINARIO ! SEMINARIO ! SEMINARIO !



                         Figura 6
                          

Autore: Roberto Baglioni
Firenze, 03 Feb 2016 - 11:08


Resources

Introduction to XML for Web developers Introduzione molto chiara su cosa e' XML - sintassi e strumenti - di Selena Sol
XML in ten points XML per principianti, comunque il documento e' di una fonte autorevole: il W3C
xml.apache.org La home page di tutte le tecnologie XML by Apache
Introduction to XML for Web developers (3rd part-DTD) La terza parte del corso introduttivo su XML di Selena Sol. Questa parte tratta il DTD
Document Type Definition - Tutorial Un'altra introduzione alla sintassi di DTD
The annotated XML Specification Uno dei documenti fondamentali su XML, scritto da Tim Bray che e' uno dei padri di XML - Molto tecnico
XML Resources and validator XML Resources and validator
XML validator Un form a cui si può passare la URL di un documento XML e si ottiene un OK se il documento e' valido, oppure una lista degli errori con un po' di diagnostica.
Extensible Stylesheet Language La pagina ufficiale su XSL del W3 Consortium.
What is XSLT Un'introduzione completa a XSLT
Using XSL Formatting Objects Un tutorial sui Formatting Objects
xalan Il processore XSL della Apache foundation
HTML 4.01 Specification Le specifiche DTD del linguaggio HTML
XPath XML Path Language secondo le specifiche ufficiali del W3
XSL Transformation and XML Path Language Un ottimo tutorial su XSLT e XPATH
XPath Un altro tutorial su XPath
xerces Il Java Parser per XML di Apache
XML::Parser Un Parser XML in Perl scritto da Clark Cooper
Seminari ad Arcetri La pagina generata dal file XML!
L'ABC di XML Un mio talk indroduttivo su XML