Usare XML e XSLT per costruire LinuxFocus.org(/Olanda)

ArticleCategory: [Artikel Kategorie]

Applications

AuthorImage:[Bild des Autors]

[Photo of the Author]

TranslationInfo:[Author and translation history]

original in en Egon Willighagen

en to en Lorne Bailey

en to it AlessandroPellizzari 

AboutTheAuthor:[Über den Autor]

Conseguirà il master quest'anno e inizierà il suo dottorato di ricerca sulla chemometria. Gli piace ancora molto il basket, mentre lavora a LinuxFocus e a Linux in generale.

Abstract:[Zusammenfassung]

Questo articolo contiene la la presentazione fatta al Libre Software Meeting di Bordeaux di luglio. Spiega il database XML usato per la generazione automatica del sito di LinuxFocus(/Olanda).

ArticleIllustration:[Titelbild des Artikels]

[Illustration]

ArticleBody:[Der eigentliche Artikel]

Introduzione

Il sistema usato per la gestione dei documenti e delle traduzioni nel progetto LinuxFocus consiste in diversi files ASCII, compresi resdb.txt, issuedb.txt e maindb.txt. Questi file hanno un formato fisso e vengono usati per generare le pagine web. Di contro, sono difficili da estendere, e la natura separata dei dati rende difficile gestire tutte le informazioni disponibili per un articolo.

LinuxFocus non generava automaticamente molto del contenuto delle pagine web quando ho iniziato con il nuovo database. Come editore del team olandese, volevo avere i vari index.html del sito generati in modo automatico. Editare a mano diversi file HTML ogni volta che un nuovo articolo veniva tradotto richiedeva un grosso sforzo e introduceva diversi link spezzati. Quindi volevo un nuovo sistema a cui poter aggiungere facilmente le informazioni, e dal quale potessi facilmente generare le pagine indice per il sito. Ho iniziato a lavorarci più o meno nell'estate del 2000.

La scelta dell'XML è stata un po' arbitraria. Ho ricevuto suggerimenti di usare un database relazionale, ma ero esperto nell'XML e preferivo un sistema basato su file di testo. È saltata fuori subito la necessità di avere un nuovo schema di numerazione, perché il database potesse usare un tipo di ID invece dei due o tre schemi allora usati. Guido Socher ha rifatto completamente la numerazione, ed è stato un lavoraccio (i miei ringraziamenti!).

La Document Type Definition (DTD) era già in fase di sviluppo, e una piccola parte dei contenuti era nel database per i test. Con il nuovo sistema di numerazione, il momento era quello giusto per riempire il database di contenuti. Dopo aver aggiunto una ventina di articoli, divenne chiaro che era un progetto enorme. Era possibile scrivere script che usassero i vecchi file, ma non erano disponibili tutte le informazioni inseribili nel nuovo database e, come già detto, le informazioni disponibili erano sparse per diversi file. Fortunatamente Floris Lambrechts intervenne, e devo ringraziarlo moltissimo per aver aggiunto la gran parte del contenuto del database. Senza il suo aiuto il sistema non sarebbe come è oggi.

Assiema al nuovo formato venne anche la possibilità di aggiungere nuove informazioni. E durante lo scorso anni sono stati aggiunti diversi tipi di dati al database. Le prime aggiunte sono state una tabella degli autori, dei traduttori, degli editori e di altre persone coinvolte in LinuxFocus, e le posizioni dei file. Il motivo dell'ultima aggiunta è una diversità nei nomi dei file usati dall'inizio di LinuxFocus. Durante la rinumerazione è stato tutto ridotto a due schemi. Alcuni file usavano i Server-side Include e quindi avevano estensione .shtml, mentre i vecchi articoli avevano estensione .html. Il tag <file> può essere usato per superare un default. (Il default attuale e` di usare il formato "article" + numero articolo + ".shtml". Questo può includere un ".meta" opzionale nel caso il file sia nel meta-formato di LinuxFocus.)

Ora che il database ha raggiunto la massa critica, finalmente ho potuto iniziare a verificare le prestazioni del software che stavo scrivendo. Gli attuali fogli di stile XSLT non sono quelli della prima implementazione. Sono stati preceduti da codice Perl. Ma con la crescita del database, le prestazioni sono diventate importanti. Il primo tentativi semplicemente non era abbastanza buono. Ma prima di descrivere gli strumenti descrivero` il formato.

La Document Type Definition

XML, prima di tutto, è una sintassi per la specifica di linguaggi di markup. XML definisce come dovrebbe apparire il markup. La sintassi descrive la sequenza di caratteri consentita nel documenti XML "ben formati". Dichiara che un documento ha un elemento radice (root) e che un elemento consiste di un tag iniziale, il contenuto (testo, elementi figli o entrambi), e un tag finale. I tag consistono in un carattere "<" seguito da un nome e un carattere ">" alla fine. Un tag finale deve avere un "/" subito prima del nome. I tag vuoti, come il <BR> dell'HTML, prendono un "/" dopo il nome. Un tag iniziale può contenere degli attributi, e anche questi hanno una sintassi specifica. I tag XML somigliano ai seguenti:

<greeting>Ciao, mondo!</greeting>
o per un tag vuoto
<br/>

A parte la sintassi, i linguaggi contengono anche una semantica. Essa descrive come alcuni elementi si rapportino con altri. La semantica dell'HTML dichiara che <body> dovrebbe essere contenuto in <html> e non viceversa. La semantica descrive anche che <img> è un tag vuoto, come il tag <br>. Se questa semantica viene data in una notazione formale, può essere analizzata da un programma e usata per validare un documento. Una di queste notazioni formali è chiamata Document Type Definition, o DTD. Se un documento supera la validazione viene chiamato valido. Dovete stare attenti con XML perchè la sua validazione è molto restrittiva.

Ora che sappiamo cosa sia una DTD, diamo un'occhiata alla DTD del database XML di LinuxFocus. Per alcune delle specifiche diamo un esempio. Esaminando questi esempi vi farete un'idea del modo in cui le informazioni sono contenute nel database XML di LinuxFocus.

<database>

L'elemento radice del database XMl di LinuxFocus o di una delle sue estensioni/localizzazioni, è l'elemento <database>.

<!ELEMENT database    (themes?, persons?, issues?, articles?)>
    

Innanzitutto notate che "?" significa che l'elemento figlio può apparire zero o una volte. Perciò il database potrà contenere informazioni sui temi, sulle persone, sulle uscite e sugli articoli di LinuxFocus. Visto che è abbastanza semplice, procediamo con un esempio più interessante.

<themes>

I temi (themes) sono contenuti in un elemento <themes> che è un elemento figlio di <database>. Ogni tema ha un ID univoco, un titolo e opzionalmente una prologo e un'immagine.

<!ELEMENT themes      (theme+)>
  <!ELEMENT theme       (title*, desc?, img?)>
    <!ELEMENT title       (#PCDATA)>
    <!ELEMENT desc       (#PCDATA)>
    <!ELEMENT img         (EMPTY)>
    

Alcuni elementi devono avere degli attributi. Questi vengono anche specificati nella DTD. Ogni contenuto di tipo testuale è racchiuso in un elemento con l'attributo xml:lang. Il valore dell'attributo può essere un token qualsiasi conforme al ISO 3166 standard per i codici regionali. Per esempio "en", "fr", e "nl". Sia l'id che l'attributo xml:lang vengono specificati nelle direttive originarie XML e sono parte della sintassi XML.

<!ATTLIST theme       id            ID            #REQUIRED>
<!ATTLIST title       xml:lang      NMTOKEN       #REQUIRED>
<!ATTLIST desc        xml:lang      NMTOKEN       #REQUIRED>
<!ATTLIST img         src           CDATA         #REQUIRED>
    

Un database di esempio potrebbe apparire come:

<database>
  <themes>
    <theme id="hw">
      <title xml:lang="en">Hardware</title>
      <img src="Hardware.jpg"/>
    <theme>
  <themes>
</database>
    

<issues>

Le uscite sono contenute nell'elemento <issues>. Come i temi, anche le uscite hanno un ID univoco.

<!ELEMENT issues      (issue+)>
  <!ELEMENT issue       (title+, published?, file*)>
    <!ELEMENT title       (#PCDATA)>
    <!ELEMENT published   (EMPTY)>
    <!ELEMENT file        (#PCDATA)>
    

L'elemento <published> contrassegna le uscite pubblicate. La prossima uscita e la pseudo-uscita SomeLanguage2Eng non hanno questo elemento. L'elemento <title> ha anch'esso l'atributo @xml:lang. L'elemento <file> definisce la directory in cui è posizionata l'uscita. Non deve puntare all'index.html, perché è usata per determinare le posizioni dei file.

Un esempio (notate che usiamo l'attributo @code per l'ordinamento):

    <issue id="ToBeWritten" code="999996">
      <title xml:lang="en">Not yet written articles</title>
    </issue>
    <issue id="September2001" code="200109">
      <title xml:lang="en">September2001</title>
    </issue>

<persons>

Le informazioni sugli autori e i traduttori vengono immagazzinate in un elemento <person>. Ogni persona ha un ID univoco.

 <!ELEMENT persons (person+)>
 <!ELEMENT person 
              ((name|email)*,(homepage|nickname|desc|team)*)>
 <!ELEMENT email (#PCDATA)>
 <!ELEMENT name (#PCDATA)>
 <!ELEMENT homepage (#PCDATA)>
 <!ELEMENT nickname (#PCDATA)>
 <!ELEMENT desc (#PCDATA|%html-els;)*>
 <!ELEMENT team EMPTY>
    

Ogni persona può avere le seguenti informazioni: un nome, un indirizzo email (o più di uno), la/le homepage e i nickname. Se la persona fa anche parte di un team di traduttori, aggiungiamo un elemento <team>. Per esempio, la linea seguente, nell'elemento <person> definisce che Floris appartiene al team olandese <team xml:lang="nl"/>. Infine, ogni persona ha una descrizione, che può contenere altri link sul web.

Ad esempio:

    <person id="nl-ew">
      <name>Egon Willighagen</name>
      <email>egonw@linuxfocus.org</email>
      <team xml:lang="nl"/>
    </person>

<articles>

Gli articoli sono naturalmente la parte più interessante del database.

  <!ELEMENT articles    (article+)>
    <!ELEMENT article     (title+, 
        (file|personref|abstract|issueref|themeref|
         nometa|nohtml|translation|proofread)*)>
      <!ELEMENT abstract    (#PCDATA)>
      <!ELEMENT nohtml      EMPTY>
      <!ELEMENT nometa      EMPTY>
      <!ELEMENT translation 
                   (personref*, (reserved|finished|proofread)*)>
      <!ELEMENT reserved    (#PCDATA)>
      <!ELEMENT finished    (#PCDATA)>
      <!ELEMENT proofread   (personref*, (reserved|finished)*)>
<!ATTLIST article     id            ID            #REQUIRED
                      xml:lang      NMTOKEN       #IMPLIED
                      type          (article|coverpage)
                                                  "article"
                      next          IDREF         #IMPLIED
                      prev          IDREF         #IMPLIED>
<!ATTLIST file        xml:lang      NMTOKEN       #REQUIRED
                      type          (target|meta) "target">
<!ATTLIST translation from          NMTOKEN       #REQUIRED
                      to            NMTOKEN       #REQUIRED>

    

Ogni articolo ha almeno un titolo; uno per ogni lingua. L'elemento <file> può essere usato per fornire la posizione del file sia per il formato META che per la versione HTML (vedete l'esempio sotto). Nel caso in cui non ci siano META o HTML, si possono usare gli elementi opzionali <nohtml/> e <nometa/>. Ogni articolo può avere una introduzione. Avere l'introduzione nel database significa che può essere usata per creare le pagine index.

L'elemento <article> ha cinque attributi: l'@ID richiesto, un attributo opzionale xml:lang per denotare il linguaggio nel quale è stato scritto originariamente, un attributo @type usato per le copertine che, per quanto riguarda la traduzione, vengono trattati come articoli. Infine due ulteriori attributi, @next e @prev, usati per abbinare gli articoli in serie.

Un articolo è associato a un'uscitaa e a un tema con gli elementi <issueref> e <themeref>, entrambi con un attributo @href. Il valore di questo attributo deve essere un ID univoco, l'ID dell'uscita o del tema associato.

Un esempio:

<article id="article206" xml:lang="en">
  <title xml:lang="en">Using XML and XSLT to build 
    LinuxFocus.org(/Nederlands)</title>
  <personref href="nl-ew"/>
  <issueref href="ToBeWritten"/>
  <themeref href="appl"/>
  <abstract xml:lang="en">
This article shows you how parts of the Dutch web site of LinuxFocus is 
generated with XSLT tools from the XML database. It compares this with 
the (very) much slower DOM tools in Perl.
  </abstract>
</article>

Un elemento <article> localizzato somiglia al seguente:

<article id="52">
  <title xml:lang="nl">Enlightenment</title>
  <file xml:lang="nl">Nederlands/July1998/article52.html</file>
  <translation from="en" to="nl">
    <personref href="nl-tu"/>
    <reserved>2000-09-06</reserved>
    <finished>2000-10-04</finished>
    <proofread>
      <personref href="nl-fl"/>
      <reserved>2000-10-04</reserved>
      <finished>2000-10-04</finished>
    </proofread>
  </translation>
  <abstract xml:lang="nl">
Enlightenment is een Linux window-manager met
uitgebreide mogelijkheden.  Dit artikel bespreekt
ze, samen met de installatie en de instelling
van E.  Dit alles is niet voor beginners daar
E op het moment nog in beta-stadium
verkeert.
  </abstract>
</article>

Notate che questa traduzione è riservata per la traduzione a una certa data, è stata fatta e anche riletta. In ogni caso la persona che ha fatto il lavoro viene collegata tramite l'elemento <personref>.

Per tutti gli elementi, il miglior tutorial è il database in sé stesso:

Creare automagicamente le pagine web

Una delle ragioni per cui creare questo nuovo formato era di creare automaticamente gli indici sul web. Ora che abbiamo capito (?) il formato del database vediamo come generare le pagine web.

Prima un po' di storia. La prima implementazione usava moduli Perl per interfacciarsi al database. Anche se l'interfaccia era molto semplice l'implementazione era molto lenta. Le informazioni erano contenute in un contenitore XML chiamato Document Object Model (DOM). La maggior parte delle implementazioni di DOM, comunque, sono molto lente, o almeno più lente dell'interfaccia alternativa Simple Application interface for XML (SAX).

Ma se l'obiettivo è solo la creazione di pagine web c'e` una terza migliore alternativa: XSLT. È un linguaggio di trasformazione basato su XML. Esistono molti processori XSLT e sono supportati molti linguaggi di programmazione. Qualche tempo fa c'era un articolo su XML::XSLT, una delle implementaziononi del Perl di XSLT. Dalla pubblicazione di quell'articolo sono emerse altre implementazioni, e ce ne sono alcune che raccomando:

Gli esempi nel resto dell'articolo useranno Sablotron.

Un processore XSLT prendono due file in input. Uno è la sorgente XML da trasformare. L'altro è il foglio di stile XSLT che definisce la trasformazione. Per la generazione delle pagine web di LinuxFocus sono disponibili i seguenti fogli di stile XSLT:

Notate che questi fogli di stile non sono le ultime versioni. Contattate me o uno degli editori del team olandese per avere quelli aggiornati.

Per generare il mainindex.html, per esempio, il team olandese lancia

sabcmd stylesheets/mainindex.xslt db/lfdb.nl.xml > ../mainindex.html

I fogli di stile sanno dove si trova il database principale in inglese, e hanno bisogno solo del database localizzato come input XML. Alcuni fogli hanno bisogno di un parametro aggiuntivo:

sabcmd stylesheets/theme.xslt db/lfdb.nl.xml '$theme=appl' > ../Themes/appl.html

Il file index.html olandese viene altresí generato dal database, ma usa un setup leggermente più complesso. Il file index.html viene generato con lfpagecomposer di Guido Socher da una serie di file di input preprocessati. E tali file di input preprocessati vengono generati da una serie di file .pre come:

<H2>Vorige nummers</H2>
 
<p>Dit zijn de uitgaven van LinuxFocus in het Nederlands:
<ul>
<!-- macro xslt previssues -->
</ul>
<H2>Recent vertaalde artikelen</H2>
< macro xslt recently_translated -->

Questi file sono semplici frammenti HTML con una macro che applica un fogli di stile al database localizzato. Il processo è eseguito con un programma chiamato apply_stylesheets.pl che cerca comandi <!-- macro xslt [stylesheet] --> e analizza il database con tali comandi. Notate che viene omessa l'estensione .xslt. Il nostro Makefile contiene:
%.shtml: %.pre
        @echo "Making $*..."
        @../../xml/bin/apply_stylesheets.pl $*.pre

I file *.shtml risultanti sono usati dallo script lfpagecomposer. I fogli di stile che vengono usati per generare index.html sono: issuetoc.xslt, previssues.xslt e recently_translated.xslt.

Localizzare

Per usare questo sistema per altri linguaggi, avete bisogno di fare le seguenti cose:

  1. localizzare il database XML (come lfdb.nl.xml)
  2. localizzare i fogli di stile

Il secondo passo è un po' arduo. In principio solo il testo in output va localizzato, ma i fogli di stile non hanno proprietà di localizzazione, ancora. È possibile, comunque, e vorrei vederlo implementato.

Raccomando di usare un editor che riconosca le DTD XML. In Emacs potete, per esempio, usare il modo psgml Questo vi darà la possibilità di validare il documento (con nsgmls). Questo aiuta molto ad evitare errori. In Emacs potete anche fare click col tasto destro del mouse per vedere gli elementi e gli attributi che potete inserire in quella specifica posizione nel file XML. (Grazie a Jaime Villate per il suo ottimo intervento alla LSM conference a Bordeaux quest'anno).

Un altro grande aiuto è la localizzazione in olandese del database XML. Se avete problemi potete consultare quel file. Anche se il contenuto è per la maggior parte in olandese potete vedere come gli elementi del database sono organizzati. Se ancora non riuscite, potete sempre scrivermi.

Localizzare i fogli di stile è probabilmente un po' complicato. Il testo è intermediato con comandi XSLT. L'ultimo non dovete toccarlo (a meno che non sappiate cosa state facendo), per preservarne la funzionalità. Prevedo di avere i fogli di stile localizzati in futuro, il che significherebbe che dovreste editare solo un file contenente le traduzioni e nessun comando XSLT, ma questo non è ancora fatto.

Piani per il futuro

OK, questo dovrebbe permettervi di iniziare. La gran parte delle cose le potete tagliare e incollare dai file in olandese. Tutti i file sono FDL e GPL. Per il prossimo anno i miei piani per questo sistema sono: