HTML-kieli perustuu SGML:ään. Tämän takia on hyvä tietää jotain SGML:stä, jos tuottaa HTML-dokumentteja.
Erityisesti on huomattava, että HTML-kielen syntaksi on määritelty SGML:n merkintätavoilla. Tätä varten perehdyin hiukan SGML:ään ja samalla kirjoitin tämän jutun - jäsentääkseni ajatuksiani ja auttaakseni ehkä muita tutustumaan SGML:ään nopeammin.
Eräs käytännön tilanne, jossa HTML-sivujen tekijä tarvitsee perustietoja SGML:stä, on validointi tilanteessa, jossa tietoisesti halutaan käyttää kielen spesifikaatioon kuulumattomia piirteitä. Aiheesta on esimerkki dokumentissani JavaScript and HTML: possibilities and caveats.
Esitys on kirjoitettu olettaen, että lukijalla on jossain määrin käsitystä formaaleista järjestelmistä kuten säännöllisistä lausekkeista (regular expressions).
Pääpaino on SGML:n selittämisellä siinä määrin, kuin HTML:n syntaksin tarkan kuvauksen ymmärtäminen vaatii. - Tässä käytetään esimerkkinä HTML-kielen versiota HTML 3.2:ta. Sen virallinen kuvaus, W3C:n määrittelemä HTML 3.2 Reference Specification sisältää sekä HTML 3.2:n yhtenäisen SGML-kielisen kuvauksen että otteita siitä kielen eri piirteiden sanallisessa selostamisessa. (HTML:n eri versioiden välillä ei ole aiheemme kannalta suurtakaan merkitystä.)
SGML, Standard Generalized Markup Language, on yleinen dokumenttien rakenteen kuvaamisen kieli. Se sisältää välineet kuvata dokumenttityyppejä (document type). Dokumenttityyppiä vastaa kieli, jolla dokumentti kirjoitetaan. Eräs tällainen tyyppi HTML, joka on tarkoitettu hypertekstidokumentteja varten. (Oikeastaan se on joukko lähisukuisia tyyppejä, sillä HTML:stähän on useita versioita.)
SGML voidaan siis käsittää metakieleksi, jolla kuvataan dokumenttityyppejä vastaavia kieliä (esim. HTML-kieli).
HTML ei kaikilta osin ole mitenkään tyypillinen tai ideaalinen esimerkki SGML:n käytöstä. Osasyynä tähän on se, että HTML on pikemminkin vähitellen muodostunut kuin järjestelmällisesti suunniteltu.
SGML:ssä dokumenttityypin määrittely
(document type definition, DTD) kuvaa dokumentin muodollisen
syntaksin kuten sen, millaisia rakenteita mikin
rakenne saa sisältää. Rakenteiden merkitys (tulkinta) esitetään
erikseen luonnollisella kielellä; tällaisia selityksiä voidaan
liittää myös dokumenttityypin määrittelyyn
kommentteihin. Yksinkertaisimmassa tapauksessa
kommentti alkaa merkkiyhdistelmällä
<!--
ja loppuu merkkeihin
-->
.
Dokumentin sisältämiä rakenteita kutsutaan elementeiksi. (Käytän tässä yhteydessä sanaa elementti englannin sanan element vastineena, koska "suomalaisempi" vastine alkio olisi harhaanjohtava: elementti voi olla hyvinkin laaja ja kompleksinen; esimerkiksi jokainen HTML-tiedosto kokonaisuudessaan on periaatteessa yksi elementti.)
Elementtien yleinen rakenne on seuraava:
<
elementinnimi määritteitä>
, mistä
määritteet voivat puuttua
<
/elementinnimi>
ja joka voi monissa
tilanteissa puuttua (tai jopa olla kielletty).
Elementin määrite (attribute) koostuu
jostakin avainsanasta, yhtäläisyysmerkistä ja määritteen arvosta.
Erikoistapauksena voivat yhtäläisyysmerkki ja määritteen arvo puuttua,
mikä tarkoittaa, että määritteen arvo on sama kuin avainsana.
(Esim. määrite COMPACT
tarkoittaa samaa kuin
COMPACT=COMPACT
.)
Esimerkki elementistä HTML-kielessä
(
H1
-elementti)
<H1 ALIGN=CENTER>Johdanto</H1>
Edellä sanottu pätee dokumenttityypistä riippumatta eli kyse on kaikille SGML:n avulla määriteltäville kielille yhteisistä piirteistä. Dokumenttityypin määrittelyssä on olennaista, että se kertoo elementtien yksityiskohtaisen syntaksin: mitä elementtien nimiä on, mitä määritteitä kuhunkin elementtiin voidaan liittää, mitä arvoja kullakin määritteellä voi olla ja millaisia elementtejä kunkin elementin sisällössä voi olla. Lisäksi se kertoo mm. sen, mistä elementeistä lopetustägi voidaan tai täytyy jättää pois.
Elementin perussyntaksi määritellään esim. seuraavaan tapaan:
<!ELEMENT H1 - - %text>
Tämä määrittelee, että H1
on yksi mahdollinen elementinnimi ja että
H1
-elementin sisällön tulee vastata määrittelyä
%text
(johon palataan
jäljempänä
mutta joka sisältää mm. pelkän tekstin ja
erilaisia korostuselementtejä mutta ei esim. otsikkoelementtejä).
Miinusmerkit
- -
tarkoittavat, että aloitus- ja lopetustägi ovat
molemmat pakollisia; jos miinusmerkin tilalla on O
-kirjain
(joka johtuu sanasta optional)
niin vastaava tägi saadaan (ja eräissä tilanteissa täytyykin) jättää
pois. Esimerkiksi HTML-kielen P
-elementin määrittely on
seuraava:
<!ELEMENT P - O (%text)*>
Ilmaisu, joka kuvaa elementin sallitun sisällön (edellä
olevassa esimerkissä %text
), on
luonteeltaan ns. säännöllinen lauseke (regular expression);
aloitussymbolina on periaatteessa HTML-niminen elementti.
SGML:ssä käytetään tässä yhteydessä seuraavia symboleita:
, | peräkkäisyys (katenaatio) |
---|---|
& | peräkkäisyys siten, että järjestys on vapaa |
| | vaihtoehtoisuus (tai-operaattori) |
? | (edeltävän rakenteen) valinnaisuus |
* | (edeltävän rakenteen) valinnaisuus ja toistettavuus |
+ | (edeltävän rakenteen) toistettavuus. |
() | ryhmittely. |
Esimerkiksi määrittely
<!ELEMENT TABLE - - (CAPTION?, TR+)>
sanoo, että
TABLE
-elementti
koostuu yhdestä tai useammasta
TR
-elementistä, joita voi edeltää
CAPTION
-elementti.
Jos plussan tilalla olisi tähti, niin myös sellainen rakenne olisi
sallittu, jossa ei ole yhtään TR
-elementtiä.
Jos kysymysmerkki puuttuisi, niin
CAPTION
-elementti olisi pakollinen.
Jos pilkun tilalla olisi
&
-merkki, niin CAPTION
-elementti voisi
sijaita myös TR
-elementtien jälkeen (mutta ei
silloinkaan niiden välissä).
Elementin sallitun sisällön kuvaava ilmaisu voi myös olla sana
EMPTY
, jolloin kyseessä on tyhjä elementti.
Tämä tarkoittaa sitä, että elementillä ei voi olla sisältöä eikä
sillä tarvitse eikä saa olla lopputägiä. Elementti siis koostuu
pelkästään alkutägistä. Tällainen elementti ei suinkaan yleensä
ole semanttisesti tyhjä. Esimerkiksi HTML-kielessä
HR
-elementti
(pelkkä <HR>
) on syntaktisesti
tyhjä edellä kuvatussa mielessä, mutta sillä on toki vaikutus.
Elementin määrittelyssä voi olla
(merkkien
<
ja
>
välissä)
myös kommentti, joka
alkaa merkkiparilla
--
ja loppuu samanlaiseen merkkipariin.
Elementin perussyntaksin määrittely ei sisällä tietoja mahdollisista määritteistä, vaan sellaiset tiedot annetaan erikseen seuraavaan tapaan:
<!ATTLIST H1 ALIGN (LEFT | CENTER | RIGHT) #IMPLIED >
Tämä tarkoittaa, että
H1
-elementin määritelistassa (attribute list) on
vain yksi mahdollinen määrite, nimeltään
ALIGN
, ja sen mahdolliset
arvot ovat LEFT
,
CENTER
ja RIGHT
.
(Näissä isojen ja pienten kirjainten ero ei ole merkitsevä.
Tosin tämä periaatteessa riippuu kielen ns. SGML-deklaraatiosta).
Symboli
|
tarkoittaa SGML:ssä
yleisesti vaihtoehtoisuutta, tai-operaattoria. Määrittelyssä oleva
sana #IMPLIED
tarkoittaa, että määrite ei ole pakollinen. Vastaavasti
sana #REQUIRED
tarkoittaa, että määrite on pakollinen.
Jos lopussa ei ole näitä kumpaakaan vaan jokin muu merkintä, se
tarkoittaa, että määrite ei ole pakollinen ja että sen oletusarvo
(default) on se, jonka merkintä ilmoittaa.
(HTML:n kuvauksessa tätä ei useinkaan käytetä, koska oletusarvo voi
riippua asiayhteydestä tai implementaatiosta.)
Esimerkiksi HTML:n
TH
- ja
TD
-elementtien määrittelyssä esiintyvä
attribuuttimäärittely
rowspan NUMBER 1 -- number of rows spanned by cell --
tarkoittaa, että
rowspan
-attribuutti voi puuttua, mikä vastaa
tilannetta
rowspan=1
.
Tavallisimmin !ATTLIST
-rakenteessa esitetty määritteen kuvaus
käyttää jotakin seuraavista avainsanoista:
avainsana | merkitys |
---|---|
CDATA | merkkijono |
NAME | nimi: alkaa kirjaimella (A-Z, a-z) ja saa sisältää kirjaimia ja numeroita |
ID | nimi, joka on yksiselitteinen dokumentin sisällä |
IDREF | viittaus (muualla määriteltyyn) nimeen |
NUMBER | luku: (etumerkitön) numeroiden jono |
NMTOKEN | kuten nimi, mutta saa alkaa numerolla |
Huomautuksia:
IDREFS
, joka tarkoittaa
listaa IDREF
ejä, erottimena blanko.
NAME
tai
NUMBER
, sen saa kirjoittaa lainausmerkkeihin,
esim. ROWSPAN="3"
.
Tämä voi olla hyvä ajatus yhtenäisyyden vuoksi - ja siksi, etteivät
lainausmerkit niin helposti unohtuisi silloin, kun ne tarvitaan!
SGML:llä kuvatun kielen ilmaisut ovat yhdeltä kannalta katsottuna
merkkien jonoja, ja rakenteellisesti alimman tason rakenteen kielessä
ovat sellaisia elementtejä, joiden sisältönä on pelkkää tekstiä.
Tällainen sisältö ilmaistaan symbolilla
CDATA
tai symbolilla
#PCDATA
. Jälkimmäisessä tapauksessa kyseessä on ns.
parsed character data, mikä tarkoittaa, että sen
tulkinnassa eräillä merkkiyhdistelmillä,
ns. entiteeteillä,
on erikoismerkitys siihen
tapaan, että ä
saattaa
tarkoittaa ä
-kirjainta
(ja jos &
-merkki halutaan esittää, on käytettävä
sille merkintää &
).
Huomautus: elementin sisällön kuvauksessa
CDATA
merkitsee,
että mainittuja entiteettejä ei tulkita (t.s. &
-merkki tarkoittaa
aina vain itseään), kun taas määritteen kuvauksessa
sillä on olennaisesti sama merkitys kuin #PCDATAlla (t.s.
entiteetit tulkitaan).
Merkistönä on yleensä ISO Latin 1 tai jokin sitä laajempi merkistö, esim. Unicode, mutta periaatteessa SGML-kielellä voidaan määritellä, mitä merkistöä käytetään.
SGML:ssä voidaan käyttää eräitä yksinkertaisia makron tapaisia rakenteita, joista käytetään nimitystä entiteetti, engl. entity.
Esimerkiksi HTML:n käyttäjälle tuttu merkintä ä
on tavallaan makron auml
kutsu. SGML:llä määritellyissä
kielissä "makron" kutsu siis alkaa &
-merkillä ja loppuu
puolipisteeseen, joskin puolipiste voidaan joissakin tilanteissa
jättää pois. Kyseisen "makron"
eli entiteetin
määrittely on seuraavanlainen:
<!ENTITY auml CDATA "ä" -- small a, dieresis or umlaut mark -->
Tässä siis määrittely esitetään yksinkertaisesti merkkijonona, joka sisältää ä-kirjaimen (ISO-Latin-1:n mukaisen) koodiarvonsa avulla esitettynä.
Rakenne ä
on sekin tavallaan makro. Sentapaisten merkintöjen
virallinen nimitys on numerical character reference
Periaatteessa sen, miten
tällaiset
merkinnät tulkitaan, määrää ns. document character set,
joka HTML:n osalta on Unicode.
HTML:ssä siis merkintä &#n; tarkoittaa
aina sitä merkkiä, jonka koodi Unicodessa
on n (jos sellainen on olemassa).
Nimitys document character set
on huomattavan harhaanjohtava, koska se tarkoittaa nimenomaan ja
vain tätä määrätyntyyppisten entiteettien tulkintaa! Sillä ei ole
mitään tekemistä sen kanssa, millaisia merkkejä ja minkä
merkkikoodin mukaan dokumentissa esiintyy.
Esimerkin pohjalta lienee helppo ymmärtää ja muistaa, että
makrojen nimissä isojen ja pienten kirjainten ero on merkitsevä,
toisin kuin esim. elementtien nimissä. (Makron auml
lisäksi
on määritelty makro Auml
, jolla saadaan iso Ä-kirjain.)
Periaatteessa nämä seikat tosin ovat sellaisia piirteitä, jotka
ovat määriteltävissä SGML-kielellä, eivät itse SGML:n piirteitä.
Makrojen kutsuja voidaan siis käyttää sellaisessa kielessä (esim. HTML:ssä),
joka on määritelty SGML:llä, jos makro on määritelty kyseisen
dokumenttityypin yhteydessä. Toisentasoisia makroja,
parameter entities, ovat ne, joita käytetään metakielessä
eli SGML:ssä (siis esim. HTML:n kuvauksessa, ei itse HTML:ssä).
Niiden määrittelyissä ja kutsuissa käytetään %
-merkkiä
erottamaan ne edellä kuvatuista makroista. Esimerkiksi HTML:n
SGML-kielisessä kuvauksessa esiintyvät
seuraavat makronmäärittelyt:
<!ENTITY % font "TT | I | B | U | STRIKE | BIG | SMALL | SUB | SUP"> <!ENTITY % phrase "EM | STRONG | DFN | CODE | SAMP | KBD | VAR | CITE">
Näistä esimerkiksi edellinen tarkoittaa yksinkertaisesti sitä, että
%font
on
lyhennysmerkintä ilmaisulle
TT | I | B | U | STRIKE | BIG | SMALL | SUB | SUP
.
Täten
esimerkiksi määrittely
<!ELEMENT (%font|%phrase) - - (%text)*>
on lyhennysmerkintä, joka tarkoittaa seuraavaa:
<!ELEMENT (TT | I | B | U | STRIKE | BIG | SMALL | SUB | SUP | EM | STRONG | DFN | CODE | SAMP | KBD | VAR | CITE) - - (%text)*>
ja siis yhdellä kertaa määrittelee varsin monien HTML-elementtien
perussyntaksin.
Tässä tietysti myös %text
on lyhennysmerkintä;
sen määritelmä on seuraava:
<!ENTITY % text "#PCDATA | %font | %phrase | %special | %form">
Muutoinkin lyhennysmerkintöjen käyttö on olennaista, jotta mm. HTML-kielen SGML-kielinen kuvaus on saatu kohtuullisen lyhyeksi ja tiiviiksi.
Koska pelkät säännölliset lausekkeet eivät aina ole riittävän ilmaisuvoimainen keino, on SGML:ssä myös mahdollisuus esittää ns. poikkeuksia (exceptions). Tätä nimitystä käytetään kahdesta varsin erityyppisestä asiasta:
Ekskluusio ilmaistaan siten, että määrittelevän ilmaisun loppuun kirjoitetaan miinusmerkki ja sitten ilmaisu, joka esittää kielletyt elementit. Inkluusio on syntaksiltaan vastaava siten, että miinusmerkin tilalla on plusmerkki.
Esimerkkejä HTML:n määrittelystä:
<!ENTITY % pre.exclusion "IMG|BIG|SMALL|SUB|SUP|FONT"> <!ELEMENT PRE - - (%text)* -(%pre.exclusion)>
Tämä tarkoittaa, että
PRE-elementin
sisältönä saa olla mikä tahansa
tekstielementtien jono, kunhan mikään niistä tai mikään niiden
sisältämä elementti ei ole
IMG
-,
BIG
-,
SMALL
-,
SUB
-,
SUP
- tai FONT
-elementti. Huomattakoon,
että "positiivisempi" määrittely, jossa ilman ekskluusiota vain
lueteltaisiin muut tekstielementit kuin nuo kielletyt, ei olisi
riittävä. Sellainen määrittely nimittäin kieltäisi esim.
IMG
-elementin esiintymisen vain ylimmällä rakennetasolla PRE-elementin
sisällössä.
<!ENTITY % head.misc "SCRIPT|STYLE|META|LINK" -- repeatable head elements --> <!ENTITY % head.content "TITLE & ISINDEX? & BASE?"> <!ELEMENT HEAD O O (%head.content) +(%head.misc)>
Tässähän head.misc
on yksinkertainen makro (jossa piste on
osa makron nimeä ilman erikoismerkitystä), samoin head.content
.
Itse määrittely kertoo
HEAD
-elementistä
seuraavat asiat:
HEAD
-elementti alkaa ja
mihin se loppuu
TITLE
-elementti, minkä lisäksi voi
olla yksi ISINDEX
-elementti tai yksi
BASE
-elementti tai molemmat,
ja näiden keskinäinen järjestys on vapaa
SCRIPT
-,
STYLE
-, META
- ja
LINK
-elementtejä
missä tahansa; niitä voi olla myös miten monta tahansa, sillä
inkluusio-operaatioon tavallaan itseensä sisältyy
toistomahdollisuus.
Itse SGML-standardia, ISO 8879:1986, ei ole Webissä, koska tekijänoikeuden omistaja ISO ei sitä halua.
SGML-kielen täydellisimpänä kuvauksena voidaan pitää sitä, joka sisältyy seuraavaan (varsin raskaslukuiseen ja laajaan, 663 s.) kirjaan, joka sisältää myös koko standardin:
Goldfarb, Charles F.: The SGML handbook
Oxford, 1990. Clarendon Press.
ISBN 0-19-853737-9. UDK: 681.3.06
Standardia tai kirjaa luettaessa voi olla apua Chris Madenin koosteesta Productions from ISO 8879:1986 - SGML, jossa on tiivistettynä SGML:n itsensä syntaksi.