Elementtien tyyppideklaraatiot Kuten tunnettua, XML-dokumenttien loogisen rakenteen peruspalasia ovat elementit, esim: <example>hello world!</example> Elementtien syntaksi seuraa suoraan XML-spesifikaation kieliopista; looginen elementtirakenne sen sijaan voi syntaksin puitteissa vaihdella paljonkin, siis esimerkiksi: <doc> <field>hello</field> <title>world</title> </doc> on eri asia kuin: <doc> <field> <title>hello World</title> </field> </doc> 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 207
Dokumentin tyyppimäärityksessä on mahdollista eksplisiittisesti määrätä, minkälaisia rakenteita (ko. tyyppisten dokumenttien) elementeistä saa muodostaa Konkreettisesti määritys suoritetaan dokumentin tyyppideklaraatioon sisällytettävän elementin tyyppideklaraation avulla: [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>' [ VC: Unique Element Type Declaration ] Elementin mahdollinen sisältö luokitellaan seuraavasti: [46] contentspec ::= 'EMPTY' 'ANY' Mixed children Näiden merkitys on kutakuinkin seuraava: - EMPTY ~ tyhjä elementti - ANY ~ "mitä tahansa" sisältöä (käytetään yleensä vain debuggaukseen) - Mixed content ~ elementin sisältö yhdistelmä merkkidataa ja lapsielementtejä - Children (element) content ~ elementin lapsina vain elementtejä XML:ssä elementtien jaottelu näiden (tieto)tyyppien mukaan on "suurpiirteistä" 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 208
Ohessa esimerkkejä elementtien tyyppideklaraatioista ja otteita niitä vastaavista XML-dokumenteista (huomaa EBNF-tyyppiset oper. ja kertojat): (1) <!ELEMENT example EMPTY>... <example/> (2) <!ELEMENT example ANY>... <example>hello World <example/></example> (3) <!ELEMENT example (#PCDATA code field)*> <!ELEMENT code (#PCDATA)*> <!ELEMENT field (#PCDATA)*>... <example>hello World <field>hej</field> Hi <code>moi</code> Hello </example> (4) <!ELEMENT example (code field?)> <!ELEMENT code (#PCDATA)*> <!ELEMENT field (#PCDATA)*>... <example> <field>hej</field> <code>moi</code> </example> 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 209
Sisältönä tekstiä ja elementtejä: mixed content Mixed-content -vaihtoehdossa elementin sisällä saa olla merkkidataa ja lapsina erikseen nimettyjä elementtejä mielivaltaisessa järjestyksessä. Vastaava XMLproduktio on seuraava: [51] Mixed ::= '(' S? '#PCDATA' (S? ' ' S? Name)* S? ')*' '(' S? '#PCDATA' S? ')' [ VC: Proper Group/PE Nesting ] [ VC: No Duplicate Types ] Esimerkkejä: <!ELEMENT example (#PCDATA H1 H2 H3)*> <!ELEMENT field (#PCDATA a b)*> <!ELEMENT field (#PCDATA field a b)*> <!ELEMENT code (#PCDATA)> Tunniste #PCDATA tarkoittaa "parsittua merkkidataa" (~saa sisältää entiteettejä, merkkiviittauksia, jne.), muut elementtien (tyyppien) nimiä Elementin lapsielementtien järjestystä ei voi valita, kuten ei merkkidatan kirjoituskohtaakaan (voivat olla "missä vain") 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 210
Huomioita mixed content -elementtimäärittelystä: - alkaa aina kentällä #PCDATA - operaattorina aina OR (" ") XML ja dokumenttien tyyppimäärittely - mikäli sisältää viittauksia elementtien (tyyppien) nimiin, päättyy aina kertojaan "*" "Mixed" -termin käyttö on paikoitellen hieman harhaanjohtavaa; elementin sisällöksi voidaan pakottaa pelkkää tekstiä (ts. ei lapsielementtejä): <!ELEMENT code (#PCDATA)> Children content -vaihtoehdossa elementin sisällä saa olla vain lapsia, mutta dokumentin looginen rakenne on yksityiskohtaisemmin määritettävissä. Vastaavat XML-produktiot ovat: [47] children ::= (choice seq) ('?' '*' '+')? [48] cp ::= (Name choice seq) ('?' '*' '+')? [49] choice ::= '(' S? cp ( S? ' ' S? cp )* S? ')' [ VC: Proper Group/PE Nesting ] [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')' [ VC: Proper Group/PE Nesting ] 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 211
Sisältönä lapsielementtejä: children element content Kun elementin sisältö määritellään children content -tyyppiseksi, voidaan lapsielementtikonfiguraatio määrittää monipuolisesti EBNF:stä tuttujen operaattoreiden ja kertojien avulla (kyseessä on kuitenkin eri syntaksi) Esimerkki: <!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 ("(",")") 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 212
Tarkista tyhjämerkkien ja sulkujen kirjoitussäännöt spesifikaation tuottosäännöistä! Yhdistelemällä elementtien nimiä sopivasti operaattoreita, kertojia ja sulkuja käyttämällä, voidaan määrittää elementin tietomalli ([content model]) Tietomalleja on usein tarkoituksenmukaista jakaa pienempiin osiin sääntöjen lukemisen ja kirjoittamisen helpottamiseksi (huomaa ero merkkauksessa!): <!ELEMENT mydoc (title?,code+,misc)> <!ELEMENT misc ((footer comment)?)> Mikäli "ylimääräisiä" alku- ja lopputageja ei dokumentteihin haluta, voidaan elementtien tyyppideklaraatiota sieventää ns. parametrientiteettien avulla (näihin palataan myöhemmin) Elementtien tietomallit voivat olla varsin mutkikkaita sisältäen myös rekursiivisia (itseensä viittaavia) rakenteita (rekursioonkin palataan vielä) Yhden ja saman (ei-triviaalin) loogisen elementtirakenteen voi yleensä ilmoittaa useilla eri elementin tyyppideklaraatioilla Elementin tyyppideklaraatioiden on oltava yksikäsitteisiä, ts. tyyppideklaraatioiden "päällekirjoittaminen" tai epädeterministisinä tuottosääntöinä tulkitseminen ei ole sallittua (mikä on harmi!) 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 213
Attribuuttilistojen deklaraatiot Attribuutit ovat (yleensä) elementteihin liitettävää "metatietoa, esim. tyyliin: <example color="red" shape="circle">hello world!</example> Attribuuttien syntaksi seuraa suoraan XML-spesifikaation kielopista; sen sijaan elementtiin liitettävien attribuuttien nimet, arvojoukot ja attribuuttien (pakollinen) esiintyminen elementeissä voivat syntaksin puitteissa vaihdella paljonkin, siis esimerkiksi (tarkkaan ottaen): <example color="red" shape="circle"/> on sama asia kuin: <example shape="circle" color="red"/> mutta saattaa olla (loogisesti) eri asia kuin: <example color="red"/> 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 214
On syytä huomata, että vaikka elementtien sisältönä voi XML:ssä olla vain joko merkkidataa tai elementtejä, on attribuuttien arvojen tyypittäminen mahdollista (tosin vain ylimalkaisesti) Attribuutit määritellään eksplisiittisesti aina tietyntyyppisille ("tietynnimisille") elementeille, määrittely suoritetaan (elementin) attribuuttilistan deklaraation avulla, esim. tyyliin: <!ELEMENT example EMPTY> <!ATTLIST example color (red green blue) "red"> Koska deklaraatioon kirjoitetaan aina assosioitavan elementin nimi, ovat erityyppisille elementeille esiteltävät samannimiset attribuutit eri attribuutteja, vrt: <!ELEMENT example EMPTY> <!ELEMENT code (#PCDATA)> <!ATTLIST example color (red green blue) "red"> <!ATTLIST code color CDATA "red"> Attribuuttilistan deklaraatio annetaan XML-kieliopissa muodossa: [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>' [53] AttDef ::= S Name S AttType S DefaultDecl 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 215
Kuten edellisistä esimerkeistäkin käy ilmi, attribuuttideklaraatioiden yhteydessä esiintyy yleensä myös avainsanoja tai oletusarvoja (ns. attribuutin oletusmääritykset ([default declaration])). Näiden merkitys on seuraava: - #REQUIRED ~ attribuutin arvo on pakko antaa - #IMPLIED ~ attribuutin antaminen on vapaaehtoista - #FIXED ~ attribuutin arvo on vakio - "merkkidataa" käytetään esim. antamaan oletusarvoja attribuuteille Attribuuttien oletusmääritykset on XML-kieliopissa määritelty seuraavasti: [60] DefaultDecl ::= '#REQUIRED' '#IMPLIED' (('#FIXED' S)? AttValue) [ VC: Required Attribute ] [ VC: Attribute Default Legal ] [ WFC: No < in Attribute Values ] [ VC: Fixed Attribute Default ] 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 216
Attribuutin (oletus)arvo on merkkidataa ja voi sisältää entiteetti- tai merkkiviittauksia: [10] AttValue ::= '"' ([^<&"] Reference)* '"' "'" ([^<&'] Reference)* "'" Esimerkkejä (eri deklaraatioista): <!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"> Yleensä oletusmäärityksinä käytetään literaaleina annettavia oletusarvoja tai vaatimusta attribuutin antamisesta Muillekin löytyy toki käyttöä: - "IMPLIED-attribuutti" sopii esim. jonkin tietyn XML-editorin yhteydessä välittämään käyttäjän näkökulmasta "implisiittistä" tietoa sovellukselle - "FIXED-attribuutti" taas voi olla käytössä samasta syystä tai vaikkapa paketoida (pakottaa) tietoa johonkin sovelluskohtaiseen muotoon (esim. hakukoneita, linkkejä tai jotakin arkkitehtuuria varten) 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 217
Attribuuttien tyypit XML-syntaksin näkökulmasta attribuuttien arvot ovat aina "tekstiä" tai "merkkidataa" joka saattaa sisältää entiteetti- tai merkkiviittauksia XML:n puitteissa attribuuttien arvojen täsmällisempi (rajaavampi) tyypittäminen on kuitenkin mahdollista - käytännössä tämä tarkoittaa sitä, että "kaikentyyppinen merkkidata" ei (aina) attribuutin arvoksi kelpaa Monisteen aikaisemmissa esimerkeissä attribuutin tyyppeinä oli yksinkertaisesti joko "paljasta merkkidata" tai "numeroituja joukkoja", tyyliin: <!ATTLIST example color (red green blue) #REQUIRED> <!ATTLIST example color CDATA #REQUIRED> Käytännössä tämä "yleensä" riittää 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ä 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 218
Perusideana on siis attribuuttien (syntaktisen) rakenteen "järkevyyden" (oikeellisuuden) tutkiminen jo XML-prosessorin avulla niin pitkälle kuin mahdollista (tai pikemminkin käytännöllistä) XML:ssä attribuuttien tyypit (arvojoukot) voivat olla jotakin seuraavista: - CDATA ~ merkkidataa - Enumeration ~ 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) 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 219
On tärkeää huomata, että XML-dokumenttissa näkyvään elementtiin kirjoitettu attribuutin arvo käy aina läpi normalisointiprosessin matkallaan XMLprosessorin "läpi" kohti sovellusta (tähän palataan pian) Attribuuttien tyypit on XML-kieliopissa määritelty seuraavasti (produktion 56 rajoitteet on alla kirjoitettu lyhyempään muotoon: [54] AttType ::= StringType TokenizedType EnumeratedType [55] StringType ::= 'CDATA' [56] TokenizedType ::= 'ID' 'IDREF' 'IDREFS' 'ENTITY' 'ENTITIES' 'NMTOKEN' 'NMTOKENS' [ VC: ID ] [ VC: One ID per Element Type ] [ VC: ID Attribute Default ] [ VC: IDREF ] [ VC: Entity Name ] [ VC: Name Token ] Nimen mukaisesti attribuuttilistat määritellään elementeille kerralla esim. tyyliin: <!ELEMENT example EMPTY> <!ATTLIST example id ID #REQUIRED file NMTOKEN #IMPLIED> 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 220
Attribuuttideklaraatioiden yhdistäminen vs. hajauttaminen Toisin kuin elementtien tyyppideklaraatioit, jotka aina pitää antaa "kerralla", attribuuttideklaraatiot voidaan antaa myös "osissa": Siis esimerkiksi: <!ELEMENT example EMPTY> <!ATTLIST example color CDATA #REQUIRED> <!ATTLIST example shape (box circle line) "box"> voidaan esittää myös yhtäpitävästi listamuodossa <!ELEMENT example EMPTY> <!ATTLIST example color CDATA #REQUIRED shape (box circle line) "box"> Erityisen kätevää tämä on DTD:n hajauttamisen näkökulmasta, sillä näin ulkoisessa DTD-osajoukossa esitetyille elementeille voidaan antaa jälkikäteen uusia attribuutteja sisäisessä DTD-osajoukossa Attribuuttideklaraatioiden päällekirjoittaminen ei kuitenkaan ole mahdollista (monikertaisista attribuuttideklaraatioista merkitsevä on aina ensimmäinen) 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 221
Attribuuttien arvojen normalisoiminen Attribuuttien arvot todellakin ovat parsittavaksi tarkoitettua tekstiä, tämä tarkoittaa käytännössä sitä, että XML-prosessorin sovellukselle välittämä merkkijono ei välttämättä ole täsmälleen sama kuin dokumenttiin kirjoitettu literaali Attribuuttien arvo määräytyy aina ns. normalisoinnin perusteella, jossa literaalista prosessoidaan (XML-)sovellukselle välitettävä attribuuttiarvo Attribuuttien arvojen normalisointialgoritmi on seuraavanlainen: 1) arvon ympäriltä poistetaan lainausmerkit 2) merkkiviittaukset korvataan vastaavilla Unicode-merkeillä 3) entiteettiviittaukset korvataan vastaavilla merkkijonoilla (mahdollisesti rekursiivisesti) 4) kaikki tyhjämerkit (siis myös rivinvaihdot, [newline]) korvataan välilyönneillä #x20 (poikkeus entiteeteille #xd#xa::=#x20) 5) jos attribuutin tyyppi on jokin muu kuin CDATA, poistetaan merkkijonosta vielä monikertaiset välilyönnit ja välilyöntiprefiksit ja -suffiksit (jos niitä on) 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 222
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="this line of text is an B-class example. "> Edellisessä esimerkissä attribuutin text (jonka tyypiksi on annettu CDATA) arvo normalisoidaan muotoon (hakasulut on esimerkissä lisätty ainoastaan havainnollistamaan merkkijonon alku- ja loppukohtia) [This line of text is an B-class example. ] Huomaa, että normalisaatio tuottaa erilaisen arvon, jos attribuutin tyypiksi olisi annettu esim. NMTOKENS muodossa: <!ATTLIST desc text NMTOKENTS #REQUIRED>... <desc text="this line of text is an B-class example."> tällöin arvo normalisoitaisiin muotoon: [This line of text is an B-class example.] 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 223
Attribuuttityyppien esittely Yksinkertaisin attribuuttityyppi on CDATA ([character data]), joka sisältää "raakaa mutta parsittavaa merkkidataa" - "rakenteeton" attribuuttiarvo - tyhjämerkkien normalisointi: vain rivinvaihdot ja alku- ja loppuvälilyönnit - myös tyhjä arvo "" kelpaa Esimerkki: <!ATTLIST example text CDATA #REQUIRED>... <example text="<all the $#x&! characters 4 me and you 4 2! >"/> NMTOKEN-tyyppinen ([name token], tunnistemerkkijono) attribuutti hyväksyy arvokseen tunnistemerkkijonon - arvona vain tunnistemerkkijonoon kelpaavia merkkejä (sekä mahdollisesti tyhjämerkkejä alussa ja lopussa) 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 224
- tyhjämerkkien normalisointi koko komeudessaan - tyhjä arvo "" ei kelpaa Esimerkki: <!ATTLIST example text NMTOKEN #REQUIRED>... <example text="4methisis"/> XML ja dokumenttien tyyppimäärittely NMTOKENS-tyyppinen attribuutti hyväksyy arvokseen luettelon tunnistemerkkijonoja (muuten kuten NMTOKEN) - arvona vain tyhjämerkeillä erotettuja tunnistemerkkijonoja - tyhjämerkkien normalisointi koko komeudessaan - tyhjä arvo "" ei kelpaa Esimerkki: <!ATTLIST example text NMTOKENS #REQUIRED>... <example text="4methisis and these are for you"/> 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 225
Enumerated-tyyppinen attribuutti hyväksyy arvokseen jonkin luetelluista tunnistemerkkijonoista - arvo täsmälleen jokin luetelluista - tyhjämerkkien normalisointi: vain rivinvaihdot ja alku- ja loppuvälilyönnit Esimerkki: <!ATTLIST example shape (box circle line) "">... <example shape="box"/> NOTATION-tyyppinen attribuutti on muuten kuten Enumeratedkin, mutta lueteltujen tunnistemerkkijonojen pitää olla esiteltyjä XML-notaatioita (tähän palataan pian) ID--tyyppinen attribuutti hyväksyy arvokseen (ko. XML-dokumentissa) ainutkertaisen nimi-tyyppisen merkkijonon ([name]) - tyhjämerkkien normalisointi: vain rivinvaihdot ja alku- ja loppuvälilyönnit - tyhjä arvo "" ei kelpaa - elementillä voi olla korkeintaan yksi ID-tyyppinen attribuutti 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 226
- attribuutin nimeksi annetaan "yleensä" id, ID, jne. Esimerkki: <!ATTLIST example id ID #REQUIRED>... <example ID="myUniqueExample"/> XML ja dokumenttien tyyppimäärittely IDREF--tyyppinen attribuutti hyväksyy arvokseen jonkin (ko. XMLdokumentissa) ID-tyyppisen attribuutin arvon joka siis on merkkijono ([name]) - tyhjämerkkien normalisointi: vain rivinvaihdot ja alku- ja loppuvälilyönnit - tyhjä arvo "" ei kelpaa - attribuutin nimeksi annetaan "yleensä" idref, IDREF, jne. Esimerkki (oletetaan edellisen esimerkin "olemassaolo"): <!ATTLIST image idref IDREF #REQUIRED>... <image idref="myuniqueexample"/> IDREFS--tyyppinen attribuutti on kuten "samanlainen IDlle kuin mitä NMTOKENS on NMTOKENille" 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 227
ENTITY--tyyppinen attribuutti on käytännössä muuten samanlainen kuin IDREF-tyyppinenkin, mutta hyväksyy arvokseen vain jonkin määritellyn "ulkoisen parsimattoman entiteetin" nimen ([external unparsed entity]) Esimerkki: <!ENTITY gif-name SYSTEM "/usr/flower.gif"> <!ATTLIST example name ENTITY #REQUIRED>... <example name="gif-name"/> ENTITIES--tyyppinen attribuutti on taaskin samanlainen "ENTITYlle kuin mitä NMTOKENS on NMTOKENille" Yleisiä huomioita attribuuteista ja yhteenvetoa: - ei ole olemassa "hierarkkisia" attribuuttirakenteita (kuten on olemassa hierarkkisia elementtirakenteita) - XML-syntaksin näkökulmasta attribuuttien arvot ovat aina "tekstiä" - merkki "<" on attribuutin arvona aina laiton - entiteetit parsitaan attribuuttien arvoissa aina "auki" - attribuuttien arvot normalisoidaan 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 228
XML-spesifikaation nimeämät attribuutit XML-spesifikaatio määrittelee semantiikan kahdelle erikoiselle vakionimiselle attribuutille: - xml:space - xml:lang xml:space voi saada kaksi eri arvoa: default tai preserve - preserve kertoo XML-sovellukselle että sen tulee ohittaa oletusarvoinen (mielivaltainen) tyhjämerkkien sievennyskäytäntönsä ja huomioida kaikki tyhjämerkit Huomioita XML-prosessorin suorittamasta tyhjämerkkien parsimisesta: - XML-prosessori välittää aina kaikki (merkkidatan) tyhjämerkit sovellukselle sellaisena kuin ne olivat XML-dokumentissa - poikkeus #1: attribuuttien arvojen normalisointi - poikkeus #2: XML-prosessori korvaa mahdolliset rivinvaihdot #xd#xa ([carriage-return][line-feed]) tai #xd aina rivinvaihdolla #xa "Unixkäytännön mukaisesti" 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 229
xml:lang voi saada jonkin ISO 639 kielikoodin, IANA-kielikoodin (prefix "i-", "I-") tai sovelluskohtaisen kielikoodin (prefix "x-","x-") - kielikoodi kertoo (ei pakota!) elementin merkkidatan, attribuuttien arvojen ja lapsielementtien kielen (luonnollisen tai formaalin) - lapsielementit voivat ohittaa tämän kielimäärityksen oman xml:langattribuuttinsa avulla, vrt. esim. <p xml:lang="en-gb">what colour is it? <p xml:lang="en-us">or does it have color at all?</p></p> XML-dokumenteissa attribuutteja xml:space ja xml:lang (kuten mitä tahansa muitakin attribuutteja) voidaan käyttää suoraan, mutta validien dokumenttien pitää attribuutit määritellä Attribuutin xml:space deklaraation muoto on spesifikaatiossa yksikäsitteisesti määrätty, attribuutti xml:lang voidaan määritellä vapaammin: <!ATTLIST elementname xml:space (default preserve) 'preserve'> <!ATTLIST examplename xml:lang NMTOKEN 'en'> XML-standardiperhe nimeää myös muitakin attribuutteja ja esittää merkityksen näille (näihin palataan myöhemmin) 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 230
Notaatiodeklaraatiot Notaatiodeklaraatio esittelee luonteeltaan semanttisen "parsimattomaan entiteettiin" kohdistuvan sievennysmerkinnän, resurssin tai relaation dokumentin käsittelemälle tiedolle (käytännössä suhteessa "XML-prosessorin ulkopuoliseen maailmaan") Notaatiodeklaraation produktio XML-spesifikaatiossa on: [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID PublicID) S? '>' [83] PublicID ::= 'PUBLIC' S PubidLiteral [75] ExternalID ::= 'SYSTEM' S SystemLiteral 'PUBLIC' S PubidLiteral S SystemLiteral Esimerkki: <!NOTATION gifconv SYSTEM "ps2gif.exe"> <!NOTATION jpgconv SYSTEM "ps2jpg.exe"> <!ATTLIST example handler NOTATION (gifconv jpgconv) #REQUIRED>... <example handler="gifconv"/> 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 231
Ehdolliset DTD-lohkot XML-dokumentin ulkoinen DTD-osajoukko voi sisältää ns. ehdollisen DTDlohkon ([conditional section]) Ehdollinen DTD-lohko mahdollistaa DTD:n osien "kytkemisen päälle ja pois päältä" helpottaen näin laajojen dokumentin tyyppimäärittelyjen hallintaa Syntaksiltaan lohko muistuttaa CDATA-lohkoa. Lohkon näkyvyyttä kontrolloidaan avainsanojen IGNORE ja INCLUDE avulla Esimerkki kertoo kaiken: <![IGNORE[ <!ELEMENT book (comments*, title, body, supplements?)> ]]> <![INCLUDE[ <!ELEMENT book (title, body, supplements?)> ]]> Ehdollinen DTD-lohko voi sisältää periaatteessa samanlaista merkkausdeklaraatiota ja merkkausta kuin DTD-osajoukotkin. On kuitenkin syytä huomata, että valinnaiset DTD-lohkot voivat olla myös sisäkkäisiä 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 232
Huomaa, että IGNORE-koodattu valinnainen DTD-lohko EI tarkoita samaa kuin ko. lohkon kommentoiminen dokumentin tyyppimäärittelyssä! XML-kielioppi määrää ehdollisen DTD-lohkon syntaksin seuraavasti: [61] conditionalsect ::= includesect ignoresect [62] includesect ::= '<![' S? 'INCLUDE' S? '[' extsubsetdecl ']]>' [63] ignoresect ::= '<![' S? 'IGNORE' S? '[' ignoresectcontents* ']]>' [64] ignoresectcontents ::= Ignore ('<![' ignoresectcontents ']]>' Ignore)* [65] Ignore ::= Char* - (Char* ('<![' ']]>') Char*) Suurin hyöty ehdollisten DTD-lohkojen käytöstä saadaan, kun avainsana IGNORE tai INCLUDE annetaan parametrientiteetin avulla parametrina (entiteetteihin palataan pian) tyyliin: <!ENTITY % jack "IGNORE"> <!ENTITY % jill "INCLUDE">... Sisäisessä DTD-osajoukossa esiteltävien parametrientiteettien avulla on siis mahdollista valita ulkoisesta DTD-osajoukosta jokin ehdollinen DTD-lohko 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 233
Yleiskäyttöinen tyyppimääritys: SYSTEM vs. PUBLIC Avainsanaa SYSTEM käyttävä dokumentin tyyppideklaraatio lukee siis DTD:n osaksi ulkoisen tekstitiedoston tyyliin: <?xml version="1.0"?> <!DOCTYPE mydoc SYSTEM "mydocclass.dtd"> <mydoc> <title>first XML-doc</title> <body>hello!</body> </mydoc> Huomioita: - ulkoinen DTD-osajoukko luetaan tekstitiedostosta -...jonka suora muokkaaminen saattaa olla mahdollista (ainakin DTD:n suunnittelijalle) Dokumentin tyyppimääritysten vakiintuessa (kun DTD on suunniteltu, testattu ja havaittu hyväksi), on yleiskäyttöisyyden nimissä järkevää sijoittaa ulkoiset DTD-tiedostot johonkin "yleisesti saatavilla" olevaan paikkaan, esim. HTTPpalvelinhakemistoon ja käyttää DTD-osajoukkoja tyyliin: <?xml version="1.0"?> <!DOCTYPE mydoc SYSTEM "http://server/dir/mydocclass.dtd">... 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 234
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" standardit nimetään, liitetään suoraan "osaksi" XML-parsereita ja DTD-osajoukko valitaan dokumentin tyyppideklaraatiossa avainsanan PUBLIC avulla tyyliin: <?xml version="1.0"?> <!DOCTYPE mydoc PUBLIC "-//XMLORG//DTD MYDOC//EN">... 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 - "//" ja DTD:n omistajan tunnus - "//" ja tiedoston tyyppi (esim. "DTD) - välilyönti " " ja dokumentin nimi - "//" kielikoodi (ISO 639) 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 235
Standalone-deklaraatio Dokumentin parsittavuuteen 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 "oikein", voidaan dokumentin alkuun XML-deklaraatioon kirjoittaa (ns. [standalone declaration]): <?xml version="1.0" standalone="yes"?> Oletusarvo on "no" Joissakin tapauksissa standalone-deklaraatio nopeuttaa dokumenttien käsittelyä Käyttö ei ole mahdollista, jos esimerkiksi: - 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 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 236
Validit XML-dokumentit Määritelmänsä mukaan XML-dokumentti ei voi olla "väärin muodostettu", mutta se voi olla validi tai sitten ei Dokumentti on validi XML-dokumentti täsmälleen silloin kun: 1) dokumentti noudattaa XML-kielioppia, 2) dokumentin prologi sisältää tyyppideklaraation JA 3) dokumentin esiintymä noudattaa sitä Jos pelkkä kohta 1 toteutuu, on kyseessä "vain" (oikein muodostettu) XMLdokumentti On syytä huomata, että dokumentti voi täyttää ehdon 1 vaikka se ei täyttäisikään ehtoja 2 ja 3 - tällöinkin dokumentti on XML-kielenkäytön mukaisesti "vain" XML-dokumentti! Jotta kielenkäytössä tieto DTD deklaraation olemassaolossa ei kuitenkaan katoaisi, on tarkoituksenmukaista ottaa käyttöön lisätermit tyyppi-validi ([typevalid]) XML-dokumentti ja ei-tyyppi-validi ([non-type-valid]) XML-dokumentti 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 237
Mitä DTD sitten loppujen lopuksi "tarkoittaa"? Suoraviivaisin tapa "ymmärtää" DTD:n merkitys pintaa syvemmältä on tulkita se reunaehdoksi, joka valitsee ja kiinnittää jonkin tietyn (sovelluksen näkökulmasta mielenkiintoisen) XML-dokumenttien luokan aliluokan: DOKUMENTTI- LUOKKA Z =LOOGISEN RAKENTEEN Z OMAAVAT XML- DOKUMENTIT TYYPPI-A-VALIDIT XML-DOKUMENTIT TYYPPI-C-VALIDIT XML-DOKUMENTIT TYYPPI-B-VALIDIT XML-DOKUMENTIT XML-DOKUMENTTIEN LUOKKA XML-dokumenttien luokka sisältää siis kaikki ne tekstitiedostot, jotka voidaan johtaa XML-spesifikaation kieliopista (WFC-rajoitteet huomioiden) 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 238
Dokumentin tyyppimääritysten kiinnittämät XML-dokumenttien luokan aliluokat ovat: 1) tyyppi-validien XML-dokumenttien suhteen aina erillisiä (ts. tyyppi-validi XML-dokumentti kuuluu aina täsmälleen yhteen dokumenttiluokkaan) 2) "pelkkien" XML-dokumenttien suhteen yleensä päällekkäisiä (ts. dokumentin esiintymän looginen rakenne voi olla useamman kuin yhden geneerisen dokumenttiluokan sääntöjen mukainen) Syy, ensimmäiseen, ts. miksi tyyppi-validien XML-dokumenttien suhteen luokat ovat aina erillisiä, selittyy XML-dokumenttiin liitettävän dokumentin tyyppideklaraation määräämän dokumentin tyyppimäärityksen (DTD) ainutkertaisuutena Jälkimmäisellä tarkoitetaan sitä, että yksi ja sama XML-dokumentti voi pelkän dokumentin tyyppideklaraation lisäyksellä olla joko tyyppi-a-validi XMLdokumentti tai tyyppi-b-validi XML-dokumentti 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 239
Esimerkiksi seuraavat kaksi XML-dokumenttia ovat molemmat tyyppi-valideja eri tyyppimääritysten suhteen - huomaa että dokumenttien esiintymät ovat identtisiä: <?xml version="1.0"?> <!DOCTYPE mydoc [ <!ELEMENT mydoc (title, body?)> <!ELEMENT title (#PCDATA)> <!ELEMENT body (#PCDATA)> ]> <mydoc><title>hello World!</title></mydoc> <?xml version="1.0"?> <!DOCTYPE mydoc [ <!ELEMENT mydoc (title)> <!ELEMENT title (#PCDATA)> ]> <mydoc><title>hello World!</title></mydoc> Jos edellisessä esimerkissä ensimmäisen DTD:n nimeksi annetaan A ja jälkimmäisen DTD:n nimeksi B, huomataan, että: - dokumenttiluokan B XML-dokumenttien esiintymät kuuluvat aina myös dokumenttiluokkaan A mutta ei päinvastoin - annettu mv. tyyppivalidi XML-dokumentti kuuluu aina joko 1) dokumenttiluokkaan A, 2) dokumenttiluokkaan B, tai 3) ei kumpaankaan näistä 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 240
Yhden ja saman DTD:n voi usein yleensä esittää usean erinäköisen dokumentin tyyppideklaraation avulla, esimerkiksi seuraavat merkkausdeklaraatiot määrittävät saman DTD:n: <!DOCTYPE mydoc [ <!ELEMENT mydoc (#PCDATA title footer)*> <!ELEMENT title (#PCDATA)> <!ELEMENT footer (#PCDATA)> ]>... <!DOCTYPE mydoc [ <!ELEMENT mydoc (#PCDATA footer title)*> <!ELEMENT title (#PCDATA)> <!ELEMENT footer (#PCDATA)> ]> Tosin käytännössä suurten tyyppideklaraatioiden palauttaminen toisikseen voi (käsin tehtynä) olla hankalaa Huomaa että: - XML-dokumenttien luokka sisältää potentiaalisesti äärettömän määrän dokumentteja - tyyppi-z-validien XML-dokumenttien luokka voi sisältää joko äärellisen määrän dokumentteja tai potentiaalisesti äärettömän määrän dokumentteja 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 241
Esimerkkejä Esimerkki äärellisen XML-dokumenttiluokan aliluokan määräävästä DTDmäärityksestä: <!DOCTYPE mydoc [ <!ELEMENT mydoc (footer?,title)> <!ELEMENT title EMPTY> <!ELEMENT footer EMPTY> ]> Esimerkkejä (potentiaalisesti) äärettömän XML-dokumenttiluokan aliluokan määräävästä DTD-määrityksestä: <!DOCTYPE mydoc [ <!ELEMENT mydoc (footer*,title)> <!ELEMENT title EMPTY> <!ELEMENT footer EMPTY> ]> <!DOCTYPE mydoc [ <!ELEMENT mydoc (#PCDATA)> ]> <!DOCTYPE mydoc [ <!ELEMENT mydoc EMPTY> <!ATTLIST mydoc attr CDATA #REQUIRED> ]> Kuten esimerkeistä voi päätellä, mielekkäät dokumenttiluokat ovat yleensä (potentiaalisesti) äärettömiä (tämä ei tarkoita että ne olisivat mielivaltaisia!) 73275 RAKENTEISET DOKUMENTIT (kevät 2003) luentorunko ON 242