6 DTD ja dokumentin tyyppimääritys XML-merkkaus tarjoaa yhteensopivan ja yksinkertaisen perustan rakenteisten dokumenttien tms. rakenteisen tiedon käsittelyyn. Tietojenkäsittelyn sovelluksissa päähuomio ei kuitenkaan yleensä ole merkkauksessa, vaan sen perusteella loogisesti jäsennettävissä olevissa (puumaisissa) tietorakenteissa SVG-kuvat Tyypimäärittely lisää sovelluskohtaisia sopimuksia esim. Web-sivujen, vektorikuvien, kirjekuorten ja muistioiden hyväksyttävistä tietorakenteista. (Huom. Yhteisymmärrys rakenteiden toivotusta tulkinnasta vaatii kuitenkin lisämäärityksiä joiden kuvaamiseen tyyppimääritys ei yleensä riitä; esim. ko. tyyppisen dokumentin käsittelijän toiminnallisen määrittelyn.) 112
6.1 Välisoitto Dokumentin tyyppi määrittelee viestin tietorakenteen Kaikki se mitä halutaan esim. mekaanisesti tarkistaa, pitää kuvata tarkasti rakennetasolla Huomaa että myös dokumentin tyyppitieto välittää informaatiota (=dokumentin rakenteen kuvailutietoa) Tyyppiesittely sinänsä ei takaa validiutta se vain ilmoittaa minkä suhteen validointi tulee suorittaa 113
6.2 Dokumentin tyyppimääritys XML-dokumenttien tyyppimääritys tarjoaa keinon jakaa XMLdokumentit hallittaviin aliluokkiin Aliluokan dokumenttien looginen rakenne on ko. aliluokalle tunnusomainen, esim. - kakkuresepteihin liitetään yleensä kakun nimi, valmistusaineet, leipomisohje sekä paistoaika, tietyssä järjestyksessä - novelleihin liitetään yleensä kertomuksen nimi, kirjoittaja, esipuhe, kääntäjän huomautuksia sekä varsinainen tarina luvuiksi ja kappaleiksi jaoteltuna - kirjeessä on yleensä lähettäjän ja vastaanottajan nimi ja osoite, päivämäärä sekä vapaamuotoista sisältötekstiä Dokumenttiluokan esiintymien looginen rakenne voi yleensä myös hieman vaihdella, esim. kirjeessä ei aina ole lähettäjän osoitetta yleensä kaikki dokumenttiluokat ovat juuri tällä tavoin geneerisiä 114
6.3 XML DTD Kuten todettua, XML 1.0 (1.1) sisältää DTD-määrityskielen; vrt. DTD-esittely [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S? ('[' intsubset ']' S?)? '>' [VC: Root Element Type][WFC: External Subset] Tyyppimääritys koostuu erilaisista säännöistä (esim. merkkausesittely tai - julistukset) joka erityisesti asettaa ko. tyypin sallitut elementti- ja attributtirakenteet - notaation määrittely (notation declaration) - elementin tyyppimäärittely (element type declaration) - attribuuttilistan tyyppimäärittely (attribute-list declaration) - entiteetin määrittely (entity declaration) Näistä tarkastelemme aluksi lähemmin elementtejä ja attribuutteja Huom. DTD-kielellä on rasitteenaan SGML-tausta. Vaikka kieli onkin "ruma", "heikko" ja "rajoittunut", on se silti varsin käyttökelpoinen 115
6.4 Esimerkki: dokumenttityypin music määrittely <?xml version="1.0" encoding="iso-8859-1"?> <!ENTITY on "Ossi Nykänen"> <!ELEMENT music (album+)> <!ATTLIST music editor CDATA #IMPLIED> <!ELEMENT album (name, tracks, img?)> <!ATTLIST album artist CDATA #REQUIRED> <!ATTLIST album year CDATA #REQUIRED> <!ELEMENT name (#PCDATA)> <!ELEMENT tracks (track+)> <!ELEMENT track (#PCDATA)> <!ATTLIST track len CDATA #IMPLIED> <!ELEMENT img EMPTY> <!ATTLIST img src CDATA #IMPLIED> 116
6.5 Esimerkki: music-tyyppinen dokumentti <?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE music SYSTEM "cd-music.dtd"> <music editor="&on;"> <album artist="dire Straits" year="1978"> <name>dire Straits</name> <tracks> <track len="5m34s">sultans of swing</track> <track len="6m14s">in the gallery</track> </tracks> <img src="/img/pda/ds-2005-01-09.gif" /> </album> <album artist="pet Shop Boys" year="1993"> <name>very</name> <tracks> <track len="3m55s">yesterday, When I Was Mad</track> </tracks> </album> </music> 117
6.6 Esimerkki: toinen music-tyyppinen dokumentti <?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE music SYSTEM "cd-music.dtd" [ <!ATTLIST music editor CDATA #FIXED "Ossi Oletus" > ]> <music> <album artist="pet Shop Boys" year="1993"> <name>very</name> <tracks> <track len="3m55s">yesterday, When I Was Mad</track> </tracks> </album> </music> Dokumentin tyyppimääritys voi siis jakautua kahteen osaan, jotka yhdessä muodostavat dokumentin tyyppimäärityksen (kokeile rxp -Va): - "vahvempi" sisänen DTD-osajoukko ("vrt. CSS") ja - ulkoinen DTD-osajoukko 118
6.7 Editoriesimerkki: Eclipse & XML Buddy Suosittu & ilmainen kehitysympäristö Eclipse tarjoaa hyviä välineitä myös XML-editointiin yms. Kun dokumentin tyyppi on tiedossa, tietoa voidaan käyttää paitsi dokumenttien validointiin, myös esim. koodin aktiiviseen täydentämiseen 119
6.8 Elementtien tyyppimäärityksen perusteet Elementin tyyppimääritys voi näyttää esim. seuraavalta <!ELEMENT album (name, tracks, img?)> 1 2 Nimen (1) jälkeistä termiä (2) kutsutaan toisinaan elementin tieto- tai sisältömalliksi XML tunnistaa neljä "erilaista" elementtien tyyppimääritystä - element content (vain elementtejä lapsina; ei "ylimääräisiä tyhjäsolmuja") - mixed content (lapsina elementti- ja/tai tekstisolmuja) - EMPTY (ei lapsia; ts. ei teksti- eikä elementtisisältöä) - ANY (lapsina tekstiä tai mitä tahansa esiteltyjä elementtejä) Erot piilevät siinä minkälaisia rakenteita elementin tietomallin määrittelyyn saa kirjoittaa; mallinnuksen näkökulmasta DTD on kuitenkin melko heikko 120
6.9 Esimerkkejä (määritys ja esimerkkimerkkaus) (1) <!ELEMENT example EMPTY> <example/> (2) <!ELEMENT example ANY> <example>hei maailma!<example/></example> (3) <!ELEMENT example (#PCDATA code field)*> <!-- #PCDATA ensin --> <!ELEMENT code (#PCDATA)*> <!--... ja vain... --> <!ELEMENT field (#PCDATA)*> <!-- -operaattori --> <example>hei maailma <field>hej</field> Hi <code>moi</code> Hello </example> (4) <!ELEMENT example (code field?)> <!ELEMENT code (#PCDATA)*> <!ELEMENT field (#PCDATA)*> <example> <field>hej</field> </example> 121
6.10 Sisältönä elementtejä: element content -tietomalli Kun elementin sisältö määritellään element content -tyyppiseksi, voidaan lapsielementtien rakenne määrittää monipuolisesti jo EBNF:stä tuttujen operaattoreiden ja kertojien avulla (toki kyseessä on eri kielioppi), esim.: <!ELEMENT mydoc (title?,code+,(footer comment)?)> XML-DTD tunnistaa seuraavat operaatorit: - A,B (B seuraa A:ta) - A B (A tai B) ja seuraavat kertojat: - A? (A on optionaalinen) - A+ (A esiintyy yhden tai useamman kerran) - A* (A esiintyy yhden tai useamman kerran tai ei ollenkaan) Lausekkeiden ryhmittelyyn käytetään tavallisia sulkuja ("(",")") 122
6.11 Huomautuksia elementtien määrittelystä Sisältömalleja on usein tarkoituksenmukaista jakaa pienempiin osiin sääntöjen lukemisen ja kirjoittamisen helpottamiseksi (huomaa että näin syntyy pakotettu säiliö- tai kääre-elementti): <!ELEMENT mydoc (title?,code+,misc)> <!ELEMENT misc ((footer comment)?)> Mikäli "ylimääräisiä" merkkausrakenteita (yllä misc-elementti) ei dokumentteihin haluta, voidaan elementtien tyyppijulistuksia sieventää ns. parametrientiteettien avulla (näihin palataan myöhemmin) Elementtien sisältömallit voivat olla melko mutkikkaita sisältäen myös rekursiivisia (itseensä viittaavia) rakenteita (rekursioonkin palataan vielä) Yhden ja saman (ei-triviaalin) loogisen elementtirakenteen voi yleensä ilmoittaa useilla erinäköisillä tyyppimäärityksillä (mutta pieni on kaunista) 123
6.12 Attribuuttien tyyppimäärittelyn perusteet (1/3) Attribuutit ovat elementteihin liittyviä "lisämääreitä", esim. tyyliin: <example color="red" shape="circle">hei maailma!</example> Tyyppimääritys asettaa attribuuttien nimet, arvojoukot sekä määrää attribuuttien (pakollisen) esiintymisen elementeissä Tarkastellaan määritystä <!ATTLIST example color CDATA #FIXED "red"> 1 2 3 4 Attribuutin tyyppimääritys sisältää seuraavat termit 1. elementin nimi 2. attribuutin nimi 3. arvoalue (AttType) 4. oletusarvo (DefaultDecl, sis. pakollisuus ja oletusarvo) 124
6.13 Attribuuttien tyyppimäärittelyn perusteet (2/3) Attribuutit määritellään aina tietyntyyppisille (tietynnimisille) elementeille: <!ELEMENT example EMPTY> <!ATTLIST example color (red green blue) "red"> Koska julistukseen kirjoitetaan aina sen elementin nimi, johon attribuuttit voidaan liittää, ovat erityyppisille elementeille esiteltävät samannimiset attribuutit eri attribuutteja, vrt: <!ELEMENT example EMPTY> <!ATTLIST example color (red green blue) "red"> <!ELEMENT code (#PCDATA)> <!ATTLIST code color CDATA "red"> Ts. attribuuttimäärittely sallii myös "intuitiivisesti epäjohdonmukaiset" attribuuttimääritykset jossa samanniminen attribuutti tarkoittaa "eri elementeille eri asiaa" (tätä on toki syytä välttää suunnittelussa) 125
6.14 Attribuuttien tyyppimäärittelyn perusteet (3/3) Oletusarvot määrittelevät onko attribuutti pakko merkata ja jos merkataan, mikä arvo sille pitää asettaa: - #REQUIRED ~ attribuutti pitää merkata - #IMPLIED ~ attribuutin voi merkata - #FIXED ~ attribuutin arvo on (annettu) vakio Toisin sanoen, oletusarvosta johtuen <example color="red" shape="circle"/>...on sama asia kuin: <example shape="circle" color='red'/>...mutta saattaa olla (loogisesti) eri asia kuin: <example color="red"/> 126
6.15 Esimerkkejä erilaisista tyyppimäärityksistä <!ATTLIST example color (red green blue) #REQUIRED> <!ATTLIST example color CDATA #REQUIRED> <!ATTLIST example color (red green blue) "red"> <!ATTLIST example color CDATA #IMPLIED> <!ATTLIST example color CDATA #FIXED "red"> Notaatio mahdollistaa myös kokonaisen attribuuttilistan määrittelyn kerralla: <!ATTLIST example type (theory application) #REQUIRED color CDATA #REQUIRED> On tärkeää huomata, että XML-dokumenttissa näkyvään elementtiin kirjoitettu attribuutin arvo käy aina läpi normalisointiprosessin matkallaan XML-prosessorin läpi kohti sovellusta (tähän palataan pian) 127
6.16 Attribuuttien arvoalueet (1/2) Aikaisemmissa esimerkeissä attribuutin tyyppeinä oli yksinkertaisesti joko merkkidata tai lueteltuja arvojoukkoja, tyyliin: <!ATTLIST example color (red green blue) #REQUIRED> <!ATTLIST example color CDATA #REQUIRED> Käytännössä tämä riittää yleensä mainiosti. XML-prosessori/sovellus - asetelman puitteissa on kuitenkin tilanteita, joissa arvojoukkojen yksityiskohtaisempi määrittäminen on perusteltua, esim. kun - attribuutit viittaavat nimettyihin XML-elementteihin - tiedetään, että sovellus aikoo käyttää (joidenkin) attribuuttien arvoja esim. tiedostoniminä Tavoitteena siis on että validoinnin yhteydessä attribuuttien mielekkyyden tutkiminen onnistuisi jo XML-prosessorin avulla niin pitkälle kuin mahdollista (eikä XML-sovelluksen tarvitsisi enää tarkistaa ko. asioita) 128
6.17 Attribuuttien arvoalueet (2/2) Arvoalue voi olla jotakin seuraavista: - CDATA ~ merkkidataa - lueteltu (enumerated) ~ jokin annetuista tunnistemerkkijonoista - NOTATION ~ jokin annetuista notaatioista - ID ~ ID-attribuutti - IDREF ~ viittaus ID-attribuuttiin - IDREFS ~ luettelo viittauksista ID-attribuutteihin (erottimena tyhjämerkki) - ENTITY ~ entiteetin nimi - ENTITIES ~ luettelo entiteettien nimiä (erottimena tyhjämerkki) - NMTOKEN ~ tunnistemerkkijono - NMTOKENS ~ luettelo tunnistemerkkijonoja (erottimena tyhjämerkki) 129
6.18 Esimerkkejä (1/2) <!ATTLIST example text CDATA #REQUIRED> <example text="ainoastaan < ja &-merkit on koodattava entiteeteillä, #$@!""/> <!ATTLIST example indexpage NMTOKEN #REQUIRED> <example indexpage="etusivu.html"/> <!ATTLIST example pet NMTOKENS #REQUIRED> <example pet="kissa koira marsu härkä muu"/> <!ATTLIST example shape (box circle line) ""> <example shape="box"/> <!ATTLIST example id ID #REQUIRED> <example id="myname"/> <!-- yksikäsitteinen nimi esiintymässä --> <!ATTLIST example href IDREF #REQUIRED> <example href="myname"/> <!-- viittaa ID-nimeen esiintymässä --> 130
6.19 Esimerkkejä (2/2): "vähemmän tarpeellisia" <!ENTITY plant-image SYSTEM "/usr/kukka.gif"> <!ATTLIST example image ENTITY #REQUIRED> <example image="plant-image"/> <!NOTATION gifconv SYSTEM "ps2gif.exe"> <!NOTATION jpgconv SYSTEM "ps2jpg.exe"> <!ATTLIST example imagesrc NMTOKEN #REQUIRED handler NOTATION (gifconv jpgconv) #REQUIRED> <example imagesrc="ratas.ps" handler="gifconv"/> Käytännössä hyödyllisimpiä ovat CDATA, enumerated, ID/IDREF(S), NMTOKEN(S) muille löytyy käyttöä harvemmin 131
6.20 Attribuutin arvon normalisointi (1/2) Myös attribuuttien arvot ovat jäsennettäväksi tarkoitettua tekstiä. Siispä XML-prosessorin sovellukselle välittämä merkkijono ei välttämättä ole täsmälleen sama kuin dokumenttiin kirjoitettu literaaliarvo Attribuuttien arvo siis normalisoidaan ja merkatusta literaalista prosessoidaan (XML-)sovellukselle välitettävä attribuuttiarvo Attribuuttien arvojen normalisointialgoritmi on seuraavanlainen: 1) arvon ympäriltä poistetaan lainausmerkit (tai heittomerkit) 2) merkkiviittaukset korvataan vastaavilla Unicode-merkeillä 3) entiteettiviittaukset korvataan vastaavilla merkkijonoilla (rekursio) 4) kaikki tyhjämerkit (mm. TAB, CR, LF) korvataan "välilyönneillä" 5) jos arvoalue on muu kuin CDATA, poistetaan tyhjämerkit merkkijonon alusta ja lopusta sekä moninkertaiset tyhjämerkit sen sisältä 132
6.21 Attribuutin arvon normalisointi (2/2) Normalisoinnin ansiosta myös attribuuttien arvojen antamisen yhteydessä voi käyttää tyhjämerkkejä ja vaikkapa jakaa arvo usealle riville tyyliin: <!ATTLIST desc text CDATA #REQUIRED>... <desc text="tämä rivi tekstiä on Ö-luokan esimerkki. "> Edellisessä esimerkissä attribuutin text (jonka tyypiksi on annettu CDATA) arvo normalisoidaan muotoon (hakasulut on esimerkissä lisätty ainoastaan havainnollistamaan merkkijonon alku- ja loppukohtia) [Tämä rivi tekstiä on Ö-luokan esimerkki. ] Huomaa, että normalisaatio tuottaa erilaisen arvon, jos attribuutin tyypiksi olisi annettu esim. muodossa NMTOKENS: <!ATTLIST desc text NMTOKENTS #REQUIRED> [Tämä rivi tekstiä on Ö-luokan esimerkki.] 133
6.22 Attribuutit xml:lang ja xml:space xml:space voi saada kaksi eri arvoa: default tai preserve - preserve kertoo XML-sovellukselle että sen "tulisi" ohittaa oletusarvoinen (mielivaltainen) tyhjämerkkien sievennyskäytäntönsä ja huomioida kaikki tyhjämerkit xml:lang voi saada jonkin ISO 639 kielikoodin, IANA-kielikoodin (prefix "i-", "I-") tai sovelluskohtaisen kielikoodin (prefix "x-","x-") - (periytyvä) kielikoodi kertoo (ei pakota!) elementin merkkidatan, attribuuttien arvojen ja lapsielementtien kielen (luonnollisen tai formaalin) Validi dokumentti määrittelee myös attribuutit xml:space ja xml:lang, esim. <!ATTLIST elementname xml:space (default preserve) 'preserve'> <!ATTLIST examplename xml:lang NMTOKEN 'en'> XML-standardiperhe nimeää myös muitakin attribuutteja (esim. xmlns) ja esittää merkityksen näille (näihin palataan myöhemmin) 134
6.23 Dokumentin tyyppimäärityksestä: PUBLIC (1/2) Dokumentin tyyppimääritysten vakiintuessa (kun DTD on suunniteltu, testattu ja havaittu hyväksi), on yleiskäyttöisyyden nimissä järkevää sijoittaa ulkoiset DTD-tiedostot paikkaan, josta ne ovat yleisesti saatavilla, esim. HTTP-palvelinhakemistoon ja käyttää DTD-osajoukkoja tyyliin: <?xml version="1.0"?> <!DOCTYPE mydoc SYSTEM "http://www.rakdok.com/mydoc.dtd"> Laajamittaisena tämä on kuitenkin epäkäytännöllistä ja tehotonta, etenkin jos DTD saa yleisesti hyväksyttävän standardin arvon ja kaikki viittaavat siihen! Ratkaisu: yleisesti tiedossa olevat dokumenttityypit nimetään, liitetään suoraan osaksi XML-parsereita ja DTD-osajoukko valitaan dokumentin tyyppijulistuksessa avainsanan PUBLIC avulla tyyliin: <?xml version="1.0"?> <!DOCTYPE mydoc PUBLIC "-//RAKDOK//DTD MYDOC//EN" "http:...dtd"> 135
6.24 Dokumentin tyyppimäärityksestä: PUBLIC (2/2) PUBLIC-avainsanaa seuraava literaali ei ole nyt suora viittaus tiedostoon, vaan DTD-osajoukon julkinen tunnistenimi (public identifier), joka sisältää seuraavat kentät: - alkaa avainsanalla "ISO" jos määrityksellä on ISO-standardin arvo - "+" jos muu merkittävä standardi, "-" jos ei ole - "//" DTD:n omistajan tunnus - "//" tiedoston tyyppi (esim. "DTD) - välilyönti " " ja dokumentin nimi - "//" kielikoodi (ISO 639) 136
6.25 <?xml...?> ja standalone Dokumentin jäsentämiseen liittyy myös tieto siitä, onko dokumentin käsittely mahdollista ilman ulkoisen DTD-osajoukon (tiedoston) lataamista Mikäli ulkoista osajoukkoa ei (kyseisen dokumentin tapauksessa) välttämättä tarvita dokumentin esiintymän lukemiseen, voidaan dokumentin alkuun lisätä riippumattomuusesittely (standalone declaration): <?xml version="1.0"encoding="iso-8859-1" standalone="yes"?> Oletusarvo on "no"; joissakin tapauksissa "yes" nopeuttaa dokumenttien käsittelyä. Arvo "yes" ei kuitenkaan ole mielekäs jos esim. - attribuuteilla on oletusarvoja tai niiden tyyppi on jokin muu kuin CDATA - käytetään muita kuin viittä oletusentiteettiä - elementtien tietomallin tulkinta ei käy elementtirakenteesta ilmi 137
6.26 Huomautuksia DTD-kielestä Laajalti tuettu, yksinkertainen ja hyvin määritelty tapa määritellä dokumenttiluokkia XMLsovellusten tarpeisiin, mutta... Epäsymmetriat (elem. ja attr. määr.) Erikoinen DTD-kieli Ei valmiita datatyyppejä, ei välineitä omien määrittelyyn Ei helppoa keinoa johtaa tietomalleja toisistaan...tietomallien määrittelyn primitiivien yksinkertaisuus ( suunnittelun monimutkaisuus) jne. ts. muillekin skeemakielille löytyy käyttöä 138
6.27 Huomatus "luokka"-käsitteen käytöstä "Luokka"-käsitteen käyttö on XML:n yhteydessä oikeutettua se vain ei suoraan vastaa esim. Java-kielisen olio-ohjelmoinnin "luokka"-käsittettä (joka historiallisesti lainaa käsitteensä C++:sta, kehysjärjestelmistä yms.) XML-kielioppi määrittelee (hyvin.muod.) XML-dokumenttien luokan XML DTD asettaa aliluokan jolla on globaali nimi. Koska DTD-tyypitys ei sisällä perintää ja pakottaa kirjoittamaan tyyppiesittelyn ja dokumentin esiintymäosan dokumenttiin, ei DTD-kieli kuitenkaan aidosti salli aliluokkien aliluokkien määrittelyä tms. Rajoitus poistuu muiden skeemakielten käytöllä. Esimerkiksi XML Schema - erottaa tyypin ja elementin määritykset toisistaan - sallii tyypin johtamisen toisesta tyypistä rajoittamalla tai laajentamalla kantatyyppiä, sallii erilaisten korvausrakenteiden käytön - tähän(kin) palataan Rakenteisten dokumenttien jatkokurssilla 139