Kihagyás

12. gyakorlat

XML technológiák

Standard Generalized Markup Language (SGML)

Az SGML egy általános jelölő nyelv, amelyet ISO szabvány definiál. A célja, hogy egy adott szintaktikának megfelelő dokumentumot könnyen lehessen kezelni. Az SGML konkrét alkalmazása a HTML, de az XML is az SGML részhalmaza. Az SGML bonyolult, ezért széles körben nem is terjedt el, ezért ezzel külön nem is foglalkozunk, csak az XML-lel.

Extensible Markup Language (XML)

Az 1. gyakorlaton már megismerkedtünk az XML-lel, és a félév során már a gyakorlati alkalmazását is láttuk, mert a maven projekt fájl (pom.xml), illetve a webes résznél a konfigurációs fájl (web.xml) is XML volt. Azonban ezek inkább a gyakorlatban történő alkalmazhatóságra példák, és nem arra, hogy magát az XML-t hogyan kell felépíteni, mit lehet és mit nem lehet használni, illetve hogyan kell validálni azt. A következőkben az XML technológiákkal fogunk megismerkedni, amihez az alábbi példát fogjuk használni.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?xml version="1.0" encoding="ISO-8859-1"?>
<jelentkezes idoszak="2019/2020II" egyetem="SZTE">
  <hallgato id="KOJEAE.SZE">
    <hnev>Kovács János</hnev>
    <szuletesnap>2000-01-08</szuletesnap>
    <szak evf="2">programtervezo informatikus</szak>
  </hallgato>
  <kurzusok>
    <kurzus id="IAB8532">
      <nev>Alkalmazásfejlesztés I.</nev>
      <kredit>2</kredit>
      <hely>I223</hely>
      <idopont>Szerda 15:00-16:00</idopont>
      <tanar>Dr. Siket István</tanar>
    </kurzus>
    <kurzus id="XEL24234" jovahagyas="igen">
      <nev>E-Learning</nev>
      <kredit>3</kredit>
      <hely>B107</hely>
      <idopont>Szerda 12:00-14:00</idopont>
      <tanar>Dr. Kovács Géza</tanar>
    </kurzus>
    <kurzus id="LL2458I" nyelv="német">
      <nev>Német középfok</nev>
      <kredit>0</kredit>
      <hely>VI. lektorátus</hely>
      <tanar>Dr. Szabó Gabriella</tanar>
      <oratarto>Nagy Annamária</oratarto>
    </kurzus>
  </kurzusok>
</jelentkezes>

Document Type Definition (DTD)

A DTD szabályok halmaza, amely SGML típusú nyelvekhez határoz meg dokumentumtípust. A DTD meghatározza, hogy

  • milyen elemek lehetnek a dokumentumban,
  • az elemek hogyan kapcsolódhatnak egymáshoz,
  • milyen tartalmuk lehet,
  • milyen tulajdonságuk lehet.

Fontos, hogy a DTD-ben minden olyan elemet definiálni kell, ami az XML-ben előfordul!

A DTD-t kétféleképpen lehet megadni:

  • Belső, amikor a DTD ugyanabban a fájlban van, mint amire vonatkozik.
  • Külső, amikor a DTD egy külön fájlban van, és csak egy hivatkozást tartalmaz a dokumentum a DTD-re.

A DTD felépítésénél definiáljuk az XML fa szerkezetét, amihez első lépésben a fa gyökerét adjuk meg. A jelentkezés xml esetében a fa gyökere a jelentkezés, amit a következő módon definiálunk.

1
2
3
4
<!DOCTYPE jelentkezes
[
 ...
]>

Egy konkrét XML-hez nagyon sokféle validációs szabályt definiálhatunk, mert nem tudhatjuk, hogy mi kötelező és mi nem, melyik elemből mennyi a minimum és maximum, melyik elemre milyen megkötések vannak, stb. Mi most egyet fogunk megadni, ami logikusan következik az XML-ből, illetve bemutatja a DTD lehetőségeit is.

A jelentkezes elemnek van egy attribútuma (id) és két gyereke, a hallgato és a kurzusok. Ezt az ELEMENT és ATTLIST segítségével adhatjuk meg.

1
2
3
4
5
<!DOCTYPE jelentkezes
[
  <!ELEMENT jelentkezes (hallgato, kurzusok)>
  <!ATTLIST jelentkezes idoszak CDATA #REQUIRED>
]>

Az idoszak típusát is megadtuk, ez tetszőleges szöveg (CDATA) lehet, (amit a feldolgozó nem is fogja feldolgozni), illetve definiáltuk, hogy kötelező megadni (#REQUIRED).

Attribútum

Az attribútum fontosabb lehetséges típusa:

  • CDATA - szöveges adat
  • ID - egyedi azonosító, azaz egy azonosító nem fordulhat elő kétszer (pl. a kurzus id-ja)
  • Felsorolás, amikor definiáljuk, hogy pontosan milyen értékeket vehet fel (pl. a kurzus esetében a jovahagyas)
  • ENTITY és ENTITIES - külső hivatkozás megadása (később lesz rá példa)
  • IDREF és IDREFS - egy vagy több másik elemre történő hivatkozás
  • NMTOKEN és NMTOKENS - Valid XML név

Az attribútum követelmények a következők lehetnek:

  • #REQUIRED - kötelező megadni, például a jelentkezési időszakot vagy a hallgatónak az egyedi azonosítóját

    1
    2
    <!ATTLIST jelentkezes idoszak CDATA #REQUIRED>
    <!ATTLIST kurzus      id      ID    #REQUIRED>
    
  • #FIXED - kötelező megadni, de csak egy fix értéket vehet fel, ami példa lehet, hogy az egyetem csak az SZTE lehet

    1
    <!ATTLIST jelentkezes egyetem CDATA #FIXED "SZTE">
    
  • #IMPLIED - opcionális, azaz megadhatjuk, de nem kötelező, például a nyelv a kurzusoknál

    1
    <!ATTLIST kurzus      nyelv   CDATA #IMPLIED>
    
  • felsorolás - megadhatjuk, hogy milyen értékeket vehet fel, mint például a jóváhagyásos kurzusoknál, de megadhatunk alapértelmezett értéket is, hogy ne kelljen minden nem jóváhagyásoshoz kiírni a "nem"-et

    1
    <!ATTLIST kurzus      jovahagyas   (igen | nem) "nem">
    

Elem

Az elemek esetében megadhatjuk, hogy mi legyen a tartalmuk:

  • EMPTY - üres, az elemnek nem lehet tartalma (pl. HTML esetében a <br />)
  • ANY- tetszőleges tartalmat megadhatunk, amit az XML megenged
  • #PCDATA - parsed data, azaz olyan adattartalom, amit az XML-parser feldolgoz
  • Gyerek elemek - további XML elemek
  • Ezek kombinációja, amikor többféle tartalmat is megadhatunk, pl. a hallgató esetében

    1
    <!ELEMENT hallgato (hnev, szuletesnap, szak)>
    

A gyerek elemek esetében azt is megadhatjuk, hogy hányszor forduljanak elő:

  • Szekvencia: ha vesszővel elválasztva adjuk mega, akkor minden elemnek léteznie kell

    1
    <!ELEMENT hallgato (hnev, szuletesnap, szak)>
    
  • Ha több elem közül kell választani egyet, akkor a | jellel adhatjuk meg, pl. tanar vagy oratarto

    1
    <!ELEMENT kurzus (... (tanar|oratarto) )>
    
  • Ismétlődés operátorok

    • Nincs - pontosan egyszer kell előfordulnia
    • ? - egyszer vagy egyszer sem, pl. lehet, hogy még nem ismert a kurzus időpontja
    • + - legalább egyszer szerepelnie kell, pl. a hallgatónak legalább egy szakja van
    • * - akárhányszor szerepelhet (akár el is lehet hagyni), pl. tetszőleges kurzust felvehet

      1
      2
      3
      <!ELEMENT hallgato (hnev, szuletesnap, szak+)>
      <!ELEMENT kurzusok (kurzus*)>
      <!ELEMENT kurzus (nev, kredit, hely, idopont?, (tanar|oratarto)+ )>
      

Teljes példa

Ezen építőelemek felhasználva a jelentkezes.xml-hez tartozó egy lehetséges DTD a következő:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!DOCTYPE jelentkezes
[
    <!ELEMENT jelentkezes (hallgato, kurzusok)>
    <!ATTLIST jelentkezes 
        idoszak CDATA #REQUIRED
        egyetem CDATA #FIXED "SZTE"
    >

    <!ELEMENT hallgato (hnev, szuletesnap, szak+)>
    <!ATTLIST hallgato id ID #REQUIRED>
    <!ELEMENT hnev (#PCDATA)>
    <!ELEMENT szuletesnap (#PCDATA)>
    <!ELEMENT szak (#PCDATA)>
    <!ATTLIST szak evf CDATA #REQUIRED>

    <!ELEMENT kurzusok (kurzus*)>
    <!ELEMENT kurzus (nev, kredit, hely, idopont?, (tanar|oratarto)+ )>
    <!ATTLIST kurzus
        id    ID    #REQUIRED
        nyelv CDATA #IMPLIED
        jovahagyas (igen | nem) "nem"
    >

    <!ELEMENT nev (#PCDATA)>
    <!ELEMENT kredit (#PCDATA)>
    <!ELEMENT hely (#PCDATA)>
    <!ELEMENT idopont (#PCDATA)>
    <!ELEMENT tanar (#PCDATA)>
  <!ELEMENT oratarto (#PCDATA)>

]>

Hivatkozások

Külső hivatkozások

Az első külső hivatkozás maga a DTD lehet. Megtehetjük, hogy a fenti DTD-t bemásoljuk az XML elejére, de ez nem célszerű, mert így minden XML tartalmazza a DTD-t, ami nagyobb méretű lesz, a DTD redundánsan szerepel az összes XML-ben, illetve, ha módosítjuk a DTD-t, akkor minden XML-ben ki kell cserélni. Ezért célszerű külső hivatkozásként megadni a DTD-t, és ilyenkor az XML elejére csak a hivatkozást kell beszúrni.

1
<!DOCTYPE jelentkezes SYSTEM "jelentkezes.dtd">

De nem csak a DTD-re lehet külső hivatkozást definiálni, hanem ,,bármire''. Például a kurzusok vagy a kurzus esetében is meg lehet adni, hogy valami külső fájlra vagy egy web címre hivatkozzon.

1
2
<!ENTITY kurzusok    SYSTEM "https://www...">
<!ENTITY kurzus      SYSTEM "file://C:...">
Belső hivatkozások

A DTD lehetőséget biztosít változó definíciókra is, és ezekre a változókra később hivatkozhatunk is. Például ha az SZTE-t nem akarjuk mindenhova kiírni, helyette felveszünk egy változót, annak értékül adjuk, és ha valamiért változik az egyetem neve, akkor csak egy helyen kell módosítani. A korábbi példa kapcsolódó része (valid XML-lé alakítva):

1
2
3
4
5
6
7
8
<!DOCTYPE jelentkezes
[
  <!ENTITY EGYETEMNEVE "SZTE">
  <!ELEMENT jelentkezes EMPTY>
  <!ATTLIST jelentkezes egyetem CDATA #FIXED "SZTE">
]>

<jelentkezes egyetem="&EGYETEMNEVE;" />
Hivatkozások használatának veszélyei

Használjuk vagy ne használjuk a ne használjuk a hivatkozásokat? Láthatjuk, hogy számos előnyük van:

  • csak egy helyen szerepel a DTD,
  • csak egy helyen adok értéket a változónak, és aztán használom.

Szóval akkor használjuk, mi baj történhet?

DTD változók

Tegyük fel, hogy van egy alkalmazásunk, ami egy webszerveren fut, és valami inputot várunk XML formátumban. Elővigyázatosak vagyunk, és hogy védjük a szervert (tárhely, memória, processzor kapacitás), lekorlátozzuk a feltöltendő fájlok méretét. Ekkor megnyugodhatunk, mi baj történhet, ,,mindenre'' gondolunk.

Vagy mégsem? Mi van akkor, ha az egyik ,,barátunk'' meglep minket a következő XML-lel?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<!DOCTYPE pelda [
  <!ENTITY a "1234567890">
  <!ENTITY b "&a;&a;&a;&a;&a;&a;&a;&a;">
  <!ENTITY c "&b;&b;&b;&b;&b;&b;&b;&b;">
  <!ENTITY d "&c;&c;&c;&c;&c;&c;&c;&c;">

  <!ENTITY l "&k;&k;&k;&k;&k;&k;&k;&k;">
  <!ENTITY m "&l;&l;&l;&l;&l;&l;&l;&l;">
]>
<pelda>&m;</pelda>

Mi fog történni ekkor? Az XML feldolgozó elvégzi a dolgát, és előállítja az XML-t, amihez ki kell számolnia m-et, amihez előbb l-re is szüksége van, ... De mekkora lesz m?

  • a 10 bájtos
  • b 8-szor tartalmazza a-t, azaz 10 * 8 = 80 bájt
  • c 8-szor tartalmazza b-t, azaz 10 * 8 * 8 = 10 * 82 = 640 bájt
  • d 8-szor tartalmazza c-t, azaz 10 * 83 = 5 KB
  • e 8-szor tartalmazza d-t, azaz 10 * 84 = 40 KB
  • ...
  • m 8-sor tartalmazza d-t, azaz 10 * 812 = 640 GB!!!

Azaz a fenti ,,ártatlannak tűnő'' XML feldolgozásához 640GB memóriára van szükség.

XML External Entity (XXE) sebezhetőség

A külső hivatkozások hasznosak, de azokat is fenntartásokkal kell kezelni. Például, ha valami külső hivatkozás tartalmát a felhasználó láthatja, akkor esetleg olyan információhoz is hozzájuthat, amihez nincs jogosultsága. De ki lenne ilyen amatőr, hogy ezt megengedi, és vajon mihez férhet hozzá? Nos, egy valós példa erre, hogy korábban a google toolbart testre lehetett szabni XML segítségével. Ez egy hasznos funkció volt, csak nem (vagy nem megfelelően) validálták az XML-t, így ha valaki a szerveren található /etc/passwd vagy az /etc/hosts fájlok tartalmával akarta kiegészíteni a toolbarját, akkor megtehette 👏🤦‍♂️

XML Schema Definition (XSD)

Annak ellenére, hogy a DTD-vel is definiálthatjuk az XML formátumát, van néhány hátránya, amiért inkább az XSD-t érdemes használni. Anélkül, hogy ismernénk az XSD-t, a DTD-vel kapcsolatban lehetett néhol hiányérzetünk, ezért most előre összefoglaljuk a fontosabb különbségeket, illetve az XSD előnyeit a DTD-vel szemben:

  • Az XSD XML alapú, míg a DTD nem, azaz a DTD-hez meg kell tanulni egy újabb szintaxist (ami azért nem annyira bonyolult 😄 ).
  • Az XSD sokféle típust definiál (szám, dátum, ...), míg a DTD alapból ezt nem támogatja.
    • Ezért nem tudtunk a születési évnek dátum típus megkövetelni, vagy a kredit számnak nemnegatív egész értéket.
  • Az XSD-vel definiálhatjuk a gyerek elemek számát és sorrendjét, míg a DTD ezt nem támogatja.
  • Az XML-ben használhatunk névtereket, és az XSD támogatja ezt.
  • Azért a DTD mellett szól például, hogy definiálhatunk ENTITY-t, amit az XSD nem támogat.

XSD Bevezető

Az XSD XML alapon definiálja, hogy az adott XML hogyan nézhet ki, azaz

  • milyen elemek és attribútumok fordulhatnak elő,
  • mennyi gyerek elem és milyen sorrendben fordulhat elő,
  • az elemek és attribútumok típusait,
  • és az elemek és attribútumok fix értékeit.

Az XSD megadása egy XML fájllal történik, ahol az XSD nyelvtanban definiált elemeket használhatjuk. A gyökérben megadjuk, hogy az XSD névteret használjuk, és ezen elemeket az xs prefixszel fogjuk használni.

1
2
3
4
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  ...
</xs:schema>

Az XSD-ben megtalálhatóak azok az alaptípusok, amelyek a legtöbb nyelvben léteznek, például:

  • szöveg: string
  • szám: integer, long, short, byte, ..., float, double, ...
  • dátum: date, time, ...
  • egyéb: boolean

Element

Egy XML elemet az XSD-ben az element segítségével adhatunk meg, ahol meg kell adni a nevét és azt, hogy mi lehet a tartalma. Az element lehet egyszerű, amikor egy XSD a típusa, de lehet összetett is, amikor mi írjuk le, hogy mit tartalmazhat.

Például a kredit vagy a tanár esetében, amikor egyszerű elemnek tekintjük:

1
2
<xs:element name="kredit" type="xs:integer">
<xs:element name="tanar" type="xs:string"/>

Komplex elemet complexType segítségével definiálhatunk, ahol meg kell adnunk azt is, hogy

  • milyen elemeket tartalmazzon,
  • melyikből mennyit tartalmazzon,
  • és hogy számít-e a sorrendjük van sem.
Összetett elem

Ha olyan összetett elemet szeretnénk definiálni, ahol az összes gyereknek elő kell fordulnia, de a sorrend tetszőleges lehet, akkor az all-t kell használni. Például a kurzusnak lehet neve, kreditje, helye, ... (a tanár vagy óratartó választást most még nem vesszük figyelembe).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<xs:element name="kurzus">
  <xs:complexType>
    <xs:all>
      <xs:element name="nev" type="xs:string"/>
      <xs:element name="kredit" type="xs:integer">
      <xs:element name="hely" type="xs:string"/>
      <xs:element name="idopont" type="xs:string"/>
      <xs:element name="tanar" type="xs:string"/>
    </xs:all>
  </xs:complexType>
</xs:element>

Ha az elemek sorrendje is fontos, akkor a sequence-t kell használni:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<xs:element name="kurzus">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="nev" type="xs:string"/>
      <xs:element name="kredit" type="xs:integer">
      <xs:element name="hely" type="xs:string"/>
      <xs:element name="idopont" type="xs:string"/>
      <xs:element name="tanar" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

Azt is megtehetjük, hogy az elemek közül választunk (choice), például, ha a kurzusnak tanára vagy óratartója van, és ilyenkor vagy az egyiket, vagy a másikat kell megadni:

1
2
3
4
5
6
7
8
<xs:element name="kurzus">
  <xs:complexType>
    <xs:choice>
      <xs:element name="tanar" type="xs:string"/>
      <xs:element name="oratarto" type="xs:string"/>
    </xs:choice>
  </xs:complexType>
</xs:element>
Számosság megadása

Lehetőségünk van azt is megadni, hogy egy elem hányszor forduljon, illetve összesen hány elem lehet. Ezekre a minOccurs és maxOccurs attribútumokat használhatjuk.

Például ha a kurzus esetében az időpont opcionális, azaz nem kötelező, akkor a minOccurs értékét 0-ra kell állítani, és így elhagyható lesz. Továbbá ha legfeljebb 5 tanára lehet (most tekintsünk el a tanár vagy oktató megközelítéstől) a kurzusnak, akkor azt a következő módon lehet megadni:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<xs:element name="kurzus">
  <xs:complexType>
    <xs:all>
      <xs:element name="nev" type="xs:string"/>
      <xs:element name="kredit" type="xs:integer">
      <xs:element name="hely" type="xs:string"/>
      <xs:element name="idopont" type="xs:string" minOccurs="0"/>
      <xs:element name="tanar" type="xs:string" maxOccurs="5"/>
    </xs:all>
  </xs:complexType>
</xs:element>

A minOccurs értéke 0 vagy 1 lehet, a maxOccurs tetszőleges egész. Mindkettőnek az alapértelmezett értéke 1, azaz minden gyerek elemnek egyszer kell szerepelnie, ha ezt nem specifikáljuk másképp.

Referencia másik elemre

Mivel az XML-ben elég mély egymásba ágyazási hierarchia alakulhat ki, azért az XSD is elég bonyolult és mély lehet, ezért célszerű bizonyos részeket kiszervezni, és azokra csak hivatkozásokat megadni. Ilyen lehet, hogy a jelentkezes-t két nagyobb részre bontjuk, a hallgato-ra és a kurzusok-ra.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<xs:element name="jelentkezes">
    <xs:complexType>
    <xs:sequence>
      <xs:element ref="hallgato"/>
      <xs:element ref="kurzusok"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

<xs:element name="hallgato">
    ...
</xs:element>

<xs:element name="kurzusok">
    ...
</xs:element>

Attribútum

Az attribútumokat az attribute segítségével adhatjuk meg, ahol meg kell adni az attribútum nevét, a típusát, és hogy kötelező (required) vagy opcionális (optional), és esetleg van-e alapértelmezett értéke. Néhány példa az attribútumokra, ahol az evf vagy az id megadása kötelező, a nyelv opcionális, mint ahogy a jovahagyas is, de ott még alapértelemezett értéket is megadunk.

1
2
3
4
<xs:attribute name="evf" type="xs:integer" use="required"/>
<xs:attribute name="id" type="idTipus" use="required"/>
<xs:attribute name="jovahagyas" type="igenNemTipus" use="optional" default="nem"/>
<xs:attribute name="nyelv" type="xs:string" use="optional"/>

Ha egy elemnek van attribútuma, akkor az már nem lehet egyszerű elem, hiába nincs további gyereke. Például a szak esetében csak a szakot kell megadni szöveggel, de van egy evf attribútuma is.

1
2
3
4
5
6
7
8
9
<xs:element name="szak">
  <xs:complexType>
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute name="evf" type="xs:integer" use="required"/>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
</xs:element>

Vagy például a kurzus attribútumainak megadása a következő lehet:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<xs:element name="kurzus">
  <xs:complexType>
    <xs:all>
      <xs:element name="nev" type="xs:string"/>
      <xs:element name="kredit" type="xs:integer">
      <xs:element name="hely" type="xs:string"/>
      <xs:element name="idopont" type="xs:string" minOccurs="0"/>
      <xs:element name="tanar" type="xs:string" maxOccurs="5"/>
    </xs:all>
    <xs:attribute name="id" type="idTipus" use="required"/>
    <xs:attribute name="jovahagyas" type="igenNemTipus" use="optional" default="nem"/>
    <xs:attribute name="nyelv" type="xs:string" use="optional"/>
  </xs:complexType>
</xs:element>
Saját típus, megszorítások

Eddig csak a beépített típusokat használtuk, azonban lehetőségünk van megszorításokat is alkalmazni a típusokra, illetve új típusokat is definiálhatunk, amit később felhasználhatunk. Egy logikus megszorítás, hogy a kredit értéknek legyen minimum és maximum értéke. így a korábbi

1
<xs:element name="kredit" type="xs:integer">

helyett megadjuk, hogy továbbra is egész szám, de a megszorításokat is definiáljuk:

1
2
3
4
5
6
7
8
<xs:element name="kredit">
  <xs:simpleType>
    <xs:restriction base="xs:integer">
      <xs:minInclusive value="0"/>
      <xs:maxInclusive value="30"/>
    </xs:restriction>
  </xs:simpleType>
</xs:element>

Saját típus definiálásánál meg kell adni a típus nevét, valamint azt, hogy mit reprezentáljon. Például a hallgatók és a kurzusok azonosítóinak olyan string azonosítókat fogadunk el, amelyek legalább 5 és legfeljebb 10 hosszúak.

1
2
3
4
5
6
<xs:simpleType name="idTipus">
  <xs:restriction base="xs:string">
    <xs:minLength value="5"/>
    <xs:maxLength value="10"/>
  </xs:restriction>
</xs:simpleType>

Ha a jóváhagyáshoz szeretnénk egy típust definiálni, ami csak igen vagy nem lehet, akkor az string típus lesz, és megadott értékeket vehet fel.

1
2
3
4
5
6
<xs:simpleType name="igenNemTipus">
  <xs:restriction base="xs:string">
    <xs:enumeration value="igen"/>
    <xs:enumeration value="nem"/>
  </xs:restriction>
</xs:simpleType>

De lehetőség van minta alapján is megszorítást definiálni. Ilyen lehet például az, hogy melyik időszakra vonatkozik, ahol a mintának az eleje az évszám/évszám, majd ezt követi egy vagy két I. Ez a minta nem fogja ellenőrizni, hogy az évszám jó-e, de legalább ilyen formátumban kapjuk meg.

1
2
3
4
5
<xs:simpleType name="idoszakTipus">
  <xs:restriction base="xs:string">
    <xs:pattern value="\d{4}/\d{4}I(I)?"/>
  </xs:restriction>
</xs:simpleType>

Teljes XML

Ezen építőelemek felhasználásával egy lehetséges XSD a jelentkezes.xml példához a következő:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">

<!-- Bevezetünk néhány típust amit a példában fogunk használni -->

  <xs:simpleType name="idoszakTipus">
    <xs:restriction base="xs:string">
      <xs:pattern value="\d{4}/\d{4}I(I)?"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="egyetemTipus">
    <xs:restriction base="xs:string">
      <xs:pattern value="SZTE"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="idTipus">
    <xs:restriction base="xs:string">
      <xs:minLength value="5"/>
      <xs:maxLength value="10"/>
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="igenNemTipus">
    <xs:restriction base="xs:string">
      <xs:enumeration value="igen"/>
      <xs:enumeration value="nem"/>
    </xs:restriction>
  </xs:simpleType>


<!-- Itt kezdjük el a szabályokat megadni az elementekre -->

  <xs:element name="jelentkezes">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="hallgato"/>
        <xs:element ref="kurzusok"/>
      </xs:sequence>
      <xs:attribute name="idoszak" type="idoszakTipus" use="required"/>
      <xs:attribute name="egyetem" type="egyetemTipus" use="required"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="hallgato">
    <xs:complexType>
      <xs:all> <!-- nem fontos az elemek sorrendje -->
        <xs:element name="hnev" type="xs:string"/>
        <xs:element name="szuletesnap" type="xs:date"/>
        <xs:element name="szak">
          <xs:complexType>
            <xs:simpleContent>
              <xs:extension base="xs:string">
                <xs:attribute name="evf" type="xs:integer" use="required"/>
              </xs:extension>
            </xs:simpleContent>
          </xs:complexType>
        </xs:element>
      </xs:all>
      <xs:attribute name="id" type="idTipus" use="required"/>
    </xs:complexType>
  </xs:element>

  <xs:element name="kurzusok">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="kurzus" maxOccurs="unbounded">
          <xs:complexType>
            <xs:all>
              <xs:element name="nev" type="xs:string"/>
              <xs:element name="kredit">
                <xs:simpleType>
                  <xs:restriction base="xs:integer">
                    <xs:minInclusive value="0"/>
                    <xs:maxInclusive value="30"/>
                  </xs:restriction>
                </xs:simpleType>
              </xs:element>
              <xs:element name="hely" type="xs:string"/>
              <xs:element name="idopont" type="xs:string" minOccurs="0"/>
              <xs:element name="tanar" type="xs:string" minOccurs="0"/>
              <xs:element name="oratarto" type="xs:string" minOccurs="0"/>
            </xs:all>
            <xs:attribute name="id" type="idTipus" use="required"/>
            <xs:attribute name="jovahagyas" type="igenNemTipus"
                          use="optional" default="nem"/>
            <xs:attribute name="nyelv" type="xs:string" use="optional"/>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

</xs:schema>
XML gyökere

A fenti XSD esetében egyértelműnek tűnik, hogy a jelentkezes-t várjuk el az XML gyökerének, de ez nem így van, mert egy olyan XML is valid, aminek a hallgató a gyökere, és csak azt a részt valósítja meg.

1
2
3
4
5
6
7
<?xml version="1.0" encoding="ISO-8859-1"?>

<hallgato id="KOJEAE.SZE">
    <hnev>Kovács János</hnev>
    <szuletesnap>2000-01-08</szuletesnap>
    <szak evf="2">programtervezo informatikus</szak>
</hallgato>

Hasznos linkek


Utolsó frissítés: 2024-03-19 07:21:59