Rivinvaihdot ja kappaleet datan käsittelyssä, luku 2 Rivinvaihtojen esitystapoja:

SGML-pohjaiset kielet (mm. HTML)

SGML on metakieli, jolla voidaan määritellä erilaisia merkkauskieliä, tarkemmin sanoen niiden muodollinen rakenne eli syntaksi. Suurelle yleisölle tunnetuin tällainen kieli on HTML. Tosin todellisuudessa HTML:n SGML-pohjaisuus on osittain vain nimellistä.

SGML:llä määritellyssä kielessä rivirakenne on periaatteessa sellainen, että kukin rivi alkaa rivinaloituskoodilla ja päättyy rivinlopetuskoodilla. Näille koodeille käytetään symboleita RS ja RE (jotka johtuvat sanoista record start ja record end), mutta kyse on tällöin ns. abstraktista syntaksista, ei mistään kiinteästi määrätyistä koodeista. Ns. konkreettisessa syntaksissa tällaiset asiat kiinnitetään jollakin tapaa, ja oletusarvoisesti (ns. reference concrete syntax) RS on LF ja RE on CR.

Tosin SGML kaikessa käsitteellisyydessään ja yleisyydessään lähtee siitä, että datalla ei tarvitse olla rivirakennetta, tai kuten SGML:ssä sanotaan: tietuerakennetta. Mutta SGML-standardi sanoo, että jos sellainen rakenne on, niin sen tulee noudattaa edellä mainittuja sääntöjä.

Tämä merkitsee, että verrattuna muotoon, jossa rivinvaihtona on CR LF, SGML-pohjaisessa kielessä tulisi periaatteessa olla LF koko datan alussa (ensimmäisen rivin aloituskoodina) ja lisäksi CR viimeisen rivin lopussa. Tätä suhteellisen harvoin noudatetaan, ja käytännössä mainitunlaisia kieliä käsittelevien ohjelmien edellytetään selviävän perinteisemmästäkin formaatista. Hiljentykäämme seuraamaan ankaraa käsien vatkutusta HTML 2.0 -spesifikaatiossa:

SGML specifies that a text entity is a sequence of records, each beginning with a record start character and ending with a record end character (code positions 10 and 13 respectively) (section 7.6.1, "Record Boundaries" in [SGML]).

[MIME] specifies that a body of type `text/*' is a sequence of lines, each terminated by CRLF, that is, octets 13, 10.

In practice, HTML documents are frequently represented and transmitted using an end of line convention that depends on the conventions of the source of the document; frequently, that representation consists of CR only, LF only, or a CR LF sequence. Hence the decoding of the octets will often result in a text entity with some missing record start and record end characters.

Since there is no ambiguity, HTML user agents are encouraged to infer the missing record start and end characters.

An HTML user agent should treat end of line in any of its variations as a word space in all contexts except preformatted text. Within preformatted text, an HTML user agent should treat any of the three common representations of end-of-line as starting a new line.

Hypertext Markup Language - 2.0, kohta Conventional Representation of Newlines

Uudemmat spesifikaatiot näyttävät vaikenevan tästä nolosta asiasta. Monella muullakin tavalla HTML 2.0 -spesifikaatio on selkeydessä merkittävä parannus seuraajiinsa nähden.

Edellä olevan lainauksen viimeinen kappale sanoo olennaisesti sen, että rivinvaihdon teknisestä esitysmuodosta riippumatta HTML:ssä rivinvaihto vastaa välilyöntiä.

Tähän on kuitenkin eräs näennäisesti pieni poikkeus: SGML:n yleiset säännöt sanovat, että aloitustägiä (esim. <p>) välittömästi seuraava rivinvaihto tulee jättää huomiotta, samoin lopetustägiä (esim. </p>) välittömästi edeltävä rivinvaihto. Tällä on merkitystä, koska useissa tilanteissa ei ole yhdentekevää, onko tägin ja sitä seuraavan tai edeltävän tekstin välissä välilyönti vai ei mitään. HTML 4.0 -spesifikaatio erikseen mainitsee tämän asian (liitteen B kohdassa line breaks), mutta käytännössä tämä on ymmärrettävä varoitukseksi siitä, että selaimet yleisesti eivät noudata tätä sääntöä. Tällöin esimerkiksi rakenne

<td><img src="foo.gif" alt="bar">
</td>
ei tarkoitakaan samaa kuin
<td><img src="foo.gif" alt="bar"></td>
kuten pitäisi vaan samaa kuin
<td><img src="foo.gif" alt="bar"> </td>
Ja kun sitten selaimet saattavat tulkita kuvaa seuraavan välilyönnin dataksi, joka vaikuttaa dokumentin esitysmuotoon, seurauksena on usein ikävä pieni kummallisuus kuten ylimääräinen reunus jossakin. Niinpä HTML:ää kirjoittavan onkin syytä varautua siihen, että selaimet ovat näkevinään välilyöntejä sielläkin, missä niitä ei ole; täten voi olla hyvä opetella kirjoittamaan lopetustägi rivin loppuun eikä seuraavan rivin alkuun. Ks. White Space Bugs in Browsers.

Muista Web-selainten virheistä mainittakoon se, että ne eivät suinkaan aina käsittele rivinvaihtoja oikein määritteiden (attributes) arvojen sisällä. Tämä aiheuttaa ongelmia mm. alt-määritteiden kirjoittamisessa.

Edellä sanottu koskee HTML:llä (tai muulla SGML-pohjaisella kielellä) kirjoitetun dokumentin rakennetta. Tästä on tarkoin erotettava dokumentin mahdollinen näkyvä esitys esimerkiksi sellaisena, kuin Web-selain sen muotoilee kuvaruudulle tai paperille. Tätä koskeva menettely on parhaiten kuvattu HTML 2.0 -spesifikaatiossa:

An HTML user agent should present the body of an HTML document as a collection of typeset paragraphs and preformatted text. Except for preformatted elements (PRE, XMP, LISTING, TEXTAREA), each block structuring element is regarded as a paragraph by taking the data characters in its content and the content of its descendant elements, concatenating them, and splitting the result into words, separated by space, tab, or record end characters (and perhaps hyphen characters). The sequence of words is typeset as a paragraph by breaking it into lines.

Hypertext Markup Language - 2.0, kohta Characters, Words, and Paragraphs

Täten siis selain olennaisesti lukee tekstidatan, erottelee sen "sanoiksi" eli osiksi, joita erottavat toisistaan välilyönnit, sarkainmerkit tai rivinvaihdot, ja sitten "latoo" tekstin kappaleiksi, jotka jakautuvat riveihin sopivalla tavalla. Olennaista on, että tieto siitä, mitä "sanojen" välissä oli (esim. välilyönti tai rivinvaihto, tai montako välilyöntiä), putoaa pois, ennenkuin selain rupeaa muotoilemaan tulostusta.

Edellä lainatussa tekstissä oleva maininta "(and perhaps hyphen characters)" on osoittautunut pahaenteiseksi. Useimmat Web-selaimet eivät käsittele yhdysmerkkiä (hyphen, oikeastaan hyphen-minus) datassa millään erityisellä tavalla. Mutta Internet Explorer tulkitsee sen kohdaksi, josta sanan saa jakaa eri riveille. Tämä on jo itsessään kyseenalainen ratkaisu, mutta järjettömäksi sen tekee se mekaanisuus, jolla IE sitä käsittelee. Se kylmän tyynesti jakaa myös esimerkiksi ilmaisun "control-J" kahdelle riville. Se vieläpä käsittelee esimerkiksi tekstin "tuloaika ja -paikka" niin, että "-paikka" on sana, jonka voi rivitystä varten jakaa osiin "-" ja "paikka"! Valitettavasti ainoa tehokas tapa estää moinen tolkuttomuus on ilmeisestikin käyttää nobr-merkkausta (esim. <nobr>control-J</nobr>), joka ei kuulu mihinkään HTML-määrittelyyn mutta toimii useimmissa selaimissa.

HTML-kielessä voidaan kyllä pakottaa rivinvaihto dokumentin näkyvään esitysmuotoon, mutta tätä ei tehdä millään ohjauskoodeilla vaan erityisellä tägillä, <br>. Tämä tägi sopii huonosti HTML:n yleisiin periaatteisiin, koska se ei varsinaisesti kuvaa dokumentin rakennetta vaan pikemminkin ulkoasua. Lisäksi kun esimerkiksi kappale esitetään elementtinä, jolla on aloitustägi, sisältö ja lopetustägi, olisi loogista, että vastaavasti on rivielementti, jos rivirakenne ylipäänsä otetaan mukaan. Voidaankin sanoa, että <br>-tägi otettiin kieleen keinotekoisesti, rivinvaihdon ohjauskoodien melko suoraksi vastineeksi.