Äîêóìåíò âçÿò èç êýøà ïîèñêîâîé ìàøèíû. Àäðåñ
îðèãèíàëüíîãî äîêóìåíòà
: http://www.arcetri.astro.it/irlab/doc/library/linux/AppLinux/al149.htm
Äàòà èçìåíåíèÿ: Tue Sep 21 18:08:47 1999 Äàòà èíäåêñèðîâàíèÿ: Sat Dec 22 13:23:53 2007 Êîäèðîâêà: |
Da quanto esposto nel capitolo precedente, dovrebbe essere stato inteso che l'SGML non Õ un «linguaggio di scrittura» da imparare e usare cosË com'Õ. Al contrario, Õ un linguaggio per definire il modo in cui il testo deve essere scritto, e solo dopo si puÐ iniziare a scrivere secondo le regole stabilite.
Volendo fare un abbinamento con i linguaggi di programmazione, sarebbe come se prima si dovesse definire il linguaggio stesso, per poi poter scrivere i programmi secondo quelle regole.
La descrizione fatta in questo capitolo potrebbe risultare noiosa, considerato che solo dopo molte sezioni si mostra in che modo realizzare effettivamente il proprio DTD e applicarlo a un documento. Considerata la complessitÞ dei concetti espressi, si ritiene piÛ conveniente una spiegazione che parte dal basso, piuttosto che usare un approccio inverso, che presumerebbe una conoscenza minima di partenza.
Le regole che definiscono la struttura e la scomposizione del documento, e tutte le altre che governano la logica dell'SGML, sono contenute nel DTD.
Queste regole, possono essere permissive, o restrittive, in funzione degli obbiettivi che ci si prefigge; ovvero, in funzione del contenuto di quel tipo di documento e delle cose che con questo ci si aspetta di fare.
La complessitÞ del mondo reale, fa sË che non ci sia modo di realizzare un unico DTD che vada bene per tutti gli scopi. Un DTD ipotetico, che volesse andare bene un po' per tutto, dovrebbe essere anche qualcosa di estremamente generico e permissivo, annullando tutti i benefici dell'utilizzo dell'SGML.
Un esempio reale di un DTD «tuttofare» Õ quello dell'HTML, in cui tutto si concentra nella definizione di elementi il cui scopo prevalente Õ definire, anche se solo vagamente, l'aspetto finale che dovrebbe avere il risultato. Lo scopo dell'SGML non Õ quello di stabilire il risultato finale del documento, tuttavia, si puÐ benissimo predisporre un DTD orientato a questo obbiettivo. Ma questo, nel caso dell'HTML, giustifica poi l'estrema debolezza della sua struttura, dove Õ ammesso quasi tutto.
Tuttavia, Õ difficile comprendere subito il significato pratico di questo approccio: la definizione del tipo di documento, e poi la scrittura del testo. Lo si puÐ comprendere solo quando si lavora assiduamente nell'ambito della produzione di documentazione, quando ci si accorge che le proprie esigenze sono diverse da quelle degli altri, per cui diventa difficile adattarsi all'uso di modelli giÞ esistenti.
Dal punto di vista di SGML, una singola unitÞ di testo la cui dimensione varia a seconda del contesto, Õ un elemento, e a ognuno di questi, SGML impone l'attribuzione di un nome. SGML non fornisce alcun modo per attribuire un significato agli elementi del testo, tranne per il fatto di avergli dato un nome. Piuttosto, attraverso un analizzatore SGML, Õ possibile verificare che questi siano collocati correttamente secondo le relazioni stabilite.
I nomi degli elementi, sono definiti tecnicamente identificatori generici, utilizzando la sigla GI (Generic Identifier).
Nel sorgente SGML, gli elementi sono indicati normalmente attraverso l'uso di marcatori che hanno la forma consueta <...>
e </...>
, dove il primo inizia l'elemento nominato tra le parentesi angolari e il secondo chiude l'elemento. Per esempio, si potrebbe definire l'elemento acronimo
e utilizzarlo nel testo nel modo seguente:
...Il gruppo <acronimo>ILDP</acronimo> si occupa di... |
Il significato che questo elemento puÐ avere, non Õ definito dall'SGML. Il fatto di avere delimitato l'elemento acronimo
potrebbe servire per estrarre dal documento tutte le sigle utilizzate, per inserire queste in un indice particolare, oppure solo per fini stilistici di evidenziamento uniforme.
La difficoltÞ nella scrittura di un testo in SGML si riduce a questo: utilizzare i marcatori necessari a identificare correttamente i vari elementi del testo, secondo le regole stabilite nella definizione del documento stesso (il DTD).
Prima ancora di iniziare a vedere il contenuto del DTD, Õ bene chiarire che esistono altri modi per delimitare un elemento SGML. Per la precisione, si tratta di abbreviazioni di cui alcuni autori non riescono a fare a meno. La scrittura di un sorgente SGML Õ un po' come quella di un sorgente di un linguaggio di programmazione: si puÐ essere concisi o prolissi. Di solito, quando si Õ concisi si scrive del codice difficile da leggere, e in generale Õ meglio scrivere tutto in forma chiara senza risparmiare. L'esempio visto in precedenza,
...Il gruppo <acronimo>ILDP</acronimo> si occupa di... |
puÐ essere abbreviato in
...Il gruppo <acronimo>ILDP</> si occupa di... |
e anche nel modo seguente, che perÐ porta con sÈ un vincolo importante: non si possono usare delle barre oblique all'interno dell'elemento abbreviato in questo modo.
...Il gruppo <acronimo/ILDP/ si occupa di... |
Con questi sistemi, oltre a rendere il sorgente SGML poco leggibile, si rischia di non ottenere i risultati che si attendono se gli strumenti di elaborazione utilizzati non riconoscono tali estensioni del linguaggio.
La definizione del DTD Õ ottenuta da una serie di istruzioni dichiarative composte secondo una sintassi molto semplice. L'esempio seguente rappresenta le istruzioni necessarie a definire gli elementi di un tipo di documento ipotetico definibile come relazione
.
<!ELEMENT relazione - - (titolo?, data, contenuto) > <!ELEMENT titolo - o (#PCDATA) > <!ELEMENT data - o (#PCDATA) > <!ELEMENT contenuto - o (paragrafo+, firma+) > <!ELEMENT paragrafo - o (#PCDATA) > <!ELEMENT firma - o (#PCDATA) > |
Ognuna delle righe che appaiono nell'esempio rappresenta una dichiarazione di un elemento SGML. Una dichiarazione, di qualunque tipo, Õ delimitata da una parentesi angolare aperta (il simbolo di minore), seguita immediatamente da un punto esclamativo (<!
), e da una parentesi angolare chiusa (>
).
La dichiarazione di un elemento si compone poi della parola chiave ELEMENT
, seguita dal nome dell'elemento, dalle regole di minimizzazione rappresentate da due caratteri e da un modello del contenuto.
<!ELEMENT titolo - O (#PCDATA) > | | | ^^^ | | | | | | | delimitatore conclusivo | | nome | | dell'istruzione | | dell'elemento | | | | | modello del contenuto | dichiarazione | | di un elemento regole di minimizzazione | delimitatore di apertura dell'istruzione SGML |
Le varie parti che compongono qualunque tipo di dichiarazione SGML sono separate da spazi orizzontali (caratteri spazio, o tabulazioni orizzontali) oppure anche da interruzioni di riga, permettendo cosË di proseguire le istruzioni su piÛ righe distinte.
Le regole di minimizzazione, rappresentate da due caratteri staccati, indicano l'obbligatorietÞ o meno dell'utilizzo del marcatore di apertura e di chiusura per l'elemento dichiarato. Il primo dei due simboli rappresenta l'apertura, il secondo la chiusura. Un trattino indica che il marcatore Õ obbligatorio, mentre la lettera O
sta per «opzionale» e indica cosË che puÐ essere omesso:
-
-
sono obbligatori entrambi i marcatori;
-
O
Õ obbligatorio il marcatore iniziale, mentre quello finale Õ facoltativo;
O
-
il marcatore iniziale Õ facoltativo, mentre quello finale Õ obbligatorio (di solito non capita questa situazione);
O O
sono facoltativi entrambi i marcatori.
Nell'esempio mostrato in precedenza, solo l'elemento relazione
richiede l'utilizzo di marcatori di apertura e di chiusura, mentre tutti gli altri possono essere indicati utilizzano il solo marcatore di apertura. In pratica, il contesto permette di individuare dove finiscano tali elementi nel testo.
La possibilitÞ o meno di rendere facoltativo l'uso dei marcatori di apertura e di chiusura non Õ solo un fatto di gusto, in quanto dipende anche dall'organizzazione del tipo di documento. Se le dichiarazioni diventano ambigue, non si possono piÛ distinguere gli elementi nel testo SGML.
La parte finale della dichiarazione di un elemento SGML Õ il modello del contenuto, che si distingue perchÈ Õ racchiuso tra parentesi tonde. Serve a descrivere il tipo di contenuto che puÐ avere l'elemento e si puÐ esprimere attraverso parole riservate che hanno un significato preciso, come #PCDATA
(Parsed Character DATA) che rappresenta una qualunque sequenza di caratteri valida, oppure attraverso l'indicazione di nomi di altri elementi che possono (o devono) essere contenuti in qualche modo.
Il modello del contenuto, puÐ articolarsi in modo molto complesso, allo scopo di definire le relazioni tra gli elementi contenuti.
Per il momento, Õ bene osservare che un elemento, il cui modello del contenuto sia composto esclusivamente della parola riservata #PCDATA
, non puÐ contenere al suo interno altri tipi di elementi. Il significato di alcune delle parole riservate piÛ comuni, utilizzabili per definire il contenuto di un elemento, sono riportate piÛ avanti in questo capitolo, dopo la presentazione di altri concetti essenziali, necessari per comprenderne il senso.
Il modello del contenuto utilizza un sistema abbastanza complesso per definire la possibilitÞ di contenere piÛ elementi dello stesso tipo e per indicare raggruppamenti di elementi. Per indicare la ripetizione, viene usato un simbolo alla fine dell'oggetto a cui si riferisce, e questo simbolo si chiama indicatore di ripetizione (occurrence indicator).
Il segno +
usato come suffisso, rappresenta una o piÛ ripetizioni dell'elemento.
Il segno ?
usato come suffisso, rappresenta zero o al massimo un'occorrenza dell'elemento.
Il segno *
usato come suffisso, rappresenta zero o piÛ ripetizioni dell'elemento.
Se non viene usato nessun suffisso, l'elemento indicato deve essere usato esattamente una volta.
Dall'esempio mostrato in precedenza viene ripreso l'estratto seguente, nel quale si puÐ osservare che: l'elemento titolo
puÐ apparire al massimo una volta all'interno di relazione
(precisamente all'inizio di questo elemento); l'elemento paragrafo
deve essere contenuto almeno una volta all'interno dell'elemento contenuto
(lo stesso vale per l'elemento firma
); l'elemento firma
puÐ contenere solo caratteri normali senza altri elementi.
<!ELEMENT relazione - - (titolo?, data, contenuto) > <!ELEMENT contenuto - O (paragrafo+, firma+) > <!ELEMENT firma - O (#PCDATA) > |
Quando un elemento deve poter contenere diversi tipi di elementi, Õ necessario usare dei simboli, detti connettori, per stabilirne la relazione.
La virgola (,
) indica che l'elemento precedente e quello successivo devono apparire nell'ordine in cui sono.
La e-commerciale (&
) indica che l'elemento precedente e quello successivo devono essere presenti entrambi, ma possono apparire in qualunque ordine.
la barra verticale (|
) indica che solo uno tra i due elementi che connette puÐ apparire.
Riprendendo il solito estratto dell'esempio giÞ mostrato precedentemente, si puÐ osservare l'uso della virgola in qualitÞ di connettore:
<!ELEMENT relazione - - (titolo?, data, contenuto) > <!ELEMENT contenuto - O (paragrafo+, firma+) > <!ELEMENT firma - O (#PCDATA) > |
L'elemento relazione
puÐ contenere al massimo un titolo all'inizio, quindi deve apparire un elemento data
e dopo di questo anche un elemento contenuto
. L'elemento contenuto
deve contenere uno o piÛ elementi paragrafo
, a partire dall'inizio, e in coda, uno o piÛ elementi firma
.
<!ELEMENT nominativo - - (nome & cognome) > <!ELEMENT voce - - (punto | numero) > |
Per completare gli esempi sull'uso dei connettori, si osservi quanto mostrato sopra. L'elemento nominativo
deve contenere un elemento nome
e un elemento cognome
, in qualunque ordine; l'elemento voce
puÐ contenere solo un elemento a scelta tra punto
e numero
.
All'interno di un modello di contenuto, Õ possibile indicare dei raggruppamenti che esprimono in pratica dei sottomodelli, a cui poter applicare gli indicatori di ripetizione e i connettori. Per questo si usano le parentesi tonde. Si osservi l'esempio seguente:
<!ELEMENT figure - - ( (eps | ph), img*, caption?) > |
L'elemento figure
deve contenere un'occorrenza del sottogruppo (eps | ph)
, zero o piÛ ripetizioni dell'elemento img
e al massimo un'occorrenza di caption
, nell'ordine descritto. Il sottogruppo (eps | ph)
rappresenta una singola occorrenza di eps
oppure ph
.
Quando si utilizzano gli operatori di ripetizione assieme ai raggruppamenti, possono nascere degli equivoci. Ammesso che ciÐ possa avere senso, si osservi la variante seguente dell'esempio giÞ presentato:
<!ELEMENT figure - - ( (eps | ph)+, img*, caption?) > |
õ stato aggiunto il segno +
dopo il gruppo (eps | ph)
. In questo modo, si intende che sia possibile l'inserimento iniziale di una serie indefinita di elementi eps
o ph
, in qualunque ordine, purchÈ ce ne sia almeno uno dei due. Quindi, non Õ necessario che si tratti solo di elementi eps
o solo di ph
.
Se nella definizione di un elemento si vogliono indicare delle eccezioni a quanto definito dal modello di contenuto, si puÐ indicare un gruppo di elementi successivo al modello del contenuto.
Questo gruppo puÐ essere preceduto dal segno +
o dal segno
indicando rispettivamente un'eccezione di inclusione, o un'eccezione di esclusione.
-
<!ELEMENT address - O (#PCDATA) +(newline) > |
L'elemento address
contiene caratteri normali, ma puÐ includere eccezionalmente anche l'elemento newline
.
<!ELEMENT acronimo - - (#PCDATA) -(acronimo) > |
L'elemento acronimo
contiene caratteri normali e non puÐ includere se stesso (a essere precisi, non dovrebbe essere necessario dichiarare una cosa del genere, dal momento che il contenuto #PCDATA
non ammette altri elementi al suo interno).
*1*
Alcuni tipi di elementi non sono fatti per circoscrivere una zona di testo, ma solo per rappresentare qualcosa che si trova in un certo punto. Questi elementi, non vengono dichiarati con un modello di contenuto tra parentesi, ma con l'utilizzo della parola chiave empty
.
L'esempio seguente, dichiara l'elemento toc
che non puÐ contenere alcunchÈ.
<!ELEMENT toc - O EMPTY> |
Tipicamente, tali elementi, sono dichiarati in modo che il marcatore di chiusura sia solo facoltativo. Non potendo contenere alcunchÈ, sarebbe perfettamente inutile renderlo obbligatorio.
Eventualmente, un gruppo di elementi che abbiano le stesse caratteristiche, cioÕ le stesse regole di minimizzazione e lo stesso modello del contenuto, puÐ essere dichiarato in una sola istruzione. L'esempio seguente dovrebbe essere sufficiente a comprendere il meccanismo.
<!ELEMENT ( annotazione | avvertimento | pericolo ) - - (#PCDATA) > |
Un elemento puÐ prevedere la presenza di uno o piÛ attributi. Si tratta di informazioni che non compongono il contenuto dell'elemento, ma di qualcosa che, non potendo apparire nel testo, serve per qualche ragione ai programmi che elaborano successivamente il documento.
Il classico esempio Õ costituito da quei marcatori utilizzati per i riferimenti incrociati. L'esempio seguente mostra la dichiarazione dell'elemento ref
che si intende utilizzare come riferimento a una parte del documento identificata attraverso il valore attribuito all'attributo point
.
<!ELEMENT ref - O EMPTY> <!ATTLIST ref point IDREF #REQUIRED name CDATA "riferimento" > |
Attraverso l'istruzione ATTLIST
si definiscono gli attributi di un elemento. Dopo l'indicazione del nome dell'elemento a cui si fa riferimento, segue l'elenco degli attributi, ognuno dei quali inizia con un codice di interruzione di riga seguito eventualmente da altri tipi di spazi. CiÐ significa che l'istruzione ATTLIST
deve essere composta proprio come indicato dall'esempio, solo i rientri sono facoltativi.
L'esempio indica che l'elemento ref
contiene due attributi: point
e name
. Il primo Õ obbligatorio (#REQUIRED
), mentre per il secondo Õ stato indicato un valore predefinito, nel caso non venga specificato espressamente (riferimento
).
Il tipo di contenuto di un attributo viene definito attraverso delle parole chiave, che possono essere indicate usando lettere maiuscole o minuscole indifferentemente:
CDATA
rappresenta una stringa di qualunque tipo di carattere, ammettendo anche simboli di punteggiatura o altro, che comunque mantiene solo il suo significato letterale (Character DATA);
Questo Õ un punto delicato. La parole chiave |
NMTOKEN
rappresenta qualunque tipo di carattere alfanumerico (lettere, numeri e spazi soltanto), che dovrebbe comporre un nome (Name TOKEN);
NUMBER
rappresenta solo cifre numeriche, cioÕ un numero;
ID
rappresenta un identificatore unico per quel tipo di documento, e si ottiene dando un nome, senza caratteri speciali o segni di punteggiatura, che poi servirÞ per farvi riferimento;
IDREF
indica che l'attributo deve essere un puntatore valido a un identificatore di un attributo ID, corrispondente in un altro elemento.
Il tipo di contenuto di un attributo, puÐ essere indicato in modo preciso attraverso una serie di scelte alternative. In tal caso, invece di utilizzare le parole chiave giÞ elencate, si indicano le stringhe alternative, separate dalla barra verticale, tra parentesi tonde. Per esempio, (bozza | finale)
rappresenta la possibile scelta tra le due parole bozza
e finale
.
L'ultimo dato da inserire per ogni attributo Õ il valore predefinito, oppure una parola chiave a scelta tra le seguenti:
#REQUIRED
rappresenta l'obbligatorietÞ dell'inserimento del valore;
#IMPLIED
rappresenta un attributo facoltativo;
#CURRENT
in mancanza di un'indicazione esplicita, rappresenta l'utilizzo dell'ultimo valore assegnato allo stesso attributo dello stesso elemento.
Tra tutti, merita attenzione la coppia ID
e IDREF
. Questi tipi di attributi possono essere molto utili per definire dei riferimenti incrociati all'interno del documento, quando la loro validitÞ deve essere controllata con gli strumenti di convalida SGML. Si osservi l'esempio seguente:
<!ELEMENT label - O EMPTY> <!ATTLIST label identity ID #REQUIRED> <!ELEMENT ref - O EMPTY> <!ATTLIST ref point IDREF #REQUIRED> |
Nell'esempio si mostra la dichiarazione di un elemento label
che non puÐ contenere testo, e serve solo per definire l'attributo identity
, di tipo ID
. Questo permetterÞ l'utilizzo di marcatori simili a <label identity="miaetichetta">
, dove viene assegnato all'attributo identity
un nome sempre diverso, allo scopo di identificare qualcosa. Sotto, la dichiarazione dell'elemento ref
mostra un altro elemento che non puÐ contenere testo, ma solo un attributo denominato point
, di tipo IDREF
, che puÐ quindi contenere solo il nome di un identificatore giÞ usato in un altro elemento con l'attributo ID
.
In pratica, se nel testo SGML si dovesse utilizzare da qualche parte il marcatore <label identity="miaetichetta">
, in un altro punto sarebbe valido il marcatore <ref point="miaetichetta">
, perchÈ l'identificatore miaetichetta
esiste effettivamente.
Ricapitolando, un attributo ID
di un marcatore Õ valido quando Õ unico nel documento SGML che si scrive, mentre un attributo IDREF
Õ valido quando esiste il valore corrispondente di un attributo ID
.
Spesso, per cose del genere, si preferisce usare attributi di tipo |
Con questo termine, entitÞ, si fa riferimento a due tipi di oggetti: macro per la sostituzione di stringhe (general entities) o macro per la sostituzione di nomi all'interno di istruzioni SGML (parameter entities).
Le macro per la sostituzione di stringhe, una volta dichiarate, si utilizzano all'interno del sorgente SGML come abbreviazioni o come un modo per identificare lettere o simboli che non possono essere usati altrimenti. Per esempio, utilizzando le entitÞ ISO 8879:1986, la frase
Wer bekommt das grÆúte StÝck Torte?
puÐ essere scritta nel sorgente nel modo seguente:
Wer bekommt das größte Stück Torte?
Le entitÞ generali, quindi, sono identificate nel testo SGML perchÈ iniziano con la e-commerciale (&
), e terminano con un punto e virgola. õ bene osservare che il punto e virgola non Õ obbligatorio in ogni situazione, ma solo quando il carattere successivo sia diverso da uno spazio orizzontale o da un codice di interruzione di riga. In generale, perÐ, sarebbe bene usare sempre il punto e virgola. La tabella
116.1 elenca alcune macro delle entitÞ standard piÛ importanti.
*2*
á | À | Á | à |
â | Á | Â | á |
à | Þ | À | þ |
å | Å | Å | å |
ã | Ö | Ã | ö |
ä | Ä | Ä | ä |
æ | Ô | Æ | ô |
ç | Ã | Ç | ã |
é | È | É | è |
ê | É | Ê | é |
è | Õ | È | õ |
ë | Ê | Ë | ê |
í | Ì | Í | ì |
î | Í | Î | í |
ì | Ë | Ì | ë |
ï | Î | Ï | î |
ñ | ß | Ñ | ÿ |
ó | Ñ | Ó | ñ |
ô | Ò | Ô | ò |
ò | Ð | Ò | ð |
ø | Ü | Ø | ü |
õ | Ó | Õ | ó |
ö | Æ | Ö | æ |
ß | ú | ||
ú | Ç | Ú | ç |
û | Ø | Û | ø |
ù | Û | Ù | û |
ü | Ý | Ü | ý |
ý | Ù | Ý | ù |
ÿ | Ú | ||
& | & | @ | @ |
* | * | ||
ˆ | ^ | ˜ | ~ |
© | © | ||
$ | $ | % | % |
# | # | ||
! | ! | ¡ | ¡ |
? | ? | ¿ | ¿ |
‐ | - | _ | _ |
\ | \ | ||
" | " | ||
< | < | > | > |
[ | [ | ] | ] |
{ | { | } | } |
L'altro tipo di macro, riguarda invece la sostituzione all'interno delle istruzioni SGML, cioÕ nella dichiarazione del DTD.
L'esempio seguente mostra la dichiarazione dell'elemento p
che puÐ contenere l'elemento o gli elementi indicati all'interno della macro %inline;
.
<!ELEMENT p - O (%inline;) > |
La dichiarazione di un'entitÞ avviene utilizzando l'istruzione ENTITY
. L'esempio seguente mostra la dichiarazione di un'entitÞ da utilizzare nel sorgente SGML.
<!ENTITY agrave "\`a"> |
In questo caso, si vuole che la macro à
venga sostituita con la stringa \`a
. Evidentemente, questa trasformazione non ha niente a che vedere con SGML. õ semplicemente una scelta motivata dal tipo di programma utilizzato successivamente per rielaborare il risultato generato dall'analizzatore SGML.
L'esempio seguente mostra la dichiarazione di due entitÞ da utilizzare all'interno delle istruzioni SGML.
<!ENTITY % emph " em | concept | cparam " > <!ENTITY % inline "(#PCDATA | %emph;)*" > |
La dichiarazione di questo tipo di entitÞ si distingue perchÈ viene utilizzato il simbolo di percentuale subito dopo la parola ENTITY
, staccandolo da questa e anche dal nome dell'entitÞ successivo. Anche in questo caso si utilizza solo come pura sostituzione di stringhe, per cui la dichiarazione di %inline;
, facendo a sua volta riferimento a %emph;
, Õ equivalente a quella seguente:
<!ENTITY % inline "(#PCDATA | em | concept | cparam )*" > |
Naturalmente, una macro puÐ contenere anche il riferimento a un'altra macro. Per esempio, la dichiarazione dell'ipotetico elemento p
, fatta nel modo seguente,
<!ELEMENT p - O (%inline;) > |
Õ equivalente a quest'altra dichiarazione:
<!ELEMENT p - O ((#PCDATA | em | concept | cparam )*) > |
Le entitÞ di qualunque tipo, possono essere dichiarate abbinando una stringa a una macro, come Õ stato mostrato in precedenza. In alternativa, a una macro si puÐ abbinare un file esterno (file inteso nel senso piÛ ampio possibile). In tal caso, si utilizza la parola chiave SYSTEM
come nell'esempio seguente:
<!ENTITY capitolo2 SYSTEM "capitolo2.sgml"> |
In tal modo, quando poi nel documento SGML si utilizza la macro &capitolo2;
, e poi lo si elabora attraverso un analizzatore SGML, si ottiene l'inserimento del file capitolo2.sgml
. PiÛ o meno ciÐ che si fa normalmente con le direttive di un tipico preprocessore di un linguaggio di programmazione.
Nello stesso modo si puÐ fare per dichiarare un'entitÞ parametrica, come nell'esempio seguente:
<!ENTITY % isoent SYSTEM "isoent.txt"> |
L'esempio mostra la dichiarazione della macro %isoent;
, riferita al file isoent.txt
. Per utilizzare questa macro, bisogna sapere a cosa si riferisce; trattandosi di un file, Õ logico pensare che si tratti di un testo articolato su piÛ righe, e quindi inadatto all'inserzione all'interno delle istruzioni. Generalmente, una macro del genere serve a incorporare un pezzo di DTD dall'esterno.
%isoent; |
Come si vede dall'esempio, Õ normale vedere la chiamata di una macro di questo tipo, da sola, all'esterno di qualunque istruzione del DTD. L'esempio mostrato Õ comunque significativo: rappresenta l'inclusione di un file che presumibilmente, dal nome, serve a incorporare le entitÞ ISO, cioÕ quelle standard riferite alle lettere accentate e ai simboli speciali.
A questo proposito, potrebbero esistere diversi file, del tipo: isoent.latex.txt
, isoent.html.txt
,... che prima di avviare l'analizzatore SGML vengono sostituiti al file isoent.txt
, in modo da ottenere la sostituzione corretta in base all'elaborazione successiva che si vuole ottenere (LaTeX, HTML, ecc.).
Se non fosse ancora chiaro, ecco come potrebbe essere composto l'ipotetico file isoent.txt
quando si vogliono le sostituzioni corrette per LaTeX.
<!ENTITY agrave "\`a"> <!ENTITY Agrave "\`A"> <!ENTITY egrave "\`e"> <!ENTITY Egrave "\`E"> <!ENTITY eacute "\'e"> <!ENTITY Eacute "\'E"> ... |
L'acquisizione di una macro da un file esterno puÐ essere dichiarata senza specificare esplicitamente il file, lasciando che l'analizzatore trovi il file corretto in base a un catalogo SGML. L'argomento verrÞ ripreso in seguito, comunque, in questo tipo di dichiarazione, manca il nome del file.
<!ENTITY capitolo2 SYSTEM> |
<!ENTITY % isoent SYSTEM> |
Solitamente, si preferisce includere in questo modo solo le macro parametriche, e questo lo si comprenderÞ intuitivamente in seguito.
õ bene ribadire che l'uso delle entitÞ standard (ISO), permette di rendere il testo SGML indipendente dalla piattaforma utilizzata. Tuttavia, la dichiarazione della sostituzione dipende dalla piattaforma, e come si Õ mostrato, si tendono a predisporre diversi schemi di sostituzione per le diverse piattaforme a cui si vuole fare riferimento.
In situazioni eccezionali, puÐ essere conveniente indicare i caratteri per numero, attraverso una notazione simile a quella delle entitÞ normali. Per esempio, se si usa la codifica ISO 8859-1 (Latin-1), la macro è
corrisponderÞ alla lettera Õ
(la «e» accentata normale).
Questa possibilitÞ Õ fondamentale proprio quando si definiscono le stringhe di sostituzione per una determinata piattaforma (hardware/software), in cui si debbano indicare caratteri speciali identificati dal numero corrispondente.
<!ENTITY egrave "è"> |
Potrebbe sembrare che un testo SGML non possa utilizzare una codifica particolare, quale ISO 8859-1 o altro. Non Õ cosË. L'SGML mette a disposizione le entitÞ standard, ma ciÐ non toglie che si possa decidere di usare comunque una codifica (ASCII) estesa come Latin-1 o altro. Ovviamente questo rende il testo dipendente dalla piattaforma, precisamente dalla codifica. |
Le sezioni marcate sono una specialitÞ di SGML, poco usata, e poco conosciuta. Si tratta di istruzioni che vengono inserite nel testo SGML, non nel DTD, e servono a vario titolo per delimitare del testo per qualche scopo.
Una sezione marcata si compone di un sorta di marcatore di apertura, e di una sorta di marcatore di chiusura. Il marcatore di apertura contiene una parola chiave che ne identifica il comportamento. Si osservi l'esempio seguente:
<![ INCLUDE [ Questa parte del testo Õ inclusa nell'elaborazione SGML. ]]> |
Come si puÐ intuire, la sezione marcata dell'esempio Õ introdotta da <![ INCLUDE [
ed Õ terminata da ]]>
. In questo caso, la parola chiave INCLUDE
indica che il testo contenuto nella sezione marcata deve essere incluso nell'elaborazione (anche se ciÐ, per ora, puÐ sembrare perfettamente senza significato).
Le parole chiave utilizzabili per definire la sezione marcata sono diverse, e di seguito ne appare l'elenco.
INCLUDE
Il contenuto della sezione marcata deve essere incluso nel documento SGML, e deve essere elaborato normalmente.
IGNORE
Il contenuto della sezione marcata deve essere escluso dal documento SGML. Se l'analizzatore SGML genera un qualche tipo di output, questo non conterrÞ tale sezione.
CDATA
Il contenuto della sezione marcata deve essere incluso e trattato come testo letterale, in modo da ignorare ciÐ che altrimenti potrebbe essere interpretato come un marcatore o un'entitÞ. CiÐ vale per tutto, tranne il simbolo di chiusura della sezione marcata (]]>
), che quindi Õ l'unica cosa che non puÐ essere rappresentato all'interno di questa.
RCDATA
Il contenuto della sezione marcata deve essere incluso e trattato come testo letterale, in modo da ignorare ciÐ che altrimenti potrebbe essere interpretato come un marcatore, ma continuando a espandere le entitÞ.
TEMP
Il contenuto della sezione marcata deve essere inteso come «temporaneo». CiÐ serve solo come riferimento umano, per localizzare facilmente una parte del documento che richiede una revisione o che dovrÞ essere rimossa.
L'utilizzo di sezioni marcate di tipo INCLUDE
/IGNORE
, sono utili solo in abbinamento a entitÞ parametriche. Prima di proseguire, Õ bene chiarire che quella specie di marcatore che apre una sezione marcata Õ come un'istruzione SGML, di quelle che appaiono nel DTD, anche se viene usata al di fuori di questo, nel documento. In questo senso, al suo interno, si possono usare le entitÞ parametriche, e quindi, una di queste macro puÐ servire per definire in modo dinamico la parola chiave INCLUDE
oppure IGNORE
, per decidere di includere o escludere quel blocco (e probabilmente anche altri) con la modifica di una sola macro.
Per esempio, nel DTD del documento potrebbe apparire la dichiarazione di un'entitÞ parametrica denominata commentato
.
<!ENTITY % commentato "INCLUDE"> |
Nel documento SGML potrebbero esserci una serie di sezioni marcate la cui inclusione deve dipendere da questa macro.
... 1 + 2 = 3 <![ %commentato; [ La matematica non Õ un'opinione. ]]> ... |
Quando il testo viene analizzato, la macro viene espansa e trovando che corrisponde a INCLUDE
, il testo delle sezioni marcate che l'hanno usata, vengono incluse. Al contrario, basta modificare la macro, assegnandole il valore IGNORE
, per fare in modo che tutte quelle sezioni marcate vengano ignorate.
Questo tipo di approccio potrebbe sembrare ugualmente scomodo per l'utilizzatore che non vuole toccare il DTD. PerÐ, si vedrÞ in seguito che si possono inserire delle eccezioni al DTD nel preambolo di un documento SGML. Oppure, si puÐ benissimo progettare un DTD con una componente esterna, destinata a questo tipo di ritocchi.
Prima di passare alla descrizione dell'abbinamento di un DTD a un testo SGML, Õ bene chiarire alcuni dettagli che sono stati trascurati nelle sezioni precedenti.
All'interno del documento sorgente SGML, e cosË anche nel DTD, possono essere indicate delle righe di commento da non considerare come parte del documento o della codifica. Queste si ottengono con i delimitatori <!
e -
-
.
-
-
>
Volendo approfondire meglio il problema, la sequenza <!>
rappresenta l'istruzione SGML nulla, e puÐ essere usata indifferentemente nel DTD o nel sorgente SGML. In qualitÞ di istruzione nulla viene ignorata semplicemente.
All'interno delle istruzioni SGML Õ possibile inserire dei commenti, attraverso una sequenza di due trattini (
), per aprire e chiudere il commento. Per esempio,
-
-
<!ELEMENT itemize - - (item+) -- elenchi puntati -- > |
dichiara l'elemento itemize
con un commento incorporato.
Questo dovrebbe chiarire il senso del commento composto da <!
e -
-
: si tratta di un'istruzione (nulla) che contiene un commento.
-
-
>
Questa particolaritÞ di SGML ha delle conseguente: nel testo che compone il commento, non possono apparire sequenze di due o piÛ trattini.
Per convenzione, i nomi di entitÞ sono sensibili alla differenza tra lettere maiuscole e minuscole, per cui À
e à
rappresentano rispettivamente la lettera «A» maiuscola con accento grave e la «a» minuscola con accento grave.
Per convenzione, i nomi degli elementi, i simboli delle regole di minimizzazione, i nomi degli attributi, e le parole chiave, non sono sensibili alla differenza tra lettere maiuscole e minuscole. Quindi, nelle dichiarazioni del DTD,
<!element ref - o empty> <!attlist ref id cdata #required name cdata "riferimento"> |
Õ identico a
<!ELEMENT REF - O EMPTY> <!ATTLIST REF ID CDATA #REQUIRED NAME CDATA "riferimento"> |
cosË come nel testo SGML
... <ref id="capitolo-introduttivo" name="Intro"> ... |
Õ identico a
... <REF ID="capitolo-introduttivo" NAME="Intro"> ... |
indifferentemente dal modo (maiuscolo o minuscolo) in cui, l'elemento ref
Õ stato dichiarato nel DTD.
Evidentemente, in generale, il contenuto delle stringhe delimitate Õ sensibile alla differenza tra maiuscole e minuscole. *3*
In varie situazioni, all'interno del DTD e all'interno dei marcatori utilizzati nel testo SGML, puÐ essere necessaria l'indicazione di stringhe. I simboli utilizzati per delimitare le stringhe possono essere gli apici doppi ("
..."
), oppure gli apici singoli ('
...'
). La scelta tra i due tipi di delimitatori dovrebbe essere indifferente, a parte la possibile necessitÞ di inserire nelle stringhe proprio questi caratteri. Si osservi l'esempio seguente, in cui vengono dichiarate le entitÞ riferite ad alcune lettere accentate da usare con LaTeX.
<!ENTITY uuml '\"u'> <!ENTITY Uuml '\"U'> <!ENTITY yacute "\'y"> <!ENTITY Yacute "\'Y"> |
In situazioni piÛ complesse, potrebbe essere necessario indicare i caratteri con l'aiuto delle macro &#nnn;
, che permettono di identificare l'oggetto attraverso il numero corrispondente riferito al tipo di codifica utilizzato (purchÈ il contesto preveda la successiva ulteriore espansione di tali macro).
In precedenza, quando Õ stato mostrato in che modo possa essere definita un'entitÞ, si Õ trascurato il fatto che si deve definire in che modo la stringa di sostituzione vada interpretata. Per questo, si aggiunge una parola chiave prima della stringa.
Se non si usa alcuna parola chiave, si intende che la stringa vada interpretata come appare, espandendo eventuali entitÞ contenute al suo interno. Si osservi l'esempio.
<!ENTITY attenzione "<ATTENZIONE>"> |
Quando dovesse essere utilizzata la macro &attenzione;
, si otterrebbe la stringa <ATTENZIONE>
, perchÈ le entitÞ <
e >
vengono espanse ulteriormente.
Se si indica la parola chiave CDATA
, si intende che la stringa di sostituzione deve essere utilizzata in modo letterale, senza espandere alcuna sequenza che potrebbe sembrare un'entitÞ.
<!ENTITY attenzione CDATA "<ATTENZIONE>"> |
L'esempio, modificato con l'introduzione della parola chiave CDATA
, fa sË che la macro &attenzione;
si traduca in pratica in <ATTENZIONE>
, perchÈ le entitÞ <
e >
non vengono riconosciute come tali, e quindi non vengono espanse.
Se si utilizza la parola chiave SDATA
(Special DATA), si intende che la stringa di sostituzione deve essere utilizzata in modo letterale, senza espandere alcuna sequenza che potrebbe sembrare un'entitÞ. PerÐ, a differenza di CDATA
, l'informazione viene filtrata in modo particolare quando l'analizzatore SGML genera un risultato transitorio da riutilizzare con un altro programma di composizione.
In precedenza Õ giÞ stata spiegata la dichiarazione degli elementi, e la dichiarazione del contenuto. In particolare si Õ visto che attraverso la parola chiave #PCDATA
si fa riferimento a testo normale che viene elaborato normalmente (parsed). CiÐ significa che questo tipo di testo Õ soggetto alla sostituzione delle entitÞ, come fino a questo punto si Õ dato per scontato.
Tuttavia esistono altre parole chiave per definire tipi di testo differenti. Segue l'elenco di quelle piÛ comuni.
#PCDATA
Parsed Character DATA. Si riferisce a testo normale soggetto alla sostituzione delle entitÞ. Questo testo non puÐ contenere altri elementi.
CDATA
Il contenuto dell'elemento deve essere trattato come testo letterale, in modo da ignorare ciÐ che altrimenti potrebbe essere interpretato come un marcatore o un'entitÞ.
In pratica, la definizione di elementi con contenuto |
RCDATA
Il contenuto dell'elemento deve essere trattato come testo letterale, in modo da ignorare ciÐ che altrimenti potrebbe essere interpretato come un marcatore, ma continuando a espandere le entitÞ.
L'abbinamento di un DTD a un documento SGML avviene generalmente in modo formale. In presenza di situazioni eccezionali, questo abbinamento Õ implicito, come nel caso dell'HTML, ma Õ bene utilizzare ugualmente l'approccio generale anche in questi casi estremi.
Un sorgente SGML inizia normalmente con la dichiarazione del tipo di DTD utilizzato. PuÐ trattarsi di un file esterno o di dichiarazioni incorporate nel documento stesso. Per esempio, la dichiarazione seguente indica all'analizzatore SGML di utilizzare un DTD esterno, denominato linuxdoc
e contenuto nel file linuxdoc.dtd
.
<!DOCTYPE linuxdoc SYSTEM "linuxdoc.dtd"> |
L'esempio seguente mostra invece una dichiarazione iniziale che contiene le istruzioni che compongono il DTD, racchiuse tra parentesi quadre.
<!DOCTYPE personale [ ... -- istruzioni SGML -- ... ... ]> |
Una terza possibilitÞ permette di definire un file esterno e di aggiungere altre istruzioni particolari riferite al documento, come nell'esempio seguente, sempre utilizzando le parentesi quadre.
<!DOCTYPE linuxdoc SYSTEM "linuxdoc.dtd" [ ... -- istruzioni SGML -- ... ... ]> |
Inoltre, come Õ stato visto nel caso delle entitÞ, l'acquisizione dall'esterno di un file contenente un DTD, puÐ avvenire anche senza stabilire espressamente il nome di un file, lasciando che questo venga determinato da un catalogo. CosË, l'esempio giÞ visto del DTD linuxdoc
si potrebbe trasformare nel modo seguente:
<!DOCTYPE linuxdoc SYSTEM> |
Esiste anche un'altra alternativa: quella di indicare un identificatore pubblico, anch'esso riferito a un catalogo. Quello che segue Õ il preambolo di un file SGML scritto secondo il DTD HTML 3.2. Si osservi, a questo proposito, l'uso della parola chiave PUBLIC
.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> |
La scelta di incorporare il DTD nel documento, o di lasciarlo all'esterno, dipende da delle scelte organizzative. Di sicuro, puÐ essere sensato l'inclusione del DTD nel documento SGML quando si tratta di un DTD specifico che non viene usato altrove.
Nella realtÞ, si utilizzerÞ quasi sempre un DTD esterno, probabilmente predisposto da altri, abbinato a una serie di strumenti che permettono di produrre dei documenti in formato finale a partire dai sorgenti SGML scritti seguendo quel DTD particolare.
L'estensibilitÞ del DTD resta sempre una possibilitÞ utile per poter aggiungere delle entitÞ interne o delle entitÞ parametriche allo scopo di gestire opportunamente le sezioni marcate.
Come si Õ visto nella sezione precedente, la dichiarazione del DTD puÐ includere delle istruzioni del DTD, generalmente estendendolo. Questo meccanismo permette, tra le altre cose, di inserire le cosiddette entitÞ interne (internal entity). Si osservi l'esempio.
<!DOCTYPE linuxdoc SYSTEM [ <!ENTITY pericolo "!!" > <!ENTITY posix "POSIX" > <!ENTITY unix "Unix" > <!ENTITY xwin "X Window System" > <!ENTITY edizione "1999.12.31"> ]> |
L'esempio appena mostrato permette di utilizzare le macro &pericolo;
, &posix;
, &unix;
, &xwin;
e &edizione;
, all'interno del sorgente SGML, ottenendo la loro sostituzione automatica. Per intenderne l'utilitÞ, basta pensare al caso della macro &xwin;
dell'esempio precedente: non occorre piÛ ricordare come si deve scrivere (X, X Window o X Window System), e se si decidesse di cambiare, basterebbe modificare la dichiarazione dell'entitÞ. Il concetto Õ analogo a quello delle macro del preprocessore nei linguaggi di programmazione.
La definizione di entitÞ interne Õ consentita anche quando queste dovessero essere giÞ state dichiarate nel DTD. Le entitÞ dichiarate nelle istruzioni aggiuntive, dovrebbero prendere la precedenza e sostituirsi a quelle eventualmente giÞ dichiarate nel DTD.
Come nel caso delle entitÞ interne, nelle estensioni del DTD puÐ essere conveniente aggiungere la dichiarazione di entitÞ parametriche da utilizzare per controllare l'inclusione o l'esclusione di sezioni marcate. Si osservi l'esempio, giÞ mostrato in precedenza, in cui la macro commentato
serve per controllare alcune sezioni marcate, stabilendone il tipo.
<!DOCTYPE linuxdoc SYSTEM [ <!ENTITY pericolo "!!" > <!ENTITY posix "POSIX" > <!ENTITY unix "Unix" > <!ENTITY xwin "X Window System" > <!ENTITY edizione "1999.12.31"> ... <!ENTITY % commentato "INCLUDE" > ]> ... ... 1 + 2 = 3 <![ %commentato; [ La matematica non Õ un'opinione. ]]> ... ... |
Si Õ visto in che modo inizia un sorgente SGML. Quello che non Õ ancora stato chiarito Õ che il tipo di documento deve essere stato dichiarato nel DTD, anche se ciÐ puÐ sembrare ridondante. In effetti Õ necessario dire di cosa Õ composto il documento. Nel DTD potrebbe apparire un'istruzione come quella seguente:
<!ELEMENT linuxdoc O O ( article | report | book | letter ) > |
In questo esempio, si comprende che non Õ necessario usare marcatori del tipo <linuxdoc>
</linuxdoc>
per delimitare il sorgente SGML. Infatti, la coppia di O
afferma che queste sono opzionali. Invece, il tipo di documento linuxdoc
deve contenere esattamente un elemento del tipo article
, oppure report
, oppure book
, o ancora letter
.
Il sorgente SGML che fa riferimento al tipo di documento linuxdoc
e che utilizza il formato definito dall'elemento article
, sarÞ composto schematicamente come segue:
<!DOCTYPE linuxdoc SYSTEM> <article> ... ... ... </article> |
Un tipo di documento potrebbe essere definito in maniera diversa, per esempio nel modo seguente:
<!element miodoc - - ( sezione+ ) > |
In questo caso, il documento puÐ contenere solo elementi sezione
, ed Õ obbligatorio l'utilizzo dei marcatori per indicare l'inizio e la fine del tipo di documento.
<!doctype miodoc system> <miodoc> <sezione> ... ... ... </miodoc> |
Fino a questo punto, si Õ vista la filosofia dell'SGML applicata alla struttura del documento e all'indipendenza rispetto alla piattaforma. L'analizzatore SGML standard, oltre che convalidare il documento in base al DTD, si occupa di rielaborare il sorgente SGML per generare un risultato intermedio, piÛ facile da gestire per altri programmi di composizione.
In un certo qual modo, questo risultato intermedio puÐ essere controllato, all'interno del DTD, attraverso la definizione di mappe di sostituzione, o shortref.
Con questo meccanismo, si punta normalmente ad attribuire significati speciali a simboli determinati, e a controllare la spaziatura orizzontale e verticale del testo.
La mappa di sostituzione definisce un abbinamento tra un simbolo e un'entitÞ che ne prenderÞ il posto. L'esempio seguente Õ solo un pezzo ipotetico della dichiarazione di una mappa del genere.
<!SHORTREF miamappa ... "[" lsqb "]" rsqb "~" nbsp "_" lowbar "#" num "%" percnt "^" circ "{" lcub "}" rcub "|" verbar > |
Dall'esempio si puÐ osservare che alcuni simboli vengono sostituiti con le relative entitÞ, indicate solo per nome, senza bisogno della e-commerciale e del punto e virgola finale. Questo fatto, di per sÈ, potrebbe sembrare assolutamente inutile dal punto di vista di SGML: se si puÐ scrivere una parentesi quadra aperta, perchÈ sostituirla automaticamente con la sua entitÞ corrispondente. Il fatto Õ che il software utilizzato per la composizione, potrebbe attribuire un significato speciale a una parentesi quadra, mentre quello che si vuole nel testo SGML Õ che questa valga solo per quello che appare. In tal modo, chi scrive dovrebbe utilizzare necessariamente la macro [
per non creare problemi al programma di composizione o di elaborazione successiva.
Nello stesso modo, attraverso la mappa di sostituzione, si puÐ attribuire un significato completamente diverso alla parentesi quadra aperta: per assurdo, potrebbe diventare una parentesi graffa...
<!SHORTREF miamappa ... "[" lcub "]" rcub ... "{" lcub "}" rcub "|" verbar > |
Volendo fare delle acrobazie, si puÐ associare un simbolo a un'entitÞ che poi si traduce in un marcatore. Si osservi l'esempio.
<!ENTITY formula1 '<formula>'> <!ENTITY formula0 '</formula>'> <!SHORTREF miamappa ... "[" formula1 "]" formula0 ... "{" lcub "}" rcub "|" verbar > |
In questo modo, quando nel testo si utilizzano le parentesi quadre, ciÐ che si ottiene Õ l'apertura e la chiusura dell'elemento formula
.
Anche se questa tecnica Õ stata usata nel noto DTD LinuxDoc, e prima in Qwertz, proprio per delimitare agevolmente le formule matematiche, si tratta di una cosa decisamente sconsigliabile dal punto di vista dell'SGML. |
Gli elementi SGML vanno abbinati alle mappe che si ritiene siano piÛ adatte per i loro scopi. Tuttavia, un elemento puÐ non essere stato abbinato esplicitamente ad alcuna mappa, e in tal caso eredita quella dell'elemento che lo contiene effettivamente, di volta in volta, nel documento. Di conseguenza, diventa importante abbinare esplicitamente una mappa almeno all'elemento piÛ esterno, ovvero a quello che corrisponde al nome del tipo stesso di documento.
Dagli esempi mostrati, si sarÞ potuto notare che la mappa ha un nome, e viene indicato subito dopo la parola chiave SHORTREF
che apre il comando. Se si vuole abbinare la mappa miamappa
all'elemento acronimo
, si procede come nell'esempio seguente:
<!USEMAP miamappa acronimo> |
In linea di principio, il risultato dell'elaborazione dell'analizzatore SGML contiene tutti gli spazi orizzontali e verticali esistenti nel sorgente di partenza. PerÐ, per quanto possibile, si cerca normalmente di evitare che il sorgente SGML sia vincolato dalla spaziatura utilizzata, che in realtÞ potrebbe servire solo per facilitarne la lettura umana con rientri, allineamenti, spazi verticali come si farebbe con un linguaggio di programmazione.
Per questo ci deve essere un modo per poter identificare le spaziature orizzontali, le righe vuote e quelle bianche, in modo da poterle sopprimere nel risultato dell'elaborazione SGML. Naturalmente, bisogna poter distinguere, perchÈ ci sono situazioni in cui gli spazi e le righe vuote hanno un significato, e vanno mantenuti.
Per queste cose si utilizzano delle macro speciali, ma prima di descriverle, occorre definire alcuni concetti. Dal punto di vista dell'SGML, una riga Õ una sequenza di caratteri, con un inizio e una fine, ignorando completamente la codifica che si utilizza in pratica per separare una riga dall'altra.
Nei sistemi Unix, il codice di interruzione di riga Õ composto dal carattere <LF> mentre in altri sistemi si utilizza la sequenza <CR><LF>. Per l'SGML Õ come se questi codici non esistessero: le righe finiscono prima del codice di interruzione di riga, e iniziano dopo tale codice. Si osservi l'esempio seguente:
<paragrafo>Ciao, come stai? Io bene, e tu?</paragrafo> |
L'idea che ha l'SGML di ciÐ che Õ stato scritto, puÐ essere rappresentata dallo schema seguente, dove Õ stato utilizzato il simbolo ^
per segnalare l'inizio della riga, il simbolo $
per segnalarne la fine, e i simboli >
e <
per indicare l'inizio e la fine dell'elemento.
>Ciao,$ ^come stai?$ ^Io bene, e tu?< |
PuÐ sembrare strano, ma all'inizio e alla fine del testo mancano questi margini: esiste solo l'inizio e la fine dell'elemento. Se si dovesse sopprimere una riga, si eliminerebbe implicitamente anche il suo inizio e la sua fine.
Da qualche parte si potrebbe leggere che il codice di inizio riga equivale al codice <LF>, mentre quello di fine riga corrisponde a <CR>. Evidentemente questo ragionamento puÐ valere solo per le piattaforme che utilizzano file di testo con un'interruzione di riga <CR><LF>, ma si tratta solo di una semplificazione che non corrisponde alla logica di SGML, e puÐ essere solo forviante.
La tabella 116.2 mostra le macro piÛ importanti che possono essere usate per il controllo delle spaziature superflue.
Simbolo | Significato |
&#RS; | Inizio di una riga (Record Start). |
&#RE; | Fine di una riga (Record End). |
&#RS;B | Spaziatura iniziale. |
B&#RE; | Spaziatura finale. |
&#RS;&#RE; | Una riga vuota. |
&#RS;B&#RE; | Una riga contenente solo spazi orizzontali (bianca). |
&#SPACE; | Uno spazio singolo, [SP]. |
&#TAB; | Tabulazione, [HT]. |
BB | Spazio orizzontale interno, e agli estremi dell'elemento. |
L'esempio seguente mostra una mappa di sostituzione tipica, in cui si vogliono ignorare (e di conseguenza, eliminare) gli spazi orizzontali superflui, le righe vuote, quelle bianche, e si vuole che tutto il testo si traduca in una riga sola.
<!shortref miamappa "BB" space "&#RS;B" null "B&#RE;" space "&#RS;B&#RE;" null "&#RS;&#RE;" null "&#RS;" null "&#RE;" space "[" lsqb "]" rsqb "~" nbsp "_" lowbar "#" num "%" percnt "^" circ "{" lcub "}" rcub "|" verbar > |
Le macro &space;
e &null;
si riferiscono rispettivamente a un singolo carattere spazio e alla stringa nulla. Generalmente devono essere dichiarate nel DTD nel modo seguente:
<!ENTITY space " "> <!ENTITY null ""> |
Per comprendere meglio l'effetto della mappa di sostituzione proposta, conviene partire da un esempio e analizzare gli effetti di ogni dichiarazione, una alla volta. In particolare, gli utenti dei sistemi Unix devono dimenticare per un po' il comportamento del codice di interruzione di riga (newline): SGML considera solo la stringa nulla all'inizio e alla fine della riga, e solo quando la fine di una riga e l'inizio della successiva sono stati rimossi, allora queste due vengono unite assieme.
Supponiamo di cominciare da una variante dell'esempio giÞ descritto, dove sono stati aggiunti tanti spazi orizzontali e verticali superflui.
> Ciao, $ ^$ ^ $ ^come stai?$ ^$ ^ Io bene, e tu? < |
Applicando la trasformazione "BB" space
, vengono sostituiti gli spazi orizzontali all'inizio dell'elemento, alla fine e all'interno delle frasi con un singolo spazio normale.
> Ciao, $ ^$ ^ $ ^come stai?$ ^$ ^ Io bene, e tu? < |
Si puÐ osservare che le frasi si sono ricompattate, e che all'inizio e alla fine dell'elemento Õ rimasto un solo spazio superfluo (che non potrÞ essere rimosso). Si continua applicando "&#RS;B" null
; si ottiene l'eliminazione dell'inizio delle righe (quelle che contengono effettivamente qualcosa) fino al primo carattere diverso da uno spazio orizzontale.
> Ciao, $ ^$ ^ $ ^come stai?$ ^$ Io bene, e tu? < |
Quando si applica anche "B&#RE;" space
; si ottiene la sostituzione degli spazi orizzontali nella parte finale, fino alla fine delle righe (quelle che contengono effettivamente qualcosa), con un singolo spazio. Nell'esempio, dal momento che nella prima riga Õ scomparso il simbolo che segnalava la fine della riga, appare un simbolo di sottolineatura, ma solo per aiutare il lettore.
> Ciao,_ ^$ ^ $ ^come stai?$ ^$ Io bene, e tu? < |
La sostituzione "&#RS;B&#RE;" null
elimina le righe bianche, ma non vuote.
> Ciao,_ ^$ ^come stai?$ ^$ Io bene, e tu? < |
La sostituzione "&#RS;&#RE;" null
elimina le righe vuote.
> Ciao,_ ^come stai?$ Io bene, e tu? < |
Si sarÞ osservato che la riga contenente la frase «come stai?», Õ rimasta intatta. Infatti, non contenendo spazi aggiuntivi all'inizio o alla fine, non Õ mai stata interessata dalle trasformazioni applicate fino a questo momento.
Finalmente entrano in gioco "&#RS; null
e "&#RE; space
, per eliminare l'inizio e la fine delle righe rimaste. Per la precisione, la fine delle righe deve essere sostituito con uno spazio singolo, altrimenti si rischia di attaccare assieme delle parole. La trasformazione viene mostrata in due passaggi.
> Ciao,_ come stai?_ Io bene, e tu? < |
---------
> Ciao, come stai? Io bene, e tu? < |
Nonostante la descrizione fatta con tanta cura, Õ probabile che la trasformazione |
Da quanto visto nella sezione precedente si potrebbe supporre che il meccanismo delle mappe di sostituzione permetta di sostituire quello che si vuole. Non Õ cosË, solo alcuni simboli sono considerati dei possibili shortref. In ogni caso, ci si accorge subito quando si usa qualcosa di sbagliato: l'analizzatore SGML avvisa immediatamente.
Attraverso le mappe di sostituzione si possono realizzare anche delle acrobazie che spesso sono poco giustificabili e che sarebbe meglio evitare. A parere di chi scrive, la cosa meno utile che si possa richiedere a un sistema SGML Õ quella di fare in modo che le righe vuote e quelle bianche nel sorgente siano trasformate in separazioni tra i paragrafi. Infatti, l'SGML non ha questo scopo, eppure molti sistemi si impegnano in questo senso. LinuxDoc raggiunge questo risultato intervenendo proprio nelle mappe di sostituzione, facendo in modo che le righe bianche, identificate dal simbolo &#RS;B&#RE;
, e quelle vuote, identificate dal simbolo &#RS;&#RE;
, siano sostituite da <p></p>
, ovvero dai marcatori che servono a chiudere e a riaprire un paragrafo.
... <!ENTITY psplit '</p><p>' > ... <!SHORTREF pmap "&#RS;B" null "&#RS;B&#RE;" psplit "&#RS;&#RE;" psplit ... "{" lcub "}" rcub "|" verbar > ... |
Quello che si vede sopra Õ proprio un estratto dal DTD di LinuxDoc, dove si vede che la macro &psplit;
viene poi rimpiazzata dai marcatori giÞ descritti.
Naturalmente, questo non esclude la possibilitÞ di generare una grande quantitÞ di elementi |
La predisposizione di un elemento SGML che consenta la scrittura di testo da riportare in modo letterale costituisce un problema. Si possono scegliere soluzioni diverse, ma nessuna perfetta secondo tutti i punti di vista.
Questo tipo di problema Õ particolarmente sentito nella scrittura di documenti tecnici, in cui ci puÐ essere la necessitÞ di mostrare porzioni di codice scritto in un qualche linguaggio di programmazione. Per evitare che simboli determinati vengano interpretati dall'analizzatore SGML, occorrerebbe utilizzare continuamente delle macro alternative.
Si possono seguire due direzioni per cercare di risolvere il problema: l'uso di elementi predisposti per un tipo di contenuto piÛ o meno letterale, oppure l'uso di elementi normali con l'aggiunta di una sezione marcata di tipo CDATA
.
Nella definizione di un elemento occorre stabilite il tipo di contenuto. A livello elementare, quando l'elemento non puÐ contenere altri elementi, si utilizza normalmente la parola chiave #PCDATA
, che fa riferimento a testo che viene analizzato alla ricerca di entitÞ generali da espandere, e non ammette altri elementi al suo interno.
Per ottenere un elemento adatto al contenuto letterale, si usa solitamente il tipo di contenuto definito dalla parola chiave RCDATA
, che non Õ perfettamente letterale, ma vi si avvicina molto. Per la precisione, la forma del testo viene mantenuta, con tutte le sue spaziature e le interruzioni di riga, ma le entitÞ generali vengono espanse, mentre vengono ignorati eventuali marcatori di apertura. CiÐ significa che, la e-commerciale (&
) non puÐ essere usata in modo letterale, a meno di usare una macro adatta al suo posto. Lo stesso ragionamento riguarda la sequenza di minore + barra obliqua (</
), che Õ ammessa solo nel marcatore di chiusura di questo elemento.
<!ELEMENT formattato - - RCDATA> |
L'esempio mostra la dichiarazione dell'elemento formattato
, di tipo RCDATA
. Generalmente, per poter utilizzare questo elemento nel modo corretto, si devono dichiarare anche due entitÞ generali specifiche.
<!ENTITY ero CDATA "&"> <!ENTITY etago '</' > |
In tal modo, al posto del simbolo &
si dovrÞ utilizzare la macro &ero;
, mentre al posto della sequenza </
, si dovrÞ usare la macro &etago;
. õ il caso di osservare che l'entitÞ generale ero
Õ volutamente diversa da un'entitÞ analoga, necessaria a indicare una e-commerciale in un testo normale. Infatti, in questo caso, si vuole generare un testo letterale, che si presume possa essere interpretato nello stesso modo letterale anche da altro software di composizione successivo.
In alternativa, si potrebbe usare anche un tipo di contenuto definito dalla parola chiave CDATA
, che dovrebbe essere in grado di ignorare sia i simboli dei marcatori, che le macro delle entitÞ generali. Di fatto perÐ, questo tipo di elemento non dÞ normalmente i risultati sperati.
Nel sorgente SGML, all'interno di un elemento che non sia stato predisposto per un contenuto letterale, Õ possibile inserire una sezione marcata di tipo CDATA
, come nell'esempio seguente:
<![CDATA[ Testo letterale: &, &etago;, <ciao>, </ciao>, ecc., vengono trattati in modo letterale. ]]> |
In tal modo, vengono preservati anche gli spazi, orizzontali e verticali, e ogni eventuale mappa di sostituzione (shortref) viene ignorata temporaneamente. L'unica cosa che non puÐ contenere questo ambiente, Õ la sequenza ]]>
, che serve a concludere la sezione marcata.
Questa tecnica ha il vantaggio di potersi applicare anche a un DTD che non sia stato predisposto con elementi atti all'inserimento di testo letterale. Purtroppo, non tutti gli strumenti SGML sono in grado di riconoscere le sezioni marcate; si pensi ai navigatori, che pur sapendo interpretare l'HTML, non sono sempre in grado di riconoscere tali particolaritÞ.
Nelle sezioni precedenti si Õ visto che il DTD puÐ essere composto da diversi file fisici nel sistema. Lo stesso preambolo di un sorgente SGML prevede la dichiarazione, e l'inclusione, di un DTD. õ stato mostrato come includere un blocco di DTD esterno, attraverso la dichiarazione e il successivo utilizzo di un'entitÞ parametrica che fa riferimento a un file esterno.
Quando si vogliono utilizzare componenti esterni senza fare riferimento a un file preciso, si possono predisporre dei cataloghi, con i quali si esplicitano questi dettagli riferiti al sistema di cui si dispone effettivamente.
Questo tipo di approccio viene usato tipicamente per due motivi: evitare di dover fare riferimento a un file preciso per il DTD nella dichiarazione del tipo di documento all'inizio del sorgente SGML; includere in modo dinamico le entitÞ standard riferite alle lettere accentate e ai simboli speciali. Per quanto riguarda il secondo problema, si deve tenere presente che l'SGML si astrae dalla piattaforma, quindi, il modo in cui le entitÞ di questo tipo vanno rappresentate dipende da quello che si vuole fare dopo.
Generalmente, quando si vogliono usare i cataloghi, si possono fare due tipi di riferimenti a componenti esterne: l'identificatore pubblico e l'identificatore di sistema. Seguono quattro esempi significativi a questo proposito: nei primi due si tratta della dichiarazione del tipo di documento HTML
e di un'entitÞ parametrica, attraverso un identificatore pubblico (una stringa piuttosto lunga); negli ultimi due si tratta delle stesse dichiarazioni, ma fatte attraverso un identificatore di sistema.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> |
<!ENTITY % ISOlat1 PUBLIC "ISO 8879:1986//ENTITIES Added Latin 1//EN"> |
<!DOCTYPE HTML SYSTEM> |
<!ENTITY % ISOlat1 SYSTEM> |
Si tratta, evidentemente, di due approcci equivalenti, ma che hanno delle conseguenze nell'applicazione pratica. Dalle parole chiave utilizzate, PUBLIC
e SYSTEM
, si puÐ intuire che l'identificatore di sistema Õ legato alla situazione del sistema, anche se non Õ obbligatoria l'indicazione immediata del file corrispondente.
L'uso degli identificatori pubblici Õ quindi una scelta piÛ conveniente, essendo meno vincolata alla piattaforma. Infatti, questi vengono utilizzati prevalentemente per tutto ciÐ che Õ giÞ stato standardizzato: i DTD standard e le entitÞ esterne standard.
Quando si usano strumenti di analisi ed elaborazione SGML comuni, il catalogo Õ un file. A seconda degli strumenti utilizzati, potrebbe essere necessario configurare una variabile di ambiente, o usare un'opzione opportuna nella riga di comando, per comunicare a questi la sua posizione.
Il catalogo serve a esplicitare tutte le componenti esterne che non sono state indicate in modo preciso (il nome del file). Si osservi l'esempio seguente:
-- EntitÞ standard richiamate attraverso un identificatore di sistema -- -- Sarebbe meglio non usare questo metodo -- ENTITY %ISOlat1 "ISOlat1" ENTITY %ISOnum "ISOnum" ENTITY %ISOdia "ISOdia" -- EntitÞ standard richiamate attraverso un identificatore pubblico -- -- Questo tipo di indicazione Õ preferibile in generale -- PUBLIC "ISO 8879:1986//ENTITIES Added Latin 1//EN" "ISOlat1" PUBLIC "ISO 8879:1986//ENTITIES Numeric and Special Graphic//EN" "ISOnum" PUBLIC "ISO 8879:1986//ENTITIES Diacritical Marks//EN" "ISOdia" -- DTD predefinito per il tipo HTML -- DOCTYPE "HTML" "html32.dtd" -- Identificatori pubblici per le varie forme dell'HTML 3.2 -- PUBLIC "-//W3C//DTD HTML 3.2//EN" "html32.dtd" PUBLIC "-//W3C//DTD HTML 3.2 Draft//EN" "html32.dtd" PUBLIC "-//W3C//DTD HTML 3.2 Final//EN" "html32.dtd" |
Ogni direttiva dell'esempio occupa una riga e si compone di tre parti, dove l'ultima informazione rappresenta il file da utilizzare per quel particolare tipo di entitÞ, documento o identificatore pubblico.
Per la precisione, invece che di file, occorrerebbe parlare di identificatore di sistema effettivo, dove questo concetto viene poi definito dallo standard ISO 8879. In generale si tratta di file, e questo dovrebbe bastare come primo approccio all'SGML. |
Si noti che i commenti sono delimitati da coppie di trattini,
, come si fa all'interno delle istruzioni SGML.
-
-
PUBLIC <identificatore-pubblico> <identificatore-di-sistema> |
Stabilisce l'identificatore di sistema effettivo (il file) corrispondente all'identificatore pubblico indicato. Quando possibile, Õ preferibile utilizzare gli identificatori pubblici per definire gli oggetti.
DOCTYPE <nome> <identificatore-di-sistema> |
Stabilisce l'identificatore di sistema effettivo (il file) corrispondente al nome del tipo di documento indicato. Dal momento che questo nome puÐ fare riferimento a uno tra diversi DTD alternativi (si pensi al caso dell'HTML con le sue versioni), questa dichiarazione serve prevalentemente per stabilire un DTD predefinito nel caso in cui non sia stato specificato un identificatore pubblico nel documento che si elabora.
ENTITY <nome> <identificatore-di-sistema> |
Stabilisce l'identificatore di sistema effettivo (il file) corrispondente all'entitÞ generale indicata.
ENTITY %<nome> <identificatore-di-sistema> |
Stabilisce l'identificatore di sistema effettivo (il file) corrispondente all'entitÞ parametrica indicata. Si osservi il fatto che il simbolo di percentuale Õ attaccato al nome dell'entitÞ.
Negli esempi seguenti, viene mostrata prima l'istruzione utilizzata nel DTD, o nel preambolo del sorgente SGML, quindi si presenta la direttiva corrispondente, necessaria nel catalogo.
---------
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> |
Si tratta della dichiarazione, all'inizio di un sorgente SGML, dell'utilizzo del DTD HTML
, definito in base all'identificatore pubblico -//W3C//DTD HTML 3.2 Final//EN
. PerchÈ da questo si possa arrivare a identificare un file particolare, occorre che nel catalogo appaia una direttiva come quella seguente:
PUBLIC "-//W3C//DTD HTML 3.2 Final//EN" "html32.dtd" |
In tal caso, all'identificatore pubblico -//W3C//DTD HTML 3.2 Final//EN
, viene abbinato il file html32.dtd
.
---------
<!DOCTYPE HTML SYSTEM"> |
Si tratta della dichiarazione, all'inizio di un sorgente SGML, dell'utilizzo del DTD HTML
, utilizzando un identificatore di sistema che non viene precisato in modo effettivo. PerchÈ da questo si possa arrivare a identificare un file particolare, occorre che nel catalogo appaia una direttiva come quella seguente:
DOCTYPE HTML "html32.dtd" |
In tal caso, all'identificatore di sistema HTML
, viene abbinato il file html32.dtd
(l'identificatore di sistema effettivo).
---------
<!ENTITY % ISOlat1 PUBLIC "ISO 8879:1986//ENTITIES Added Latin 1//EN"> |
All'interno del DTD, dichiara l'entitÞ parametrica ISOlat1
definita secondo l'identificatore pubblico ISO 8879:1986//ENTITIES Added Latin 1//EN
. PerchÈ da questo si possa arrivare a identificare un file particolare, occorre che nel catalogo appaia una direttiva simile a una delle due mostrate di seguito:
PUBLIC "ISO 8879:1986//ENTITIES Added Latin 1//EN" "ISOlat1.latex" |
ENTITY %ISOlat1 "ISOlat1.latex" |
Nel primo caso, all'identificatore pubblico ISO 8879:1986//ENTITIES Added Latin 1//EN
, viene abbinato il file ISOlat1.latex
; nel secondo, si specifica direttamente che l'entitÞ parametrica ISOlat1
corrisponde al contenuto del file ISOlat1.latex
.
---------
<!ENTITY % ISOlat1 SYSTEM> |
Nel DTD, viene dichiarata l'entitÞ parametrica ISOlat1
, utilizzando un identificatore di sistema che non viene precisato in modo effettivo. PerchÈ da questo si possa arrivare a identificare un file particolare, occorre necessariamente che nel catalogo appaia una direttiva come quella seguente, dal momento che non Õ possibile fare riferimento a un identificatore pubblico:
ENTITY %ISOlat1 "ISOlat1.latex" |
Definisce l'identificatore di sistema effettivo dell'entitÞ parametrica ISOlat1
, facendola corrispondere al file ISOlat1.latex
(l'identificatore di sistema effettivo).
C. M. Sperberg-McQueen, Lou Burnard, Guidelines for Electronic Text Encoding and Interchange (TEI P3), in particolare il secondo capitolo: A gentle introduction to SGML
The SGML Newsletter
The SGML/XML Web Page
---------------------------
Appunti Linux 1999.09.21 --- Copyright © 1997-1999 Daniele Giacomini -- daniele @ pluto.linux.it
1.) In questo momento puÐ apparire strano l'uso di questa forma di eccezione. Tuttavia, per comprenderne meglio il senso, occorrerebbe conoscere come funzionano le entitÞ parametriche che sono descritte piÛ avanti. Con queste si puÐ definire un modello del contenuto attraverso una sorta di variabile, e in tal caso, potrebbe essere conveniente l'indicazione di una o piÛ eccezioni, sia in aggiunta che in detrazione.
2.) Le entitÞ standard ISO 8879, sono distinte in 19 gruppi, che in parte si sovrappongono (a volte si ripetono alcune dichiarazioni nello stesso modo). Questi 19 gruppi di entitÞ corrispondono ad altrettanti file, per i quali esiste anche un nome stabilito.
3.) Il contenuto delle stringhe delimitate riguarda i programmi che fanno uso del documento dopo l'analisi SGML. Dipende da loro il senso che hanno queste informazioni.