XML-séma értelme és a dokumentum érvényesség ellenőrzése

A másodlagos jelző egyfajta használati vagy akár keletkezési sorrendet akar szimbolizálni, mivel az érvényes XML dokumentumok létrehozásának eredeti és talán elterjedtebb módja a DTDk használata, melyet az XML specifikáció is magába foglal.
Ezek után gondolom sokakban megfogalmazódik a kérdés: vajon mi értelme az XML sémának?

A kérdés megválaszolásához nem kell messzire mennünk, mivel elég, ha átfutjuk a DTD-kkel foglalkozó cikk bevezető részét. A DTD-k két, talán legnagyobb hátránya a külön szintaktika és némely helyzetekben a dokumentum tartalma feletti gyér ellenőrzés.
Ezek után fordítsunk egy kicsit a megközelítésen és ugyanezen két dolgot soroljuk fel az XML-séma előnyeként.

Következő fontos eltérés a deklaráció elhelyezésénél lép fel, mivel a DTDket deklarálhattuk az XML dokumentumon belül, vagy akár kívül egy külső fájlban, amelyet egy hivatkozás segítségével linkeltünk be. Az XML-sémáknál ez nem így van. Az XML-séma definíció, csakis kizárólag egy külső fájlban lehet, amelyet nem linkelünk be az XML dokumentumba. Ekkor viszont hogyan tudja a mi okos kis alkalmazásunk, hogy melyik sémával vesse össze az XML-dokumentumot?
A választ egyenesen az XML-séma szerinti érvényesség ellenőrző szkript működésének megértésével kapjuk meg.

XML-sema ellenor

<HTML> <HEAD><TITLE>Érvényesség-ellenorzo (Sema)</TITLE> <SCRIPT LANGUAGE="JavaScript"> function XML_SEMA_ellenor(dok_URL, sema_URL, nevter_neve) {   var XMLDocument = new ActiveXObject("Msxml2.DOMDocument.4.0"),       XMLSemaCache = new ActiveXObject("Msxml2.XMLSchemaCache.4.0");   XMLSemaCache.add(nevter_neve, sema_URL);   XMLDocument.schemas = XMLSemaCache;   XMLDocument.async = false;   XMLDocument.load(dok_URL);   if(XMLDocument.parseError.errorCode != 0)     {      var msg;      msg = "Hibaszám: "     + XMLDocument.parseError.errorCode + "\n"         + "fájlpozíció: "   + XMLDocument.parseError.filepos   + "\n"         + "sor: "           + XMLDocument.parseError.line      + "\n"         + "karakter: "      + XMLDocument.parseError.linepos   + "\n"         + "leírás: "        + XMLDocument.parseError.reason    + "\n"         + "forrás szöveg: " + XMLDocument.parseError.srcText   + "\n"         + "URL: "           + XMLDocument.parseError.url;               return alert(msg);     }else alert("OK"); } </SCRIPT> </HEAD> <BODY onLoad="XML_SEMA_ellenor('Leltar Elofordulas.xml', 'Leltar Sema.xsd', '')"> <H2>Sémát használó érvényesség-ellenorzo</H2> </BODY> </HTML>
Magyarázat:
A HTML dokumentum betöltődése (BODY onLoad) után meghívódik a XML_SEMA_ellenor(dok_URL, sema_URL, nevter_neve) függvényünk a következő paraméterekkel:
  • dok_URL - az ellenőrizni kívánt XML dokumentum URL-je
  • sema_URL - az XML-séma URL-je, amely szerint ellenőrizni szeretnénk az XML dokumentumot
  • nevter_neve - az ellenőrizni kívánt XML dokumentum dokumentumelem névterének neve
A függvényben létrehozunk két ActiveX objektumot, az XMLDocument-ot, amely az XML dokumentum betöltését fogja végezni és a XMLSemaCache-t, amely az XML-séma betöltését fogja végezni. Ezután betöltjük az XML-sémát a XMLSemaCache objektum add metódusával, melynek paraméteréül átadjuk az ellenőrizni kívánt XML dokumentum dokumentumelem névterének nevét (vagy üres sztringet, ha nem tartozik semilyen névtérhez) és az XML-séma URL-jét. Végezetül a séma objektumot (XMLSemaCache) hozzárendeljük a dokumentum objektumhoz (XMLDocument) és szinkron módon (addig nem fut tovább a program, míg az egész dokumentum be nem töltődik) betöltjük az XML dokumentumot (XMLDocument.load(dok_URL)).
Ezt a DTD-s ellenőrző szkriptünkből jól ismert sorok követik, amikor is kiiratjuk az egyes érvényességi hibákat.

Lényegében annyi az eltérés a DTD-s ellenőrőző szkripttől, hogy programilag kell az egyes XML dokumentumokhoz sémát rendelni.

 

XML-séma definíció létrehozása

Mivel az XML-séma elég sok lehetőséget biztosít a dokumentum tartalmának leírására, ezért nehézkes és talán érthetetlen is lenne egy általános definíció alakot leírni. Éppen ezért inkább példákon szeretném bemutatni a XML-séma definíció használatát, valamint támaszkodni fogunk az előző részekben definiált fogalmakra, s így az ismétlések helyét érékes példák foglalhatják el.
Az XML sémadefiníciót egy külön fájlban kell létrehozni, amelyre ugyanazon jólformázottsági szabályok vonatkoznak mint egy XML dokumentumra, melyeket pár kiegészítés követ:

  • egyetlen legfelső szintű elemet tartalmazhat a schema-t
  • az összes sémában használt elemnek és jellemzőnek az "http://www.w3.org/2001/XMLSchema" névtérhez kell tartozni, ezzel is jelezve, hogy XML-sémáról van szó
Ezek után lassunk egy egyszerű példát az XML-séma definíció létrehozására:

egyszeru.xsd

<?xml version="1.0" encoding="ISO-8859-2"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">   <xsd:element name="F1VILAGBAJNOK" type="xsd:string"> </xsd:schema>
egyszeru.xml
<?xml version="1.0" encoding="ISO-8859-2"?> <F1VILAGBAJNOK>Jacques Villeneuve</F1VILAGBAJNOK>
A séma definícióban létrehoztuk a legegyszerűbb XML dokumentum definícióját, amely egyetlen elemet tartalmaz, a dokumentumelemet, melynek bárminemű szöveges tartalma lehet. Ezután létrehoztunk egy XML dokumentumot, amely megfelel ennek az XML-séma definíciónak.
Egyszerű elemtípusok deklarációja

Az XML-sémában az elemeket az element elemmel tudjuk deklarálni, melyen belül mindenképpen fel kell tüntetnünk az elem nevét.
Amennyiben egyszerű típusú elemet(nem tartalmaz gyermekelemeket) deklarálunk nem származtatott tartalom-típussal, úgy magát az elem (tartalom) típust is az element elemen belül kell megadni:

<xsd:element name="NEV" type="xsd:string"/> <xsd:element name="DATUMIDO" type="xsd:dateTime"/>
A példánkban két egyszerű típusú elemet deklaráltunk (NEV, DATUMIDO), melyek típusmeghatározásánál az XML-séma alaptípusait használtuk fel. Az XML-séma egyszerű típusai közül néhány:
  • string - bármilyen érvényes karakter (érvényes karakterek definícióját lásd a cikksorozat 2. részében)
  • integer - <-126789, 126789> intervallumból bármilyen egész szám, vagy nulla. Pl. (-100, 0, 15)
  • positiveInteger - <1, 126789> intervallumból bármilyen egész szám. Pl. (2, 50, 999)
  • negativeInteger - <-126789, -1> intervallumból bármilyen egész szám. Pl. (-25, -559, -78902)
  • nonNegativeInteger - <0, 126789> intervallumból bármilyen egész szám. Pl. (0, 50, 98745)
  • nonPositiveInteger - <-126789, 0> intervallumból bármilyen egész szám. Pl. (0, -50, -98745)
  • decimal - pozitív illetve negatív tizedes szám
  • time - idő a következő formátumban: óó:pp:mm[.mm+-UTC], Pl. (14:30:00, 16:30:00.0, 16:30:00-01:00, 16:30:00.00-01:00)
  • dateTime - dátum és idő a következő formátumban: éééé-hh-nnTóó:pp:mm.mm+-UTC. Pl. (2004-03-15T15:30:00.0-01:00)
  • gYear - év a következő formátumban: éééé. Pl. (2004, 1983)
  • gMonth - hónap a következő formátumban: --hh--. Pl. (--03--, --12--) -> (március, december)
  • gDay - nap a következő formátumban: ---nn. Pl. (---01, ---23)
  • gYearMonth - év és hónap a következő formátumban: éééé-hh. Pl. (1983-02)

Az XML-séma által támogatott egyszerű típusok teljes listája megtalálható a XML Schema Part 0: Primer Second Edition címen. Ezen típusok úgynevezett alaptípusok, amelyekből lehetőség van saját típus létrehozására úgy, hogy az egyes alaptípusokból egy saját típust származtatunk. Vegyük alapul a forma1-es példánkból az EV elemet. A gYear típus használatával ugyan biztosítva van, hogy az EV elem biztosan megfelelő formátumú évet fog tartalmazni, viszont mi tudjuk, hogy csak 1954 és 2003 között rendeztek forma1-es futamokat. Nincs más teendőnk, minthogy lekorlátozzuk a gYear típust:
<xsd:element name="EV">                  <xsd:simpleType>                        <xsd:restriction base="xsd:gYear">       <xsd:minInclusive value="1954"/>       <xsd:maxInclusive value="2003"/>     </xsd:restriction>                  </xsd:simpleType>                    </xsd:element>
Ahogy az a definíciórészletből is kiderül a típusszármaztatás a restriction elem segítségével történik amely a simpleType gyermekeleme, egyszerű típusról lévén szó. A restriction elem base jellemzőjének adjuk meg azt a típust, amelyből származtatni szeretnénk a saját típusunkat. A restriction elem gyermekelemeiként megadhatjuk az új típusra vonatkozó megszorításokat. Jelen esetben ezek a megszorítások a minimális(minInclusive) és maximális(maxInclusive) érték meghatározása. Ezen kívül használhatnánk még:
  • reguláris kifejezést(pattern) - segítségével egy olyan sablont hozhatunk létre, amelyel pontosan leírhatjuk egy karaktersorozatban használható karakterek listáját illetve sorrendjét. Pl.:
    <xsd:simpleType name="szemelyiSzamTipus">                <xsd:restriction base="xsd:string">        <xsd:pattern value="[A-Z]{2} \d{6}"/>   </xsd:restriction>                      </xsd:simpleType>    <!-- megfelelő típusok pl. ("SP 225588", "KC 147896", ...) --> <xsd:simpleType name="emailTipus">   <xsd:restriction base="xsd:string">     <xsd:pattern value="^([0-9,a-z,A-Z]+)([.,_]([0-9,a-z,A-Z]+))*[@]([0-9,a-z,A-Z]+)([.,_,-]([0-9,a-z,A-Z]+))*[.]([0-9,a-z,A-Z]){2}([0-9,a-z,A-Z])?$" />   </xsd:restriction> </xsd:simpleType> <!-- megfelelő típusok pl. ("pityi@palko.hu", "info@microsoft.com", ...) -->
  • felsorolást(enumeration) - melynél egy előre definiált lista elemei közül választhatunk egyet. Pl.:
    <xsd:simpleType name="nemTipus">   <xsd:restriction base="xsd:string">     <xsd:enumeration value="férfi" />     <xsd:enumeration value="nő" />   </xsd:restriction> </xsd:simpleType> <!-- megfelelő típusok ("ferfi", "nő") -->
  • minimális érték(minInclusive) meghatározását - lásd a használatát feljebb
  • maximális érték(maxInclusive) meghatározását - lásd a használatát feljebb
Gondolom mindenkinek feltűnt, hogy másként vannak definiálva a lista példaprogramjaiban található típus-származtatások és az első példaprogram típus-származtatása. Mindkét megoldás helyes, az első példaprogramban névtelen típust hoztunk létre, míg a többiben nevesítettet. Működésileg semmi különbség sincs a két megoldás között. Ha nevesített típust hozunk létre, akkor azt a típust az egész sémában használhatjuk mint új típus (egyszerűen a típushoz a mi új származtatott típusunk nevét írjuk).

Ezek után készítsünk egy embereket nyilvántartó adatstruktúrát, felhasználva a saját adattípusainkat:

taglista.xsd

<?xml version="1.0" encoding="ISO-8859-2"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <!-- szemelyi szam tarolasara letrehozott tipus --> <xsd:simpleType name="szemelyiSzamTipus">                <xsd:restriction base="xsd:string">        <xsd:pattern value="[A-Z]{2} \d{6}"/>   </xsd:restriction>                      </xsd:simpleType> <!-- email cim tarolasara letrehozott tipus --> <xsd:simpleType name="emailTipus">   <xsd:restriction base="xsd:string">     <xsd:pattern value="^([0-9,a-z,A-Z]+)([.,_]([0-9,a-z,A-Z]+))*[@]([0-9,a-z,A-Z]+)([.,_,-]([0-9,a-z,A-Z]+))*[.]([0-9,a-z,A-Z]){2}([0-9,a-z,A-Z])?$" />   </xsd:restriction> </xsd:simpleType> <!-- a szemely nemenek tarolasara letrehozott tipus --> <xsd:simpleType name="nemTipus">   <xsd:restriction base="xsd:string">     <xsd:enumeration value="férfi" />     <xsd:enumeration value="no" />   </xsd:restriction> </xsd:simpleType> <!-- a szemely adatainak tarolasara letrehozott komplex tipus, mivel elemeket tartalmaz --> <xsd:complexType name="tagTipus"> <xsd:sequence>    <xsd:element name="NEV" type="xsd:string"/>    <xsd:element name="SZEM_SZAM" type="szemelyiSzamTipus"/>    <xsd:element name="NEM" type="nemTipus"/>    <xsd:element name="EMAIL" type="emailTipus"/> </xsd:sequence> </xsd:complexType> <!-- a dokumentum elem deklaralasa -->   <xsd:element name="TAGLISTA">     <xsd:complexType>       <xsd:sequence>         <xsd:element name="TAG" type="tagTipus" minOccurs="0" maxOccurs="unbounded"/>               </xsd:sequence>     </xsd:complexType>   </xsd:element> </xsd:schema>
taglista.xml
<?xml version="1.0" encoding="ISO-8859-2"?> <TAGLISTA>   <TAG>     <NEV>Valaki Jancsi</NEV>     <SZEM_SZAM>SF 124578</SZEM_SZAM>     <NEM>férfi</NEM>     <EMAIL>valaki_jancsi@hotmail.com</EMAIL>   </TAG>   ... </TAGLISTA>
Rögtön az XML-séma definíció dokumentumeleme (schema) után definiáltuk a saját egyszerű típusainkat (szemelyiSzamTipus, emailTipus, nemTipus) és egy összetett típust (tagTípus, az összetett adattípusok létrehozását a későbbiekben fogjuk tárgyalni), mely az egyes tagok adatait fogja tárolni. Miután az összes szükséges típust definiáltuk nincs más hátra, mint a dokumentum elem definíciója. A dokumentum elemnek is definiálhattunk volna nevesített típust, de ezt szándékosan nem így tettem, hogy mindenki számára láthatóvá válljon a névtelen, illetve nevesített típusok közötti különbség.
Az egyes elemek előrdulása korlátozható a minimális (minOccurs) illetve maximális (maxOccurs) előfordulás megadásával. Amennyiben nem adunk meg minimális és maximális előfordulást, úgy az elemnek pontosan egyszer kell előfordulnia. Ha azt szeretnénk elérni, hogy egy elem előfordulása <0, végtelen> legyen akkor fenti példa alapján kell eljárni, vagyis
<xsd:element name="TAG" type="tagTipus" minOccurs="0" maxOccurs="unbounded"/>
Összetett elemtípusok deklarációja

Összetett típusúnak nevezzük azon elemeket, melyek gyermekelemeket, jellemzőket, vagy karekteres adatokat és gyermekelemeket is tartalmaznak egyidejűleg. Amennyiben összetett típusú elemeket szeretnénk használni, a következő lehetőségek közül választhatunk:

  • általános összetett típus (anyType) használata esetén az elem tartalmazhat bármilyen jellemzőt, elemet és karakteres adatot
    <xsd:element name="BARMITARTALOM" type="anyType" minOccurs="0" maxOccurs="unbounded"/>
  • saját összetett típus létrehozása akár névtelenül, akár nevesített módon (névtelen és nevesített típusok definícióját lásd feljebb)
Összetett típusokat hasonló módon hozhatunk létre, mint az egyszerű típusokat. Az egyes gyermekelemek a complexType elemen belül deklarált sequence, choice vagy all gyermekeiként adjuk meg, attól függően, hogy:
  • felsorolást szeretnénk kötött elemsorrenddel (sequence)
    <-- XML-sema definicio --> <?xml version="1.0" encoding="ISO-8859-2"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:complexType name="f1vilagbajnokTipus">   <xsd:sequence>     <xsd:element name="EV" type="xsd:gYear"/>     <xsd:element name="NEV" type="xsd:string"/>     <xsd:element name="NEMZETISEG" type="xsd:string"/>   </xsd:sequence> </xsd:complexType>   <xsd:element name="F1VILAGBAJNOKOK">     <xsd:complexType>       <xsd:sequence>         <xsd:element name="F1VILAGBAJNOK" type="f1vilagbajnokTipus" minOccurs="1" maxOccurs="unbounded" />       </xsd:sequence>     </xsd:complexType>   </xsd:element> </xsd:schema> <-- érvényes XML dokumentum --> <?xml version="1.0" encoding="ISO-8859-2"?> <F1VILAGBAJNOK>   <F1VILAGBAJONOK>     <EV>1959</EV>     <NEV>Jack Braham</NEV>     <NEMZETISEG>Ausztral</NEMZETISEG>   </F1VILAGBAJONOK> <-- figyeljunk az elemsorrendre, mivel EV,NEV,NEMZETISEG nem egyenlo NEV,EV,NEMZETISEG-el -->   <F1VILAGBAJONOK>     <NEV>Alberto Ascari</NEV>     <EV>1953</EV>     <NEMZETISEG>Olasz</NEMZETISEG>   </F1VILAGBAJONOK>   </F1VILAGBAJNOK>
  • választólistát szeretnénk(choice)
    <-- XML-sema definicio --> <?xml version="1.0" encoding="ISO-8859-2"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:complexType name="f1vilagbajnokTipus">   <xsd:choice>     <xsd:element name="EV" type="xsd:gYear"/>     <xsd:element name="NEV" type="xsd:string"/>     <xsd:element name="NEMZETISEG" type="xsd:string"/>   </xsd:choice> </xsd:complexType> <xsd:element name="F1VILAGBAJNOKOK">     <xsd:complexType>       <xsd:sequence>         <xsd:element name="F1VILAGBAJNOK" type="f1vilagbajnokTipus" minOccurs="1" maxOccurs="unbounded" />       </xsd:sequence>     </xsd:complexType>   </xsd:element> </xsd:schema> <-- érvényes XML dokumentum --> <?xml version="1.0" encoding="ISO-8859-2"?> <F1VILAGBAJNOK>   <F1VILAGBAJONOK>     <NEV>Alberto Ascari</NEV>   </F1VILAGBAJONOK>   <F1VILAGBAJONOK>     <EV>1953</EV>   </F1VILAGBAJONOK>   <F1VILAGBAJONOK>     <NEMZETISEG>Olasz</NEMZETISEG>   </F1VILAGBAJONOK>   </F1VILAGBAJNOK>
  • felsorolást szeretnénk kötetlen elemsorrenddel (all)
    <-- XML-sema definicio --> <?xml version="1.0" encoding="ISO-8859-2"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:complexType name="f1vilagbajnokTipus">   <xsd:all>     <xsd:element name="EV" type="xsd:gYear"/>     <xsd:element name="NEV" type="xsd:string"/>     <xsd:element name="NEMZETISEG" type="xsd:string"/>   </xsd:all> </xsd:complexType>   <xsd:element name="F1VILAGBAJNOKOK">     <xsd:complexType>       <xsd:sequence>         <xsd:element name="F1VILAGBAJNOK" type="f1vilagbajnokTipus" minOccurs="1" maxOccurs="unbounded" />       </xsd:sequence>     </xsd:complexType>   </xsd:element> </xsd:schema> <-- érvényes XML dokumentum --> <?xml version="1.0" encoding="ISO-8859-2"?> <F1VILAGBAJNOK>   <F1VILAGBAJONOK>     <EV>1959</EV>     <NEV>Jack Braham</NEV>     <NEMZETISEG>Ausztral</NEMZETISEG>   </F1VILAGBAJONOK> <-- mindket megadas helyes -->   <F1VILAGBAJONOK>     <NEV>Alberto Ascari</NEV>     <EV>1953</EV>     <NEMZETISEG>Olasz</NEMZETISEG>   </F1VILAGBAJONOK>   </F1VILAGBAJNOK>

Amint azt a DTDk használatánál már láttuk az XML-sémánál is lehetséges az egyes felsorolás típusok összeolvasztása, amennyiben megfelelünk néhány szabálynak:

  • all típusú felsorolásba nem olvasztható be sem sequence sem pedig choice típusú felsorolás
  • sequence és choice típus összeolvasztható
  • sem a sequence sem a choice felsorolásba nm olvasztható all típusú felsorolás
valasztas.xsd
<?xml version="1.0" encoding="ISO-8859-2"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:complexType name="emberTipus">   <xsd:sequence>     <xsd:element name="NEV" type="xsd:string"/>     <xsd:element name="SZULEV" type="xsd:gYear"/>     <xsd:element name="VEGZETTSEG" type="xsd:string"/>     <xsd:choice>       <xsd:element name="MUNKAHELY" type="xsd:string"/>       <xsd:element name="ISKOLA" type="xsd:string"/>     </xsd:choice>     <xsd:element name="GYERMEK" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>   </xsd:sequence> </xsd:complexType>   <xsd:element name="EMBEREK">     <xsd:complexType>       <xsd:sequence>         <xsd:element name="EMBER" type="emberTipus" minOccurs="1" maxOccurs="unbounded" />       </xsd:sequence>     </xsd:complexType>   </xsd:element> </xsd:schema>
valasztas.xml
<?xml version="1.0" encoding="ISO-8859-2"?> <EMBEREK>   <EMBER>     <NEV>Gulyás Péter</NEV>     <SZULEV>1970</SZULEV>     <VEGZETTSEG>Technikai egyetem</VEGZETTSEG>     <MUNKAHELY>Paksi atomeromu</MUNKAHELY>     <GYERMEK>Gujás Veronika</GYERMEK>     <GYERMEK>Gujás Zoltán</GYERMEK>   </EMBER>   <EMBER>     <NEV>Hajmási Péter</NEV>     <SZULEV>1981</SZULEV>     <VEGZETTSEG>Ipari Középiskola</VEGZETTSEG>     <ISKOLA>ELTE</ISKOLA>   </EMBER> </EMBEREK>
A példaprogram gondolom sokak számára ismerős a DTDkkel foglalkozó cikkből. Az EMBEREK dokumentumelem 1 vagy több EMBER típusú elemet tartalmazhat. Minden EMBER típusú elem tartalmaz egy nevet (NEV), egy születési évet (SZULEV), egy végzettséget (VEGZETTSEG), egy munkahelyet (MUNKAHELY) vagy egy iskolát (ISKOLA) és nulla vagy több gyermeket (GYERMEK).

Üres elem létrehozásánál hasonlóan járunk el, mint egy összetett típusú elem deklarálásánál, azzal a különbséggel, hogy nem deklarálunk gyermekelemeket, tehát a complexType elemnek nem lesznek element típusú gyermekelemei.

<xsd:element name="BR">   <xsd:complexType>   <xsd:complexType> </xsd:element>   
Vegyes elemet szintén összetett típusúnak kell deklarálni, mivel tartalmaz gyermekelemet és szöveges tartalmat is egyben. A complexType elem mixed jellemzőjének igazra állításával jelezzük, hogy vegyes elemet szeretnénk deklarálni.
<xsd:element name="COMMENT">   <xsd:complexType mixed="true">     <xsd:sequence minOccurs="0" maxOccurs="unbounded">       <xsd:element name="BR">         <xsd:complexType>         </xsd:complexType>       </xsd:element>     </xsd:sequence>   </xsd:complexType> </xsd:element> <!-- érvényes dokumentum részlet --> <COMMENT>A COMMENT elem tartalmazhat nulla sortörés elemet</COMMENT> <COMMENT>A COMMENT elem tartalmazhat egy <BR /> sortörés elemet</COMMENT> <COMMENT>A COMMENT elem tartalmazhat nulla, egy <BR></BR> vagy akárhány <BR /> sortörés <BR /> <BR /> elemet</COMMENT>
Téhát a példánkban létrehozunk egy COMMENT elemet vegyes tartalommal, amelyet a mixed="true" szimbolizál. Ezután a COMMENT elemen belül létrehozunk egy BR nevű üres elemet, melynek előfordulása 0 vagy végtelen.
Jellemzők deklarálása

Ahhoz, hogy egy elem tartalmazhasson jellemzőket összetett típusúnak kell lennie. Az egyes jellemzőket a complexType gyermekelemeiként deklaráljuk. Az egyes jellemzők csakis kizárólag egyszerű típusúak lehetnek, tehát vagy az alaptípusok egyikét használjuk, vagy származtatunk egy új típust. A származtatás és létrehozás nagyban hasonlít az egyszerű típusú elemek létrehozásához.

<!-- XML-séma definíció részlet --> <xsd:element name="BEKEZDES">   <xsd:complexType>     <xsd:attribute name="ALIGN" type="xsd:string" default="left" />   </xsd:complexType> </xsd:element> <!-- XML dokumentum részlet --> <BEKEZDES/>Valami itt nem tetszik <BEKEZDES ALIGN="center"></BEKEZDES>mintha lenne itt meg valaki
Az egyes jellemző deklarációk a következő jellemzőket támogatják:
  • default - alapérték, amelyet felvesz a jellemző akkor, ha nem adunk meg neki értéket
  • fixed - értékéül megadhatjuk azt az értéket, amelyet mindenképpen fel kell venni a jellemzőnek, tehát ha nem adunk meg értéket, akkor a fixedben megadott értéket veszi fel a jellemző, viszont, ha megadunk értéket akkor csakis kizárólag a fixedben megadott értéket adhatjuk.
  • use - értékéül megadhatjuk
    • optional - a jellemző elhagyható, ami egyben az alapérték is
    • prohibited - a jellemző le van tiltva, olyan mintha nem is deklaráltuk volna
    • required - a jellemző használata kötelező

attributumok.xsd

<?xml version="1.0" encoding="ISO-8859-2"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <!-- ember nevét definialó egyszerű típus létrehozása --> <xsd:simpleType name="nevTipus">   <xsd:restriction base="xsd:string">     <xsd:pattern value="[A-Z,a-z,\s]+" />   </xsd:restriction> </xsd:simpleType> <!-- családi állapotot definialó egyszerű típus létrehozása --> <xsd:simpleType name="csaladiAllapotTipus">   <xsd:restriction base="xsd:string">     <xsd:enumeration value="nős" />     <xsd:enumeration value="férjezett" />     <xsd:enumeration value="szabad" />   </xsd:restriction> </xsd:simpleType> <!-- nemet definiáló egyszerű típus létrehozása --> <xsd:simpleType name="nemTipus">   <xsd:restriction base="xsd:string">     <xsd:enumeration value="nő" />     <xsd:enumeration value="férfi" />   </xsd:restriction> </xsd:simpleType> <!-- embert definiáló összetett típus létrehozása, amely tartalmazza a jellemzőket --> <xsd:complexType mixed="true" name="emberTipus">   <xsd:simpleContent>     <xsd:extension base="nevTipus">       <xsd:attribute name="csaladi_allapot" type="csaladiAllapotTipus" default="szabad" />       <xsd:attribute name="nem"             type="nemTipus"            use="required" />     </xsd:extension>   </xsd:simpleContent> </xsd:complexType> <!-- ember típusú elemeket tartalmazó dokumentumelem definiálása -->   <xsd:element name="EMBEREK">     <xsd:complexType>       <xsd:sequence>         <xsd:element name="EMBER" type="emberTipus" minOccurs="1" maxOccurs="unbounded" />       </xsd:sequence>     </xsd:complexType>   </xsd:element>

attributumok.xml

<?xml version="1.0" encoding="ISO-8859-2"?> <EMBEREK>   <!-- mivel a csaladi_allapot alap erteke is szabad feleslegesen adtuk meg, de nem okoztunk hibat -->   <EMBER csaladi_allapot="szabad" nem="férfi">Schwartz Attila</EMBER>   <EMBER csaladi_allapot="férjezett" nem="nő">Varga Eszter</EMBER>   <!-- vegeredménye ugyanaz mint a első emberé, mivel alapban "szabad" a csaladi_allapot -->   <EMBER nem="férfi">Szabad Tibor</EMBER> </EMBEREK>
Magából a definícióból egyetlen részt szeretnék kiemelni, mivel a fennmaradó részek megértésének nem szabadna gondot okozni. Az elmített rész az emberTípus defíciója. A probláma okozója az, hogy egy egyszerű típusú elemhez szeretnénk jellemzőt rendelni és egyben az elem tartalmát is bekorlátozni. A megoldás a simpleContent elem használatában rejlik, amely segítségével egy egyszerű típusból (nevTipus) összetett típust származtatunk, amely már jellemzőket is fog tartalmazni. Az extension elem végzi a származtattás, mely base jellemzőjének adjuk értékül az egyszerű típust, amely az elem (EMBER) karakteres adatainak végleges típusa lesz, és amelyet ki szeretnénk egészíteni (terjeszteni) jellemzőkkel is. Végül a jellemzőket a simpleContent elem gyermekelemeiként adjuk meg a már fentebb taglalt jellemződefiníció alapján.

Az ezen cikkben bemutatott lehetőségek csak töredékét jelentik az XML-séma által nyújtott lehetőségeknek, mivel a teljes bemutatás nagyon idő és helyigényes lenne. Ezen cikkel fel szerettem volna kelteni az olvasó érdeklődését és egy kis alapot szerettem volna biztosítani az esetleges tanulás folytatásához. Az érdeklődők a World Wide Web Consortium oldalán megtalálhatják a teljes XML-séma definíciót ( XML Schema Part 0: Primer, XML Schema Part 1: Structures, XML Schema Part 1: Structures ), rengeteg példával kiegészítve. Ajánlanám az olvasóknak az egyes példák megértése céljából a mintapéldákat kicsit megváltoztatni, hogy így is egy kis tapasztalatot szerezzen az XML-sémák készítésében, mivel a cikksorozat későbbi részeiben támaszkodni fogunk az idáig megszerzett tudásanyagra.

A cikksorozat ezen részével lezártunk egy témakört, mégpedig az XML dokumentumok létrehozását. A következő részekben már csakis az XML dokumentumok megjelenítésével fogunk foglalkozni, amely talán már az első olvasás után is emberközelibbnek fog tűnni. A következő részben megismerkedünk az XML dokumentumok lépcsős stíluslapokkal (közismertebb nevén CSS) való megjelenítésével.

A cikkben közölt forráskódok összetömörítve innen tölthetők le.