Egy XML alkalmazás megtervezésekor valamilyen problémakört modellezünk: ez sok szempontból hasonlít ahhoz, mint amikor egy objektumközpontú programnyelvben osztályhierarchiákat tervezünk vagy adatbázissémát alkotó táblákat határozunk meg. Ilyenkor egy valóságos rendszert képezünk le olyan szerkezetté, amelyet az adott nyelv lehetõvé tesz. Az XML esetében a tényleges információkat fákká, elemekké és jellemzõkké alakítjuk. A leképezés lehet magától értetõdõ, de egy adott nyelven – például RELAX NG, DTD, Schematron vagy W3C XML sémanyelv – írott sémában meghatározott is. A 2. rész azokat a problémákat taglalja, amelyek az ilyen leképezések végrehajtásakor kerülnek felszínre. Megmutatja, milyen XML szerkezetek milyen típusú adatoknál alkalmazhatók, és melyek azok, amelyek egyáltalán megfelelnek a fontos adatok tárolásához. (Az XML-ben sok nyelvtani finomság található, amelyek az alkalmazások készítésekor ugyan hasznosak, de nem fokozzák lényegesen a kifejezõképességet.) Ez a rész a dokumentálás és a tervezés eszközeit tárgyalja, többek között a névtérként való leképezést és a sémákat, továbbá olyan tanácsokat ad, amelyek segítségével biztosíthatjuk, hogy a modellek kifejezõk legyenek a jelenben és egyúttal bõvíthetõk a jövõben.
11. szabály Jelöléssel tegyük egyértelmûvé a szerkezetet! Az XML dokumentumokban minden szerkezetet XML címkékkel kell jelölni, nem ettõl eltérõ módszerekkel. Az XML-elemzõk az XML-címkék feldolgozására szolgálnak; semmilyen ettõl eltérõ adatszerkezet-formát nem látnak, legyen az egyértelmûen kifejezett vagy beleértett. Ha nem címkéket, illetve azok jellemzõit használjuk a szerkezetek ábrázolásához, az adatok sokkal nehezebben olvashatóvá válnak. Az ilyen programokat készítõknek lényegében saját kis elemzõket kell fejleszteniük az adatok nem XML szerkezeteinek olvasásához.
XML02.qxd
52
11/6/2006
2:31 PM
Page 52
Hatékony XML Az 1. részben vizsgált számlakivonat-alkalmazásnál például elméletben így lehetne ábrázolni egy mûveletet: Withdrawal 2003 12 15 200.00
Ehhez az adatokat olvasó alkalmazásoknak tudniuk kell, hogy az elsõ mezõ a mûvelet típusa, a második mezõ az év, a harmadik a hónap, a negyedik a nap, az utolsó pedig az összeg. A legtöbb esetben az ügyfélprogramoknak a szóközök mentén részekre kellene bontaniuk az adatokat a további feldolgozáshoz. Ezzel szemben, ha az adatok az alábbi jelöléssel szerepelnek, az ügyfél gördülékenyebben mûködhet: 2003-12-15200.00
Itt minden hasznos információegység egy elem vagy egy jellemzõ teljes tartalmaként jelenik meg.
Minden információegységet lássunk el címkével! Az alapelv az, hogy két címke között a legkisebb olyan szövegegységnek kell állnia, amelyet hasznosan lehet egészként feldolgozni. Nem jó, ha a gyakori feladatokhoz további részekre kell osztani azt. Egy Amount (összeg) elemnek például egy teljes összeget kell tartalmaznia és semmi mást. Az összeg egyetlen, teljes információegység, ami ebben az esetben egy szám. Nincs belsõ szerkezete, amelyet az alkalmazások várhatóan elemeznek majd. Az, hogy mi alkot egy egységet, idõnként attól függ, hogy az adatot hol és hogyan használjuk. Vegyük például a fenti Transaction (tranzakció) elem Date (dátum) elemét. A kötõjelek beleértett (implicit) jelölést határoznak meg. Így lehetne írni másféleképpen: 2003 <Month>12 15
Az, hogy ez hasznos-e, azon múlik, hogy miként használjuk a dátumokat. Ha csupán megjelenítjük az eredeti elrendezésben egy oldalon, vagy egy olyan API-nak adjuk át, amely tudja, hogyan kell a 2003-12-15 típusú karakterláncokból Date objektumokat létrehozni, akkor nem kell önálló elemekként elkülöníteni a hónapot, a napot és az évet. Általánosságban attól függ, hogy további részekre kell-e osztani az adatokat, hogy milyen módon használjuk fel az információt, valamint hogy késõbb milyen mûveleteket végzünk azokon. Ha a dátumok célja csupán az, hogy egy adott esemény idõpontját jelöljék, akkor a 2003-12-15 formátum megfelelõ. Ez olyan esetekben hasznos például, amikor meg szeretnénk tudni, hogy eljött-e az ideje, hogy megigyunk egy pohár bort, vagy
XML02.qxd
11/6/2006
2:31 PM
Page 53
2. fejezet • Szerkezet egy bizonyos munkás jogosult-e a nyugdíjra, illetve ha ki szeretnénk számítani, hogy mennyi idõ van hátra egy autó jótállásából. A fenti esetek egyikénél sem igazán fontos maga a nap és a hónap, de még az év sem. Csak a mennyiségek kombinációja számít. Maga a tény, hogy a dátumok ezekbõl a mennyiségekbõl állnak össze, leginkább a csillagászat és a Föld szeszélyeinek köszönhetõ, és nem az idõ természetébõl ered. Gondoljunk azonban az idõjárási adatokra. Mivel az idõjárás az évszakokkal változik, és az évekhez, illetve hónapokhoz kötõdõ, nagyjából rendszeresen visszatérõ szerkezettel rendelkezik, van értelme egy adott február idõjárását összevetni egy másik februáréval úgy, hogy nem feltétlenül vesszük figyelembe az évet. A születésnapok, a fizetések gyakorisága és az üzleti eredmények olyan további valós adatok, amelyek éves, illetve havi ciklusokhoz kötõdnek. Ha ilyen típusú adatokat modellezünk, elvárjuk, hogy a hónapokat, a napokat és az éveket el tudjuk különíteni egymástól. Ebben az esetben strukturáltabb jelölésre van szükség, például: 2003<month>1215. Valójában az a kérdés, hogy az ezeket az adatokat módosító folyamatok egyetlen információegységként akarják-e majd kezelni a szöveget vagy inkább alapvetõbb adatok összetételeként. Ennek ellenére az, hogy nem kell kigyûjtenünk a dátumok egyes elemeit, nem jelenti azt, hogy ezt senkinek sem kell elvégeznie, aki késõbb az adatokkal dolgozik. Szerintem általánosságban mindig jobb, ha sok címkét használunk, mint ha túl keveset. Rendszerint a szülõ- vagy õselemek szükség szerinti módosításával alkothatók nagyobb adattömbök. Szerkezeteket mindig könnyebb eltávolítani feldolgozáskor, mint bõvíteni. Jellemzõ példa arra, hogy mint nem szabad, a Scalable Vector Graphics (SVG) formátum. Az SVG rengeteg nem XML alapú jelölést használ. Vegyük például a következõ polygon (sokszög) elemet: <polygon points="350,75 379,161 469,161 397,215 423,301 350,250 277,301 303,215 231,161 321,161" />
Nézzük meg közelebbrõl a points (pontok) jellemzõt, ami nem egyszerû karakterlánc, hanem x és y koordináták sorozata. Egy SVG-feldolgozó nem tudja egyszerûen kezelni a jellemzõ értékét; ehelyett elõször megfelelõ párokra kell bontania a jellemzõ értékét, majd el kell döntenie, hogy melyek az x-ek, illetve az y-ok. A koordináták gyermekelemekként történõ meghatározása lenne a helyes megoldás: <polygon> <point x="350" <point x="379" <point x="469" <point x="397" <point x="423" <point x="350" <point x="277" <point x="303"
Ily módon az XML-feldolgozó már rendezett állapotban adja át a koordinátákat az alkalmazásnak. Ez azt a fontos tényt is szemlélteti, hogy a jellemzõk nem igazán támogatják a szerkezetet (lásd a 12. szabályt). A strukturált adatokat rendszerint elemhierarchiákban kell tárolni. Csak a legalacsonyabb szintû, legkevésbé strukturált egységeket kell jellemzõként megadni. A fenti rossz felépítés a túl nagy fájlméret és a terjengõsség kiküszöbölésének eredménye. A jelölés tömörsége ennek ellenére kifejezetten nem cél az XML-ben. Akit igazán foglalkoztat, hogy a felhasználónak mennyi karaktert kell begépelnie, annak eleve nem XML-t kell használnia. Ebben az esetben a tömörség azonban valóban nem jár elõnyökkel. Szinte az összes SVG-t vagy számítógépes programok hozzák létre, vagy olyan WYSIWYG alkalmazásokban rajzolják, mint az Adobe Illustrator. A programoknak nem okoz gondot a terjedelmesebb, tiszta XML formátum, sõt lényegesen könnyebb lenne ilyen SVG-t feldolgozó és létrehozó programokat írni, ha az összes szerkezet az XML-en alapulna. Az állományok mérete még kisebb jelentõségû. Az SVG dokumentumokat a gyakorlatban amúgy is tömörítik, ezáltal gyorsan eltûnnek a terjedelmes és kevésbé terjedelmes formátumok közötti különbségek (lásd az 50. szabályt). A nem XML többszintû stíluslapok (CSS, Cascading Style Sheets) formátumának beépítésével az SVG még tovább halad a rossz úton. Egy sokszöget például a következõ módon lehet kitölteni, körvonalazni és színezni: <polygon style="fill: red; stroke: blue; stroke-width: 10" points="350,75 379,161 469,161 397,215 423,301 350,250 277,301 303,215 231,161 321,161" />
A legfontosabb és leggyakoribb stílusoknál szerencsére az SVG jellemzõ alapú megoldást is lehetõvé tesz. Ez például az elõzõvel azonos sokszög: <polygon fill="red" stroke="blue" stroke-width="10" points="350,75 379,161 469,161 397,215 423,301 350,250 277,301 303,215 231,161 321,161" />
Mindamellett, mivel a CSS style (stílus) jellemzõje engedélyezett, az SVG-leképezõnek XML- és CSS-elemzõre is szüksége van. CSS-elemzõt könnyebb írni, mint XML-elemzõt, de így is jelentõs munkával jár. A CSS szabályainak megsértését ráadásul sokkal nehezebb észlelni. Mivel a hibakezelése kevésbé szigorú, könnyebb helytelen SVG dokumentumokat létrehozni úgy, hogy a szerzõ esetleg észre sem veszi. Az SVG kevésbé együttmûködõ és megbízható, mint ha tiszta XML-bõl állna. Ennek ellentéteként az XSL Formatting Objects (XSL-FO, XSL objektumformázás) annak példája, hogy miként lehet az XML formátumot megfelelõen egyesíteni az olyan régebbi formátumokkal, mint a CSS. Az XSL-FO megõrzi a CSS-tulajdonságok nevét, értékét és
XML02.qxd
11/6/2006
2:31 PM
Page 55
2. fejezet • Szerkezet jelentését, a CSS eredeti szerkezetét viszont az XML megfelelõjére cseréli. Az XSL-FO-ban nincsenek sokszögek, de íme egy kék színû, piros hátterû és 10 képpontos kerettel rendelkezõ bekezdés: Ide jön a bekezdés szövege.
Ez rendelkezik a CSS összes ismert elõnyével, a nem XML szerkezetek hátrányai azonban nem jelennek meg. A CSS jelentése megmarad, miközben az utasításforma az alkalmasabb XML-re változik.
Kerüljük a beleértett szerkezeteket! Különösen körültekintõnek kell lenni a beleértett (implicit) jelölésekkel, amelyeket gyakran térközök jeleznek. Vegyünk például egy egyszerû nevet: Lenny Bruce
A nevet idõnként egyetlen egységként kezelik, pedig meglehetõsen gyakran van szükség a vezetéknév és a keresztnév külön gyûjtésére, leginkább azért, hogy vezetéknév szerint rendezhessünk. Ez könnyûnek tûnik: a szóköznél egyszerûen ketté kell bontani a karakterláncot. Angol neveknél a keresztnév a szóköz elõtt áll, a vezetéknév pedig a szóköz utáni rész. Természetesen ez az algoritmus azonnal felborul, amikor további keresztnevek jelennek meg: Lenny Alfred Bruce
Választhatjuk azt, hogy nem foglalkozunk a második névvel, hanem egyszerûen a keresztnévhez kapcsoljuk azt, mivel amúgy is vezetéknév szerint rendezünk. Gondoljuk meg azonban, hogy mi történik olyankor, amikor a vezetéknévben szerepel szóköz: Stefania de Kennessey
A nyilvánvaló algoritmus rossz vezetéknevet társít az emberekhez. Ez igen sértõ lehet a megcsonkított nevû személyek számára, habár mindannyian találkoztunk már számos naiv programmal, amely pontosan ezt teszi. Mi a helyzet a címekkel? Nézzük például az alábbi neveket: Mr. Lenny BruceDr. Benjamin SpockTimothy Leary, Ph.D.William Kunstler, Esq.Ms. Anita HoffmanProf. John H. Exton, M.D., Ph.D.
55
XML02.qxd
56
11/6/2006
2:31 PM
Page 56
Hatékony XML Egy lehetséges megszólításokat tartalmazó hosszú lista segítségével minden bizonnyal készíthetõ olyan algoritmus, amely számításba veszi a címeket, a korábban egyszerûnek tûnõ mûvelet azonban egyre bonyolultabbá válik valós adatok ismeretében. Végül ne feledjük, hogy a vezetéknév nem minden kultúrában áll az utolsó helyen. Japánban (és Magyarországon) például a családnév rendes esetben elöl áll: Kawabata Yasunari
Amikor tehát japán neveket rendezünk, nem az utolsó, hanem az elsõ név alapján rangsorolunk. Nyilván nem akarunk olyan rendszert tervezni, amely képes kitalálni, hogy egy adott karakterlánc angol vagy japán név-e. Az is nehezíti a helyzetet, hogy a japán neveket gyakran (de nem mindig) felcserélik, ha angolra fordítják: Yasunari Kawabata
Sõt, a kínai írásjelekkel írott japán neveknél általában nincs is térköz a vezetéknév és a keresztnév között:
A probléma sokkal bonyolultabb, mint ahogy elsõ látásra tûnik. Minden gondunk megszûnik, ha kifejezett jelöléssel azonosítjuk a nevek különbözõ összetevõit, ahelyett, hogy a programra bíznánk azok kibogozását: LennyBruceLenny <Middle>Alfred BruceStefaniade Kennessey <Title>Mr. LennyBruce <Title>Dr. BenjaminSpockTimothyLeary, <Title>Ph.D. WilliamKunstler, <Title>Esq. <Title>Ms. AnitaHoffman
XML02.qxd
11/6/2006
2:31 PM
Page 57
2. fejezet • Szerkezet
<Title>Prof. John <MiddleInitial>H. Exton, <Title>M.D., <Title>Ph.D. KawabataYasunariYasunariKawabata
A szóközök helytelen használatának másik példája az olyan elbeszélõ dokumentumokban figyelhetõ meg, amelyek megpróbálnak jelentõséget tulajdonítani a szóközöknek, csakúgy, mint a következõ versben:1 <poem type="sonnet" poet="Eleanor Alexander"> For me, my friend, no grave-side vigil keep With tears that memory and remorse might fill; Give me your tenderest laughter earth-bound still, And when I die you shall not want to weep. No epitaph for me with virtues deep Punctured in marble pitiless and chill: But when play time is over, if you will, The songs that soothe beloved babes to sleep. No lenten lilies on my breast and brow Be laid when I am silent; roses red, And golden roses bring me here instead, That if you love or bear me I may know; I may not know, nor care, when I am dead: Give me your songs, and flowers, and laughter now.
A sortörések itt egy-egy verssor végét jelzik, az üres sorok pedig a versszakok befejezését. Ez azonban gondot jelenthet, ha a tartalom olyan környezetben jelenik meg, ahol a sorok megtörnek, illetve a szóközöket másképp szerkesztik, tipográfiai szempontok miatt. Továbbá, ezeket az üreshelyeken alapuló megszorításokat nem lehet ellenõrizni sem az XML (minden versszak egy vagy több sort tartalmaz), sem a költészet (a szonett elsõ versszakában hat, a másodikban nyolc sor szerepel) szempontjából. Ha a szóközök jelentõsége túl nagy, a szerzõk nagyobb valószínûséggel hibáznak. Sokkal jobb, ha egyértelmûen fejezzük ki a versszakok és a sorok felosztását: <poem type="sonnet" poet="Eleanor Alexander"> <stanza> For me, my friend, no grave-side vigil keepWith tears that memory and remorse might fill; Give me your tenderest laughter earth-bound still,And when I die you shall not want to weep. 1
Eleanor Alexander Now címû verse a The Country Series of Contemporary Poetry No. IX, Middlesex Poetry (High Holborn, U.K.: Fowler Wright Ltd., 1928) címû kötetbõl.
57
XML02.qxd
58
11/6/2006
2:31 PM
Page 58
Hatékony XML
No epitaph for me with virtues deepPunctured in marble pitiless and chill:But when play time is over, if you will,The songs that soothe beloved babes to sleep. <stanza> No lenten lilies on my breast and browBe laid when I am silent; roses red,And golden roses bring me here instead,That if you love or bear me I may know;I may not know, nor care, when I am dead: Give me your songs, and flowers, and laughter now.
Talán egyedül olyankor kell ragaszkodni a térközök pontos megõrzéséhez, amikor azok a tartalom fontos elemei, mondjuk e. e. cummings versei vagy Python forráskódok esetében. A számítógépes – akár Python, akár más nyelven írott – forráskód különleges eset: rengeteg szerkezet található benne, amely nem adja magát az XML-ben történõ kifejezéshez. Ezen kívül léteznek hozzá elemzõk, amelyek ugyanannyira elterjedtek és használhatók, mint az XML-elemzõk. (Ezeket általában a fordítóprogramok tartalmazzák.) A legfontosabb, hogy az XML dokumentumokba ágyazott forráskódoknak csupán két hagyományos felhasználási módja van: 1. A kód átadása a fordítónak. 2. A teljes, formázatlan kód megjelenítése a felhasználó számára (például programozási segédletben). A fenti esetek egyikénél sem valószínû, hogy az XML-t olvasó folyamatok kisebb részekre akarják osztani az adatokat, majd külön kezelni azokat, annak ellenére, hogy nyilvánvalóan vannak ilyen részek. Így van értelme annak, hogy a forráskód szerkezete implicit maradjon.
Hol a határ? A legszélsõségesebb (tréfás) tanács, amivel ezen sorok írója találkozott az, hogy egy egész számot, például a 6587-et így kell írni: 6587
Nyilvánvaló, hogy ez már túlzás – sokkal nehézkesebb lenne ezt feldolgozni, mint egy egyszerû, jelölés nélküli számot. Végül is szinte mindenki, aki számot akar alkalmazni, elemi mennyiségként kezeli azt, és nem különálló számjegyek összetételeként. Mindenesetre ez
XML02.qxd
11/6/2006
2:31 PM
Page 59
2. fejezet • Szerkezet jó irányt adhat arra vonatkozóan, hogy hol kell abbahagynunk a címkék hozzáadását. Semmi olyasmit nem kell tovább tagolni jelöléssel, amit rendes esetben egyetlen elemi értékként kezelnénk. Íme néhány határeset a könyv szerzõjének indoklásával, amelyben kifejti, hogy miért végezne további felosztást, illetve miért nem: • Mértékegységgel ellátott számok, például 7 px, 8,5 kg vagy 108 dB: Önmagában sem a szám, sem a mértékegység nem jelent semmit. Nem nagy segítség, ha tudjuk, hogy valamilyen tömeg kilogrammban van megadva, ha nem tudjuk, hány kilogrammról van szó. Ugyanígy nem sokat ér tudni, hogy valaminek a tömege 3,2, ha nem tudjuk, hogy 3,2 grammról, 3,2 kilogrammról vagy 3,2 tonnáról van szó. Ezért az ilyen mennyiségeket a következõképpen érdemes jelölni: 7,5kg és <sebesseg>32mph. • Idõ: Az idõ órákra, percekre és másodpercekre bontása nagyon hasonlít a dátumok példájához. Sõt, a dátum valójában csak egy valamivel durvább léptékû idõmérték, és a dátumokhoz idõpontokat csatolva pontosabban meghatározhatunk egy pillanatot. Az idõtartam azonban már más kérdés: olyan mennyiség, mint a San Jose és New York közötti repülési idõ vagy egy videókazettára SP üzemmódban rögzíthetõ percek száma. Itt a teljes idõ számít, nem a kezdõpont és a végpont. Az idõ naponként 24 órára, óránként 60 percre és percenként 60 másodpercre történõ felosztása a babilóniai csillagászat és az akkori hatvanas számrendszer történelmi emléke, nem pedig olyasmi, ami alapvetõen kötõdne a természetes mennyiségekhez. (az idõtartamok percek vagy másodpercek összegére válthatók, és nem kell három különbözõ mértékegységet használni.) E sorok írója ezért elõszeretettel kezeli az idõtartamot egyetlen mennyiségként, a 6h32m formátumot alkalmazva a strukturáltabb formátum helyett: 632. • Listák: A DTD-k (Document Type Definition, dokumentumtípus-meghatározás) és a sémák is meghatároznak olyan lista adattípusokat, amelyek képesek szóközökkel elválasztott tartalmat leírni. A DTD-knél ezek IDREF vagy ENTITY típussal bevezetett jellemzõk, a sémáknál pedig bármilyen listatípussal bevezetett elem vagy jellemzõ. Én ezt nem tartom szerencsésnek. Lehet, hogy ez az egyetlen módja, hogy több mennyiséget, például egységeket vagy számokat tartalmazó listát tároljunk a jellemzõkben, de amikor várhatóan több egységgel találkozunk, érdemesebb gyermekelemeket alkalmazni. Ha túl sok jellemzõt használunk, a jelölés áttekinthetetlenné válhat. • URL-ek: Az URL-ek (vagy URI-k) számos belsõ szerkezettel rendelkeznek. A http://www.cafeconleche.org:80/books/xmljava/chapters/ /ch09s07.html#d0e15480 URL például egy protokollból, egy kiszolgálóból (kiszolgálónév, tartománynév és felsõ szintû tartomány), egy kapuból, egy fájlútvonalból és egy töredékazonosítóból áll.
59
XML02.qxd
60
11/6/2006
2:31 PM
Page 60
Hatékony XML Elméletileg ezt a következõképpen jelölhetnénk: <protocol>http www.cafeconleche.org <port>80 /books/xmljava/chapters/ch09s07.htmld0e15480
Ezt az eljárást azonban szinte soha nem alkalmazzák, és ennek jó oka van. Az URL-ek szinte minden felhasználása – onnantól kezdve, hogy átadjuk egy API valamelyik függvényének, azon keresztül, hogy vágólapra helyezzük, és egy böngészõ címsorába illesztjük, egészen addig, hogy egy ház falára festjük – teljes URL-t vár, és nem csak annak egy darabját. Azokban a ritka esetekben, ahol az URL-t összetevõ elemeire kell bontani, a legtöbb API megfelelõ támogatást biztosít, ezért jobb, ha az URL-eket nem bontjuk az elvártnál tovább. Általánosságban, ha sejthetõ, hogy egy elemet hasznos további részekre bontani, akkor érdemes felbontani. Az XML-ben sokkal könnyebb újra összerakni a darabokat, amikor a tartalmat címkék aprózzák fel, mint felbontani úgy, hogy nincs elég címke. Ritkán okoz gyakorlati problémát az, ha az adatok túl sok jelölést tartalmaznak. Sokkal kellemetlenebb, ha túl kevés a jelölés.
12. szabály A metaadatokat tároljuk jellemzõkben! Az xml-dev levelezési listán idõrõl idõre kisebb véleményháború zajlik arról, hogy mikor kell jellemzõket, és mikor elemeket alkalmazni. A vita kissé hevesebb azzal kapcsolatban, hogy szabad-e egyáltalán jellemzõket használni. A végeredmény az, hogy ez valójában a felhasználótól függ. Mindig azt tegyük, ami az adott alkalmazásban megfelelõnek tûnik. A legtöbb fejlesztõ inkább használ jellemzõket a metaadatokhoz, mint magukhoz az adatokhoz, de ez a legjobb esetben is csak egy nagyon általános irányelv. Természetesen az, hogy mi adat és mi metaadat, az nagy mértékben függ attól, hogy ki és milyen céllal olvassa az adott dokumentumot. Egy lehetséges módszer, amellyel az információról eldönthetjük, hogy metaadat-e vagy sem, ha megpróbáljuk megválaszolni, hogy a szöveget olvasó személy szeretné-e látni azt. Vegyük például az XML Base szabvány alábbi bekezdését: Az xml:base jellemzõkben engedélyezett karakterkészlet ugyanaz, mint az XML-ben, név szerint a [Unicode]. Néhány Unicode karakter azonban nem engedélyezett az URI hivatkozásokban, ezért a feldolgozóknak vezérlõjelekkel kell kódolniuk ezeket a karaktereket, hogy érvényes URI hivatkozást kapjanak a jellemzõértékbõl.1 1
XML Base W3C ajánlás, 2001. június 27. Letöltve 2003 júniusában a http://www.w3.org/TR/xmlbase/#escaping címrõl.
XML02.qxd
11/6/2006
2:31 PM
Page 61
2. fejezet • Szerkezet Ha ezt a DocBook-ban jelölésekkel szeretnénk ellátni, minden fenti szó az elemtartalom része lenne: <para id="p32"> Az <markup>xml:base jellemzõkben engedélyezett karakterkészlet ugyanaz, mint az XML-ben, név szerint a [Unicode]. Néhány Unicode karakter azonban nem engedélyezett az URI hivatkozásokban, ezért a feldolgozóknak vezérlõjelekkel kell kódolniuk ezeket a karaktereket, hogy érvényes URI hivatkozást kapjanak a jellemzõértékbõl.
Az alábbi részeket viszont jellemzõértékekben tárolnánk: • • • • • •
Azonosítók Stílusok Távoli hivatkozások URL-jei Távoli hivatkozások címei Módosítások dátuma A szerzõ neve
Ezekben az adatelemekben az a közös, hogy az olvasó nem akarja õket a rendes szövegfolyamban látni. Természetesen hasznosak és van céljuk: az url jellemzõben szereplõ URL nélkül például a böngészõ nem tudja, hogy az adott hivatkozás hová mutat, az id jellemzõ nélkül más oldalak nem tudnak erre a bekezdésre hivatkozni, a módosítások dátuma nélkül pedig a szerzõ nem tudja áttekinteni, majd elfogadni, illetve elvetni a változtatásokat. Mindenesetre a végfelhasználó számára, aki csupán egymás után szeretné olvasni a szavakat, ezek nem számítanak. A jellemzõértékek némelyike befolyásolhatja, hogy a szöveg miként jelenik meg az olvasó elõtt, például hogy egy szó dõltbetûs vagy egy hivatkozás aláhúzott-e, az olvasó azonban semmilyen esetben nem akarja látni a jellemzõértéket alkotó szöveget, mert az igen zavaró lenne: p32 Az xml:base jellemzõkben engedélyezett karakterkészlet ugyanaz, mint az XML-ben, név szerint a [Unicode http://www.w3.org/TR/xmlbase/#Unicode]. Néhány Unicode karakter azonban nem engedélyezett az URI hivatkozásokban, ezért a feldolgozóknak vezérlõjelekkel kell kódolniuk Must, May, etc. http://www.w3.org/TR/xmlbase ezeket a karaktereket, hogy érvényes URI hivatkozást kapjanak a jellemzõértékbõl. Néhány különleges esetben elõfordulhat, hogy az olvasó látni szeretné a jellemzõérték tartalmát. Amikor például a felhasználó egy hivatkozás fölé viszi az egeret, a böngészõ egy gyorssúgóban vagy a böngészõ címsorában megjelenítheti a hivatkozás címét vagy az URL-t. Ez azonban többletinformáció, amely továbbra sem a rendes szövegfolyam részeként jelenik meg.
61
XML02.qxd
62
11/6/2006
2:31 PM
Page 62
Hatékony XML A rekordszerû dokumentumokban közel sem olyan éles a határvonal az adatok és a metaadatok között, mint a leíró jellegû dokumentumokban. A felhasználókat a tartalom másmás tényezõi érdekelhetik. Lehet, hogy az, ami az egyik felhasználónak jelentéktelen adat, egy másik olvasó számára éppen az egész lényege. Gyakran több ésszerû módszer létezik, amellyel az adatokat eloszthatjuk az elemek tartalma és a jellemzõértékek között, mindazonáltal mindig ugyanaz az alapelv érvényes: ha az információ lényeges, elemtartalomként kell megadni. A jellemzõket az olyan rendezési információk számára tartsuk fenn, mint például az azonosítószámok. Annak ellenére, hogy az adatok és a metaadatok nagy vonalakban történõ elkülönítése hasznos módszer annak eldöntésére, hogy valamilyen egyszerû szöveget jellemzõbe illesszünk-e vagy sem, van egy szabály, ami magasabb rendû: a strukturált adatoknak az elemtartalomban kell szerepelniük. A jellemzõértékek nem megkülönböztetett szöveget tartalmaznak. Nincs alapszerkezetük, legalábbis nem olyan, ami elérhetõ lenne az XMLelemzõ számára. A jellemzõértékek tartalmazhatnak számot, URL-t, dátumot, idõt vagy más elemi értéket, a bonyolultabb szerkezeteket azonban gyakran összetevõkre kell bontani, és ezt csak elemekkel hajthatjuk végre ésszerûen. Vegyük például ezt a blockquote (idézetblokk) elemet, ahol az src jellemzõ az idézet forrásának jelölésére szolgál.
Az Internettel kapcsolatban soha nem volt semmiféle nagy terv, és ma sincs ilyen. A Háló csupán a Háló, de <em>ténylegesen hatékony kommunikációs eszközöket nyújtott azoknak, akiket olyan régóta figyelmen kívül hagynak, és akik olyan régóta láthatatlanok, hogy még csak most kezdenek rájönni, mit kezdjenek a lehetõséggel. Érdekes, hogy törvények, tervek és vezetés nélkül sokkal hamarabb felfedezik, mire használható az Internet, mint a kormányhivatalok, a tudományos intézmények és a gazdag, befolyásos vállalatok.
Az src jellemzõben több különbözõ információegység szerepel: a szerzõ, a fejezet címe, a könyv címe, a kiadó, az oldalszám és így tovább. Ezek esetleg külön jellemzõkre bonthatók, az alábbi módon:
...
XML02.qxd
11/6/2006
2:31 PM
Page 63
2. fejezet • Szerkezet Ezáltal azonban az alapszerkezet, például a kereszt- és a vezetéknév vagy a sorrend követhetetlenné válik. Én például az eredeti idézet leírásakor ügyeltem arra, hogy kövessem a Chicago Manual of Style szabályait. Amikor az idézetet külön jellemzõkre bontjuk, ez érvényét veszti. De mi történik, ha a fejezetnek több szerzõje van? Egy adott elemben csak egy author (szerzõ) névvel ellátott jellemzõ szerepelhet, viszont korlátlan számú gyermekelemmel rendelkezhet. Nem, valójában itt egy source (forrás) gyermekelemre van szükség, annak ellenére, hogy a forrás egyértelmûen az idézettel kapcsolatos metaadat, és nem lényegi információ.
Az Internettel kapcsolatban soha nem volt semmiféle nagy terv, és ma sincs ilyen. A Háló csupán a Háló, de <em>ténylegesen hatékony kommunikációs eszközöket nyújtott azoknak, akiket olyan régóta figyelmen kívül hagynak, és akik olyan régóta láthatatlanok, hogy még csak most kezdenek rájönni, mit kezdjenek a lehetõséggel. Érdekes, hogy törvények, tervek és vezetés nélkül sokkal hamarabb felfedezik, mire használható az Internet, mint a kormányhivatalok, a tudományos intézmények és a gazdag, befolyásos vállalatok.
Amikor az alapszerkezetet elemek fejezik ki, egy stíluslap egyszerûen képes a szándékunk szerint megjeleníteni vagy elrejteni a tartalom tetszõleges részét. Tegyük fel például, hogy meg szeretnénk jeleníteni a szerzõ nevét, a könyv címét, az évet és az oldalszámot, a kiadót és a fejezetcímet viszont ki akarjuk hagyni. Ezt a következõ CSS szabályok teljesítik: source, author, book, year, page { display: inline } publisher, publisher_city, chapter { display: none }
Ha mindössze egyetlen nagy jellemzõ állna rendelkezésre, ezt tényleg nem tudnánk megvalósítani. Az elemek még egy nagy elõnye a jellemzõkkel szemben, hogy sokkal jobban bõvíthetõk. Számos könyvtár szereti például megadni a szerzõ születési évét a katalógusban. Elemek segítségével ez könnyen megoldható:
63
XML02.qxd
64
11/6/2006
2:31 PM
Page 64
Hatékony XML
ChristopherLocke1950
Jellemzõkkel sokkal nehézkesebb lenne ilyen kiegészítõ adatok hozzáadása. Egy adott elem altípusának meghatározása az olyan jellemzõk gyakori felhasználási módja, amelyekrõl egyértelmûen elmondható, hogy inkább jellemzõkhöz tartozó metaadatok, mint gyermekelemekbe való adatok. A HTML-ben és az XHTML-ben például gyakran találkozunk class (osztály) jellemzõvel ellátott elemekkel, leginkább a div-vel és a span-nel:
...
...
...
...
<span class="person">... <span class="book">...
A class jellemzõ itt kibõvíti az egyébként meglehetõsen kötött HTML szótárt. Az elemek osztályonként történõ azonosítása lehetõvé teszi a szerzõ számára, hogy a különbözõ osztályok elemeihez különbözõ stílusokat vagy feldolgozási szabályokat rendeljen, még akkor is, ha azonos a nevük. Belátható, hogy ez egyértelmûen metaadat, ugyanúgy, ahogy egy elemnév is az. Ezek a jellemzõk tulajdonképpen érvénytelen elemneveket helyettesítenek, ezért a kezdõcímkében van a helyük, csakúgy, mint az elemneveknek. Ha azt vesszük észre, hogy sûrûn használunk ilyen jellemzõket, az azt jelzi, hogy a jelölés szótára nem megfelelõ az adatok számára. A DocBook hasonlóképpen használja a role (szerep) jellemzõt, ezáltal lehetõvé teszi a szerzõknek, hogy olyan tetszõleges szerepeket rendeljenek az elemekhez, amelyekre a DocBook tervezõi nem is gondoltak. Valamivel szabályszerûbben: a DocBook systemitem (rendszerelem) elemének van egy class jellemzõje, amelynek értékét meghatározott típusú (domainname – tartománynév, ipadress – IP cím, newsgroup – hírcsoport és username – felhasználónév) systemitem elemekbõl álló felsorolásként adják meg: H2OPaxil, 20 mgLaurenceBienvenue <systemitem class="domainname">www.cluetrain.com <systemitem class="username">eharold
A DocBook ezt nagyon ésszerûen kezeli. Ha úgy találják, hogy egy adott szerepet vagy osztályt sûrûn használnak a gyakorlatban, akkor az a következõ DocBook-változatban jó eséllyel szerepel majd elemként. Több jelenlegi DocBook-elem, például az environvar és a prompt korábban systemitem osztályként vagy egyszerû szerepként létezett.
XML02.qxd
11/6/2006
2:31 PM
Page 65
2. fejezet • Szerkezet Végül, ha bármilyen kétség merül fel azzal kapcsolatban, hogy az információ metaadat vagy adat-e, érdemes inkább elemtartalomként szerepeltetni azt. Kevés olyan dolog van, amire egy jellemzõ képes, de egy elem nem, viszont az elemek sok mindenre képesek, amire a jellemzõk nem. Sokkal nagyobb árat fizetünk, ha jellemzõként adunk meg egy olyan adatot, amelynek elemnek kellene lennie, mint ha tévesen elemként jelölünk egy olyat, amelynek jellemzõben lenne a helye.
13. szabály Ügyeljünk a vegyes tartalom ra! Az XML olyan leíró dokumentumok számára készült, amelyeket elvileg emberek olvasnak: könyvekhez, regényekekhez, színdarabokhoz, versekhez, mûszaki leírásokhoz és fõképpen weboldalakhoz. A rekordközpontú adatok terén történõ felhasználás csak szerencsés véletlen. A leíró dokumentumok számos olyan tulajdonsággal rendelkeznek, amelyek a rekordszerû adatoknál ritkán érvényesek. Nézzük például ezt az egyszerû bekezdést, amely az XML szabvány második kiadásából származik:
Ez a második kiadás <emph>nem az XML új változata (amelyet elõször 1998. február 10-én adtak ki), csupán azokat a változtatásokat foglalja magában, amelyeket az elsõ kiadás hibajegyzéke (elérhetõ a http://www.w3.org/XML/xml-19980210-errata címen) tett szükségessé. A mostani, második kiadás hibajegyzéke a következõ címen érhetõ el: http://www.w3.org/XML/xml-v10-2e-errata.
A bekezdésben hét gyermek szerepel, a következõ sorrendben: 1. 2. 3. 4. 5. 6. 7.
Egy „Ez a második kiadás”-sal kezdõdõ szövegcsomópont. Az emph elem. Egy „az XML új változata”-val kezdõdõ szövegcsomópont. Egy loc elem. Egy „címen ) tett szükségessé”-vel kezdõdõ szövegcsomópont. Egy loc elem. Egy egyetlen pontot tartalmazó szövegcsomópont.
A szöveg a fa ugyanazon szintjén helyezkedik el, mint a gyermekelemek. A bekezdés jelentése szempontjából ez egy rendkívül fontos dolog, amit nem lehet figyelmen kívül hagyni. Ennek ellenére számos eszköz és API feltételezi naivan, hogy vegyes tartalom egyszerûen nem létezik. Ezek a feltételezések a relációs táblák esetében helyesek, és noha az olyan XML formátumokra is igazak, amelyek szinte nem csinálnak mást, mint hogy kiírják egy adatbázis tartalmát (például az RSS 0.9.x), a legtöbb valóságos XML esetében biztosan nem
65
XML02.qxd
66
11/6/2006
2:31 PM
Page 66
Hatékony XML helytállóak; gyakran olyan alkalmazásoknál sem, amelyekrõl a fejlesztõ ezt képzeli. Az RSS-t például eredetileg arra tervezték, hogy az alábbihoz hasonló, egyszerû rekordszerû hírcikkeket hozzon létre: Xerlin 1.3 released <description> Xerlin 1.3, an open source XML Editor written in Java, has been released. Users can extend the application via custom editor interfaces for specific DTDs. New features in version 1.3 include XML Schema support, WebDAV capabilities, and various user interface enhancements. Java 1.2 or later is required. http://www.cafeconleche.org/#news2003April7
Folyamatosan világossá vált azonban, hogy ez nem elég ahhoz, hogy megfeleljen a webhelyek többsége által támasztott igényeknek. A webhelyek készítõi különösen a leírásba szerettek volna gyakran vegyes tartalmat illeszteni, ahogy a következõkben látjuk: <description> <strong>Xerlin 1.3,an open source XML Editor written in Java, has been released. Users can extend the application via custom editor interfaces for specific DTDs. New features in version 1.3 include:
XML Schema support
WebDAV capabilities
Various user interface enhancements
Java 1.2 or later is required.
Mivel azonban az RSS ezt nem teszi lehetõvé, a szerzõk és a gyártók igazán rettenetes megoldáshoz folyamodtak – HTML vezérlõkarakterekhez: <description> <strong>Xerlin 1.3, an open source XML Editor written in Java, has been released. Users can extend the application via custom editor interfaces for specific DTDs. New features in version 1.3 include:
XML Schema support
WebDAV capabilities
Various user interface enhancements
Java 1.2 or later is required.
XML02.qxd
11/6/2006
2:31 PM
Page 67
2. fejezet • Szerkezet Ezt a rondaságot nem csak azért csinálták, hogy ki lehessen küszöbölni a vegyes tartalmat, hanem a névtereket (20. szabály) és a modularizálást (8. szabály) is elkerülték vele. Általában azonban a vegyes tartalomtól való félelem a döntõ tényezõ. Ami a fenti példában igazán sokatmondó, hogy a közösség a saját, csúnyább, vegyes tartalommal rendelkezõ változatát azonnal visszabarkácsolta az RSS-be, annak ellenére, hogy az eredeti fejlesztõk ezt megpróbálták elkerülni. A vegyes tartalom nem hiba, nem kell tartani tõle. Éppen ilyen információk jelölésére találták ki az XML-t. A vegyes tartalmat helyesen kezelni nem képes eszközök köre az olyan egyszerû programoktól, mint az XML-megjelenítõk, a teljes adat-összekapcsoló API-kig terjed. Jómagam találkoztam egy különösen megátalkodott API-val, amely elolvasta a vegyes tartalmat, de úgy rendezte át azt, hogy az összes egyszerû szövegcsomópont a gyermekelemek mögé került. Számos más eszközt készítettek, amely nem támogatja a vegyes tartalmat – ezeken utólag bonyolult és költséges átalakításokat kellett végezni, amikor nyilvánvalóvá vált a támogatás szükségessége. Szintén gyakori problémát jelentenek azok a programok, amelyek azt állítják magukról, hogy képesek kezelni a vegyes tartalmat, de soha nem ellenõrizték õket alaposan leíró dokumentumokkal. Én már több XML-szerkesztõt kényszerítettem térdre DocBook-ban írt könyvek betöltésével. A programozók igen gyakran vétenek olyan hibákat a kódban, amelyek az XML dokumentumok megjelenésével kapcsolatos hibás elképzeléseken alapulnak. Az a programozó például, aki megfeledkezik a vegyes tartalomról, esetleg Element (elem) objektumokból álló listaként próbálja meg tárolni az elemek gyermekeit egy általánosabb, Object (objektum) vagy Node (csomópont) objektumokból álló lista helyett. Egy valódi XML-programnak fel kell készülnie az összes olyan formátum kezelésére, amelyeket az XML fogadni képes, beleértve a leíró és a rekordszerû dokumentumokat. A problémák abban gyökereznek, hogy a tervezõk elõször azt kérdezik, hogy miként lehet az objektumokat XML dokumentummá alakítani, és nem a sokkal nehezebb kérdést teszik fel, azaz azt, hogy miként lehet XML dokumentumokat objektummá alakítani. Van, aki a „Hogyan lehet relációs adattáblákat XML dokumentumokká alakítani?” kérdéssel indít, az alapprobléma azonban ugyanaz. A fogkrémtubushoz hasonlóan sokkal könnyebb kipréselni az XML-t egy objektumból, mint visszanyomni. A legtöbb ilyen eszköz azt állítja, hogy képes Java vagy C++ formátummá alakítani az XML dokumentumokat, de nagyon hamar kudarcot vallanak, ahogy elkezdjük valódi dokumentumokkal bombázni õket. Általánosságban elmondható, hogy a fejlesztõk hibás feltételezések alapján dolgoznak, beleértve a következõket: • A dokumentumok W3C XML sémanyelvû sémákkal rendelkeznek. (A nagy többségnél ez nem igaz.) • A dokumentumok rendelkeznek valamilyen sémával. (A legtöbb nem rendelkezik.) • Az olyan dokumentumok, amelyek valóban rendelkeznek valamilyen sémával, tényleg követik azt a sémát. (Gyakran ez sem igaz.)
67
XML02.qxd
68
11/6/2006
2:31 PM
Page 68
Hatékony XML • Még mielõtt látnánk a dokumentumot, tudjuk, milyen szerkezetekkel találkozunk majd. Más szóval: a dokumentumok kiszámíthatók. (Nem ésszerûtlen feltételezés, ennek ellenére a gyakorlatban gyakran téves.) • Vegyes tartalom nem létezik. (Nyilvánvalóan hamis.) • Az XML dokumentumok meglehetõsen laposak, sõt, a szerkezetük szinte táblázatos. (Azok hajlamosak ezt feltételezni, akik adatbázis-leképezéssel foglalkoznak. Kisebb a valószínûsége, hogy az objektumokkal foglalkozók éppen ebbe a hibába essenek.) Ugyanezek a problémák merülnek fel olyankor, amikor a fejlesztõk XML adatokat relációs táblákban próbálnak tárolni. Az XML dokumentumok nem táblák. Különbözõ (nagyon nem elegáns) módszerekkel ugyan táblákba lehet erõltetni õket, de a relációs adatbázisokat egyszerûen nem erre a feladatra találták ki. Jobban járunk egy olyan adatbázissal és API-val, amelyet eleve az XML-hez terveztek, és nem próbál úgy viselkedni, mintha az XML egyszerûbb lenne, mint amilyen valójában. Az igazság az, hogy az XML dokumentumok teljes általánosságukban tekintve rendkívül bonyolultak. Nem táblák, és nem is objektumok. Csak az olyan modellek elfogadhatók, amelyek számolnak ezzel a bonyolultsággal. A szerkezetük nagyon ritkán felel meg a táblák és objektumok sokkal szûkebb tartományának. Természetesen leképezhetünk XML osztályokat, de amennyiben nem egy nagyon szûk területen dolgozunk, kérdéses, hogy képesek vagyunk-e a JDOM-nál sokkal egyszerûbb dolgot kitalálni. Ha pedig korlátozott területen dolgozunk, akkor tulajdonképpen mindössze egy szabványos módszerre van szükségünk, amellyel az osztályok példányait meghatározott XML formátumba sorosíthatjuk, illetve onnan visszaállíthatjuk. Ennek mûködésérõl az ügyfélprogram készítõjének szinte nem is kell tudnia. Legyünk elõvigyázatosak az olyan eszközökkel, amelyek alegységként magukba foglalják az XML-t, és csak bizonyos típusú XML dokumentumokat kezelnek. A hatékony, megbízható XML-feldolgozáshoz olyan eszközre van szükség, amely az XML egészét képes kezelni, beleértve a vegyes tartalmat.
14. szabály Engedélyezzük az XML minden nyelvi elemét! Az XML alkalmazásokat az elemek és a jellemzõk köré kell tervezni. Sémák vagy DTD-k alkalmazásával korlátozhatjuk, hogy mely elemek és jellemzõk hol fordulhatnak elõ, és mi lehet a tartalmuk. További olyan korlátozásokat is bevezethetünk, amelyek a dokumentum tartalmát szabályozzák, de nem lehet sémákkal kifejezni. Elõfordulhat például, hogy azt akarjuk, hogy egy Employee (alkalmazott) elem ID jellemzõje egy jelenlegi vagy volt alkalmazott tényleges azonosítószáma legyen. Ezek mind a dokumentum tartalmának és szerkezetének megszorításai. Általánosan tükrözik egy bizonyos alkalmazásterület jelentését (szemantikáját).