Praktikum: XML failide valideerimine (XSD, DTD) ning XML stiilide (XSLT) loomine , VR2.3

From EIK wiki

Teooria

XML on standardiseeritud märgendikeel. Selle eesmärgiks on struktureeritud info hoidmine enamasti transpordi eesmärgil. Kuna XML on laiendatav, siis baseeruvad sellel keelel väga paljud standardiseeritud struktuurid - XHTML, RSS, SOAP, SVG jne.

Selleks, et XML-i edukalt tarnida ühest süsteemist teise on vaja kontrollida selle valiidsust. See on vajalik selleks, et ühest süsteemist teise viies ei esineks vigu. Mõlemad süsteemid kusjuures peavad kasutama sama valideerimismeetodit.

XML-i puhul on valideerimisvõimalusteks Dokument Type Definition (DTD) ja XML Schema (XSD).

  • DTD meetodiga määratakse ära lubatud struktuurelemendid, nende attribuudid ning nende väärtustüübid.
  • XSD meetod on võimalusterohkem, kui DTD, ning sellega on võimalik kirjeldada palju keerulisemaid struktuure valideerimiseks.

Aga milleks me ikkagi valideerime XML-e?

XML on enamikel juhtudel elulise tähtsusega rakenduse toimimisel. Kui me valideerime XML-i ja leiame enne selle kasutamist, et see ei ole soovitud formaati, siis sellega saame me hoida ära paljud ebameeldivad üllatused, mis võivad tekkida. Siiski see ei välista nende tekkimist.

Document Type Definition - DTD

DTD puhul on tegemist XMList eraldi seisva keelega. Sellega on võimalik ära määrata elementide ja nende attribuutide esinemist. Elementide ja attribuutide väärtuste tüüpi on võimalik määrata väga kesiselt.

DTD struktuurikirjeldust saab määrata XML-i jaoks kahte moodi:

  • Inline - ehk siis sama XML'i sees kirjeldatakse ära selle juurelemendi alamelementide ja -attribuutide puu.
  • External - ehk XML-i struktuur kirjeldatakse ära XML-ist eraldi failina.

Esimest varianti tasub kasutada vaid juhul, kui tegu on väga väikese struktuuiga XML-iga. Ehk siis enamasti õppimise ja testimise raames. Teine variant on mõeldud kasutamiseks juba väheke keerukamate XML struktuuride kirjeldamise puhuks.

Selle XML-i struktuuri kirjeldamise peamisteks märgenditeks on:

  • <!ELEMENT elemendi_nimi (alam_element1, alam_element2)> või <!ELEMENT elemendi_nimi (elemendi_andmetüüp)>
    • Elemendi tüüpideks on: W3Schools
      • #PCDATA - kontrollitakse väärtust, et temas ei oleks < ja & sümboleid.
      • #CDATA - väärtust ei kontrolita, et temas ei oleks < ja & sümboleid.
      • EMPTY - elemendil ei ole väärtust
  • <!ATTLIST elemendi_nimi attribuudi_nimi andmetüüp nõutavus>
    • Andmetüübid: W3Schools
      • CDATA - Tekstväärtus
      • (en1|en2|..) - Üks võimalik väärtus enumereeritud loetelust
      • ID - Väärtus on unikaalne id
      • IDREF - Väärtus on mõne teise elemendi ID
      • IDREFS - Väärtus on loetelu teiste elemendide ID-dest
      • NMTOKEN - Väärtus on valiidne XML-i nimi
      • NMTOKENS - Väärtuseks on valiidsed XML-i nimed
      • ENTITY - Väärtus on üksuse nimi
      • ENTITIES - Väärtus on üksuste loetelu
      • NOTATION - Väärtus on märke nimi.
      • xml: - Väärtus on eelnevalt määratud XMLi väärtus
    • Nõutavus: W3Schools
      • väärtus - Vaikimisi attribuudi väärtus
      • #REQUIRED - Väärtus on vajalik.
      • #IMPLIED - Väärtus on valikuline
      • #FIXED väärtus - fikseeritud väärtus

Internal DTD

Nagu mainitud, kirjeldatakse sellisel juhul ära struktuur XML'i enda sees:

<?xml version="1.0" encoding="utf-8">
<!DOCTYPE HOUSE [

<!ELEMENT HOUSE (ROOM*)>
<!ELEMENT ROOM (DOOR+,WINDOW+)> <!-- + * ? tähistavad esinevust failis -->
<!ELEMENT DOOR (#PCDATA)>
<!ELEMENT WINDOW (#PCDATA)>

<!ATTLIST HOUSE ADDRESS CDATA #REQUIRED>
<!ATTLIST ROOM OWNER CDATA #IMPLIED>
]>
<HOUSE ADDRESS="Raja 3C">
  <ROOM OWNER="User1">
    <DOOR />
    <WINDOW />
    <WINDOW />
  </ROOM>
  <ROOM OWNER="User2">
    <DOOR />
    <WINDOW />
    <WINDOW />
    <WINDOW />
  </ROOM>
  <ROOM>
    <DOOR />
  </ROOM>
  <ROOM OWNER="User1">
    <DOOR />
    <WINDOW />
  </ROOM>
</HOUSE>

External DTD

Sellisel juhul asub struktuurikirjeldus eraldi failis. Oletame, et meil on selleks failiks House.dtd

<!ELEMENT HOUSE (ROOM*)>
<!ELEMENT ROOM (DOOR+,WINDOW+)> <!-- + * ? tähistavad esinevust failis -->
<!ELEMENT DOOR (#PCDATA)>
<!ELEMENT WINDOW (#PCDATA)>

<!ATTLIST HOUSE ADDRESS CDATA #REQUIRED>
<!ATTLIST ROOM OWNER CDATA #IMPLIED>

Ja XMLiks House.xml

<?xml version="1.0" encoding="utf-8">
<!DOCTYPE HOUSE SYSTEM "House.dtd">
<HOUSE ADDRESS="Raja 3C">
  <ROOM OWNER="User1">
    <DOOR />
    <WINDOW />
    <WINDOW />
  </ROOM>
  <ROOM OWNER="User2">
    <DOOR />
    <WINDOW />
    <WINDOW />
    <WINDOW />
  </ROOM>
  <ROOM>
    <DOOR />
  </ROOM>
  <ROOM OWNER="User1">
    <DOOR />
    <WINDOW />
  </ROOM>
</HOUSE>

DTD loomiseks ei ole Visual Studio keskkonnas olemasoleva XMLi peale genereerimiseks automaatseid vahendeid. DTD tuleb kirjutada käsitsi.

Valideerimine

Valideerimisel tuleb silmas pidada, et ei saa kasutada Linq to XML meetodit, kuna ee ei toeta DTD-d. XML'i valideerimiseks DTD põhjal kasutame external DTD näidet:

// Set the validation settings.
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Parse;
settings.ValidationType = ValidationType.DTD;
settings.ValidationEventHandler += new ValidationEventHandler ((sender, e) =>{
        System.Windows.Forms.MessageBox.Show("Validation Error: " + e.Message);
    });

// Create the XmlReader object.
XmlReader reader = XmlReader.Create("House.xml", settings);

// Parse the file. 
while (reader.Read());


XDocument'iga ei tööta

XML Schema Definition (XSD)

XSD puhul on tegemist alternatiiviga DTDle. Kusjuures XMLi struktuur kirjeldatakse ära samuti XML märgendikeeles. XSD struktuuris saab kirjeldada, mis tohib, mis ei tohi olla ja kuidas peavad olema need elemendid määratud. Selles märgendistandardis saab kirjeldada väga keerulisi struktuure.

Selles saab kirjeldada:

  • Elementide järjestikulist esinemist.
  • Nende esinemiste arvu
  • Attribuutide esinemisi elementides
  • Attribuutide ja elementide väärtustüüpe.
  • Lisaks on võimalik määrata andmetele tingimusi.
  • Oluliseks saab teha nende esinemise järjekorra

XSDs leiduvad elemendid saab jämedalt jagada kaheks:

  • Simple type
  • Complex type

Simple type

Tegemist on elemendikirjeldusega, millel ei ole attribuute ega ka alamelemente vaid lihtsalt väärtus.

<elementName>value</elementName>

Complex type

Sellisel andmetüübil ehk elemendil võib olla alamelemente ja attribuute.

Complex type lähemaks uurimiseks palun kasutada järgnevaid viiteid:

XSD genereerimine Visual Studio keskkonnas

Võrreldes DTDga on XSD'l hea eelis. Seda ei pea käsitsi kirjutama. Selleks saab kasutada Visual Studio arenduskeskkonna vahendeid. Selleks loote või avate VS keskkonnas XML'i ja vajuta "Create Schema" nuppu tööriistaribal. Peale seda genereeritakse teile XSD fail, mida antud hetkel ei ole veel salvestatud kuskile. selle peate ise salvestama soovitud asukohta.

Valideerimine

XML'i valideerimiseks XSD-ga saab kasutada järgnevat meetodit:

// Oletame, et meil on House.xml jaoks ka fail House.xsd
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add("", "House.xsd");

// Laeme sisse House.xml-i
XDocument doc = XDocument.Load("House.xml");
// Ja üritame valideerida
custOrdDoc.Validate(schemas, (o, e) =>
    {
        // Iga vea kohta avatakse teade
        System.Windows.Forms.MessageBox.Show(e.Message);
    });

MSDN Näide

Extensible Stylesheet Language Transformations (XSLT)

Jämedalt öeldes on XSLT teemakirjeldus nagu CSS on HTMLi jaoks. See on mõeldud XML andmete HTMLiks transformeerimiseks. Seda selleks, et neid andmeid oleks võimalik inimlikul kujul lugeda. Siiski ei ole see mõeldud kasutajaliideste loomiseks! Kuigi see on võimalik.

XSLT puhul on väga tähtsal kohal XPath'i kasutamise oskamine. Selle adresseimismeetodiga liigutakse transformeerimise andmete saamiseks XML-is ringi.

XPath süntaksi tarbeks vaadake antud viidet.

XSLT viitamine XMLis

Selleks, et XMLi jaoks XSLT template'i kasutataks tuleb see määrata XML'is peale <?xml ... ?> tagi

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="House.xsl"?>
...

<xsl:template>

Antud elemendiga määratakse ära stiili põhi. Näide:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/"> <!-- xsl:template element vastab XML'i juurelemendile -->
  <html>
  <body>
    Mingi nimekiri.
    <ul>
      <li>Element 1</li>
      <li>Element 2</li>
      <li>Element 3</li>
      <li>Element 4</li>
    </ul>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

<xsl:value-of>

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <html>
  <body>
    Mingi nimekiri.
    <ul>
      <li><xsl:value-of select="HOUSE/ROOM"/></li> <!-- xsl:value-of element vastab XML'i HOUSE juurelemendi esimesele ROOM elemendile -->
      <li>Element 2</li>
      <li>Element 3</li>
      <li>Element 4</li>
    </ul>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

<xsl:for-each>

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <html>
  <body>
    Mingi nimekiri.
    <ul>
      <xsl:for-each select="HOUSE/ROOM"> <!-- valime järjest tsüklis kõik ROOM elemendid -->
      <li><xsl:value-of select="@OWNER"/></li> <!-- xsl:value-of tagastab ROOM elemendi OWNER attribuudei väärtuse -->
      </xsl:for-each>
    </ul>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

<xsl:sort>

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <html>
  <body>
    Mingi nimekiri.
    <ul>
      <xsl:for-each select="HOUSE/ROOM">
      <xsl:sort select="@OWNER"/> <!-- sorteerime omaniku järgi -->
      <li><xsl:value-of select="@OWNER"/></li>
      </xsl:for-each>
    </ul>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

<xsl:if>

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <html>
  <body>
    Mingi nimekiri.
    <ul>
      <xsl:for-each select="HOUSE/ROOM">
        <xsl:if test="0 = count(WINDOW)"/> <!-- kuvame ainult ruumi omanikud, kelle ruumil pole aknaid -->
      <li><xsl:value-of select="@OWNER"/></li>
        </xsl:if>
      </xsl:for-each>
    </ul>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

<xsl:choose>

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <html>
  <body>
    Mingi nimekiri.
    <ul>
      <xsl:for-each select="HOUSE/ROOM">
        <xsl:choose>
          <xsl:when test="0 = count(WINDOW)">
      <li bgcolor=red><xsl:value-of select="@OWNER"/></li> <!-- kuva punaselt, kui pole aknaid -->
          </xsl:when>
          <xsl:otherwise>
      <li><xsl:value-of select="@OWNER"/></li> <!-- kuva tavaliselt -->
          </xsl:otherwise>
        </xsl:choose>
      </xsl:for-each>
    </ul>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

Materjali lugemiseks

Praktiline ülesanne

Käsi_hoitud_tegevus

Praktikumi ülesande aluseks on filmide andmebaasi XML. Antud XMLis on kirjeldatud filmid.

Loengus tehtud näited asuvad siin

Filmide kohta on piisavalt andmeid, et lahendada järgnev ülesanne:

  • Loo XSLT, mis kuvab kõikide filmide pealkirjad ja näitlejad
  • Luua filmide andmebaasi XMLi jaoks XSLT, kus kuvatakse kõik žanrid.
    • Ning iga žanri alla pannakse filmid. Sama filmi võib esineda erineva žanr'i all mitu korda.
    • Väljundiks on HTML
    • Iga filmi puhul tuleb välja kirjutada ka näitlejad
    • Kirss tordil: kuva ka pildid, mis on XMLiga kaasas


  • Juhul kui Visual Studiost ei toimi XSLT käivitamine, võib proovida lisada järgneva deklaratsioonis XML faili, millest transformatsiooni tehake. movies.xslt asendada enda xslt faili nimega.
    • <?xml-stylesheet type="text/xsl" href="movies.xslt" ?>

Proovi automaatselt genereerida XSD skeemifail ning vii sisse vajalikud parandused


C# näide: https://msdn.microsoft.com/en-us/library/ms163431.aspx

Lõpetada Käsi_hoitud_tegevus. Saata õppejõule hiljemalt 26.02.2017 kell 23:59. Kirja pealkiri algab teemaga: [DKBoonus2] ja võimalik on teenida 2p boonust.

  • NB! Lisa juurde Year="1994" IMDB_Position="1" ja Description väljad
  • Vajadusel saad abi päevaõppe praktikum 2 videost.

Käsi_mittehoitud_tegevus

Luua eelmises praktikumis loodud XMLidele stiilifailid, kus

  • prinditakse välja HTML kujul eelmises praktikumis valminud retseptide XML andmefailist välja retseptide kohta käiv info
  • prinditakse välja kõik ruumid HTML kujul koos arvutitega


Luua eelmises praktikumis tehtud XML failidele skeemifailid