XML: eXtreem Moeilijk te Leren?

Inleiding en achtergrond

Veel nieuwe hype's treffen regelmatig de ontwikkelaar. Daarbij is er eigenlijk maar �n vraag echt relevant en die luidt: "Is deze technologie niet alweer verouderd voordat ik er mee te maken krijg?". Luidt het antwoord hierop ja, dan verdiep je je er niet meer dan oppervlakkig in, net voldoende om mee te komen aan de borrel, en het zingt verder je tijd wel uit. Deze strategie is alles behalve verstandig voor XML, en alles wat daarmee samenhangt. En dat is veel. Om maar gelijk het met de deur in huis te vallen, we krijgen te maken met XSL, XLL, DTD, DOM, SAX, SVG, SML, en eigenlijk zo'n beetje elke afkoring van drie letters die je kunt bedenken.

Over deze zaken kunnen we gemakkelijk enkele dikke boeken volschrijven. Dat is natuurlijk niet de bedoeling. Daarom wil ik me in dit verhaal concentreren op zaken die direct relevant zijn, en achtergrond, geschiedenis en dergelijke zo veel mogelijk achterwege te laten. Ook zal ik nergens volledigheid van bijvoorbeeld de syntaxis kunnen nastreven.

Bijna elk artikel over XML begint met een inleiding over het hoe en waarom van XML, dat XML van SGML is afgeleid en meer van dat soort zaken. Laten we dat nu eens niet doen, het voegt weinig toe voor die mensen die gelijk aan de slag willen en bovendien is het allemaal op het Web te vinden. We starten derhalve met de kern van de zaak.

Mijn eerste XML bestand

Wat is nu eigenlijk XML? XML staat voor eXtensible Markup Language. Dit betekent dat we het hebben over uitbreidbaar instrument geschikt om gegevens van structuur te voorzien. Met de juiste afspraken over de syntax van de structuurbeschrijving hebben we het over een taal. En als we nu die afspraken niet vastleggen, maar overlaten aan de gebruiker, hebben we het over een metataal. XML is dus een metataal; een taal om een taal in te schrijven om data te structureren. Dan hebben we natuurlijk ook weer een andere taal nodig om vast te leggen hoe we onze zelf gedefinieerde taal gaan kiezen. Dit is de DTD, de Document Type Definition. Een alternatief voor de DTD's zijn de XML-Schema's of kortweg Schema's. XML wordt beheerd' door het World Wide Web Consortium [1]. Zo, dat is voldoende theorie, nu eerst de praktijk.

Laten we er eens van uitgaan dat je van een schaakclub met de naam "Pat" de gegevens gestructureerd wilt onderbrengen. Je weet nog niet precies wat je met de data wilt gaan doen, maar het moet in ieder geval gemakkelijk zijn data op het web te publiceren en zelf in een script te manipuleren. Daarnaast wil je de data ook op een generieke wijze toegankelijk maken voor de beheerders van andere schaakclubs. Dat deze zaken natuurlijk wel al honderd maal zijn uitgevonden is nu niet relevant; we gaan hier samen opnieuw het wiel uitvinden, mag je zelf straks bepalen welk wiel het beste rolt.

We brengen onze deelnemers onder in een XML bestand [Open dit bestand in IE5] :

<?xml version="1.0"?>

<deelnemer ID="pat-0020-0562">
  <naam>
    <voornaam> Maarten </voornaam>
    <achternaam> van Dijke </achternaam>
  </naam>
  <adres type="Nederlands">
    <straat> Jan Tiniusstraat </straat>
    <nummer> 13 </nummer>
    <plaats> Zwaandam </plaats>
  </adres>
  <telefoon/>
  <email> maarten@coldmail.com </email>
  <rating> 1402 </rating>
</deelnemer>

Aan dit bestand vallen een aantal zaken op:

Met name dit laatste punt is wat mij betreft het belangrijkste aspect van XML; een bestand geladen in een simpele editor geeft meteen prijs waar de data over gaat. Daarbij is het wel belangrijk enkele ontwerpregels te hanteren, waar we later op terug zullen komen. De tags zijn duidelijk zelf gekozen, zodat we de parser van dit document, wat voor een applicatie dat ook moge zijn, nog zullen moeten meedelen wat te doen met deze tags. Zo wordt ook duidelijk dat de tags primair bedoeld zijn om aan te geven waar de data over gaat die zich tussen de tags bevindt; en niet om aan te geven hoe deze data moet worden weergegeven, zoals bij HTML. Natuurlijk kunnen we XML wel voor dit doel gebruiken, en we zullen ook nog zien hoe. En door de hi�archische structuur lijkt het de representatie van een object instantie.

Formele eisen

Hoewel we de discussie praktisch willen houden zijn enkele formele punten op dit moment even van belang:

  1. De instructie <?xml version= "1.0"?> is een processing instruction', welke meedeelt hoe het dit bestand te begrijpen is. De inhoud spreekt voor zich. Overigens kunnen proces instructies <? ... ?> ook elders in een document voorkomen.
  2. Elke openingstag <MijnTag> moet worden afgesloten met een sluitingstag </MijnTag>. De afsluiting mag overigens ook in �n tag worden vervat, dus met <MijnTag/>. De openingstag tot en met de overeenkomende sluitingstag wordt een element genoemd. De namen van de tags zijn case-sensitive', dus <MijnTag> kan niet worden afgesloten met </mijntag>.
  3. Elementen mogen wel genest' worden, maar elkaar niet gedeeltelijk overlappen, dit heeft ook wel "proper nesting". Bijvoorbeeld <b><i> hi there </i></b> is toegestaan, maar <b><i> hi there </b></i> niet.
  4. E� element is het root-element, in ons voorbeeld is dit <deelnemer>.
  5. Een tag kan attributen hebben, welke de waarde krijgen toegekend via de = en waarbij de aanhalingstekens verplicht zijn.

We zien dus dat een XML document, ondanks alle vrijheid, erg strikt is opgebouwd. Een XML document dat aan de bovenstaande eisen voldoet is Well-Formed', en kan daarmee door een XML-parser worden gelezen. Omgekeerd, een goede parser geeft een foutmelding bij een niet goed gevormd XML-document en probeert er geen slag naar te slaan'. Zouden we bijvoorbeeld ergens �n sluitingstag vergeten, dan mag de parser niet doen alsof deze er wel staat en hiermee verder gaan, ook al is overduidelijk dat er een vergissing in het spel is. Dit is namelijk de gangbare praktijk bij HTML parsers en heeft meer kwaad dan goed gedaan.

Met alle vrijheid komt ook de verantwoordelijkheid. We zouden de bovenstaande informatie bijvoorbeeld ook als volgt kunnen hebben verpakt [Open dit bestand in IE5] :

<?xml version="1.0"?>

<deelnemer
  ID="pat-0020-0563"
  naam="Marieke Doorwinter"
  adres="Achterdreef 233"
  plaats="Zwaandam"
  telefoon=""
  email="marieke@coldmail.com"
  rating="2231" />
of als [Open dit bestand in IE5] :
<?xml version="1.0"?>

<deelnemer ID="xt018308">
  <naam> Anne Sluis </naam>
  <adres> Klaproos 53, Zwaandam</adres>
  <telefoon/>
  <email> anne@coldmail.com</email>
  <rating> 1670 </rating>
</deelnemer>

Wat is nu wijsheid? Ik denk dat het duidelijk mag zijn dat het niet de bedoeling is (alle) data in attributen onder te brengen, hoe gemakkelijk dit ook moge zijn vanuit bijvoorbeeld een relationele database. Aan de andere kant is het natuurlijk ook een kwestie van smaak. Ik hanteer de volgende regels bij het ontwerp van een XML-structuur:

  1. Alles wat data is komt in elementen met tags, welke zelf zo weinig mogelijk eigen structuur kennen, tenzij deze standaard' is. Dus bijvoorbeeld, een adres verdeel je zo ver mogelijk onder, maar voor een tijdstip zou je eventueel een open standaard kunnen hanteren, nu ik dit artikel schrijf is het bijvoorbeeld 2000-06-13T16:36:30.000+01:00. Datum en tijd spreken voor zich en refereren aan de lokale tijd. De +1:00 is een zone-indicator en wil zeggen dat de aangegeven tijd �n tijdzone voorloopt op de universele tijd (GMT).
  2. De tag ID neemt een speciale plaats in omdat in het gehele document elke ID waarde maar �nmaal mag voorkomen, hier is het gebruik van een attribuut dus wel op zijn plaats.
  3. Daarnaast kan je overwegen om informatie die zegt op welke wijze de structuur van het document door een translator' begrepen dient te worden wel in attributen onder te brengen.
  4. Bij twijfel kies je voor elementen.

Wat zijn dan de nadelen van attributen ten opzichte van elementen? Hier zijn er een aantal:

  1. Attributen kunnen slechts �n waarde bevatten en zijn daarmee dus niet uitbreidbaar als zich in de toekomst veranderingen voordoen.
  2. Met attributen kunnen geen structuren beschreven worden.
  3. De waarden van de attributen laten zich lastiger beschrijven in een DTD.

Mijn persoonlijke voorkeur gaat dan ook uit naar het eerste voorbeeld.

De verwarring die bovenstaande discussie kan opleveren [2] heeft er al toe geleid dat er een subcommunity' is ontstaan die alleen gebruik maakt van de meest eenvoudige onderdelen van XML, met de afkorting SML (Simple Markup Language). SML is XML waarbij geen gebruik gemaakt wordt van attributen, procesinstructies, DTD's, CDATA en zonder allerlei andere features. Het is een interessante beweging, waarvan je op de hoogte moet zijn, maar ik vraag me af of het echt zal doorzetten, XML staat zelf al stevig op de rails.

Beschrijving van de taal met een DTD of een Schema.

We weten nu hoe we een document kunnen maken dat goed is gevormd en als zodanig door een XML parser gelezen kan worden. Als je echter een dataformaat wilt beschrijven is het nodig dat je afspraken maakt waar welke informatie kan worden aangetroffen. Die afspraken maak je bij voorkeur in het team dat met de data aan de slag gaat. Daarna leg je ze vast in het XML bestand zelf. Hiermee wordt als het ware een voorschrift gecre�rd zodat je zeker weet dat alle toekomstige gebruikers van het formaat via dezelfde richtlijnen werken. In de industrie zie je al dat grote partijen onderling afspraken maken over hoe bepaalde data moet worden gestructureerd, en dat terwijl de XML-standaards nog niet eens af zijn. Die afspraken worden zelf weer vastgelegd met behulp van een taal. Hiervoor hebben we de keuze uit de DTD of uit een XML-Schema's.

De DTD is de huidige standaard en XML-Schema's is een uitvinding van de jongens uit Redmond, welke overigens ondertussen wel door het W3C is overgenomen. We gaan beide bespreken. En hoewel ik doorgaans helemaal geen Microsoft fan ben, moet ik toegeven dat het Schema-concept wel een elegante uitvinding is. Het grootste voordeel is van esthetische aard; Schema's zijn namelijk zelf ook weer XML, terwijl voor DTD's een aparte syntax geldt. Daarnaast zijn de Schema's in potentie ook wat krachtiger.

Mijn eerste DTD

We zullen nu bekijken welke DTD past bij het XML bestand dat we eerder gezien hebben, hier nogmaals ons voorbeeld, nu uitgebreid met een DTD [Open dit bestand in IE5] :

<?xml version="1.0"?>

<!DOCTYPE deelnemer [
  <!ELEMENT deelnemer (naam,adres+,telefoon,email*,rating?)>
  <!ELEMENT naam      (voornaam,achternaam)>
  <!ELEMENT adres     (straat,nummer,plaats)>
  <!ELEMENT telefoon   (#PCDATA)>
  <!ELEMENT email      (#PCDATA)>
  <!ELEMENT rating     (#PCDATA)>
  <!ELEMENT voornaam   (#PCDATA)>
  <!ELEMENT achternaam (#PCDATA)>
  <!ELEMENT straat     (#PCDATA)>
  <!ELEMENT nummer     (#PCDATA)>
  <!ELEMENT plaats     (#PCDATA)>
  <!ATTLIST deelnemer  ID ID #IMPLIED>
  <!ATTLIST adres type (Nederlands|Europees|Amerikaans)
                       "Amerikaans">
]>

<deelnemer>
<!-- Hier volgen gegevens van de deelnemer zoals
     uit het eerste voorbeeld -->
</deelnemer>

De DTD is opgenomen in het XML bestand zelf en beschrijft wat de parser kan verwachten. Een XML document welke well-formed' is, en waar het root-element voldoet aan de DTD is een geldig, valid', document. We zien hier dat op de eerste regel van de !DOCTYPE declaratie de naam van het root element is vermeld, gevolgd door een opsomming van de elementen die kunnen voorkomen in het root element. De syntax voor !DOCTYPE is:
<!DOCTYPE root-element [ element-declarations ] >
Overigens, het is ook mogelijk de DTD in een ander bestand te beschrijven, hetgeen voordelen biedt indien er een projectteam met de data werkt, en dan is de syntax als volgt:
<!DOCTYPE root-element SYSTEM "filename">

De elementen die kunnen voorkomen worden gedeclareerd met:
<!ELEMENT element-name (element-content)>
De element-content geeft aan om welk soort data het gaat. #CDATA staat voor data bestaande uit karakters, zonder dat die door de parser moeten worden bekeken en #PCDATA staat voor karakterdata die wel door de parser wordt geanalyseerd. Dit zal vrijwel altijd het geval zijn. Als een element subelementen bevat wordt dit aangegeven door de namen tussen de haakjes te plaatsen. Er kan worden opgegeven of deze elementen:

  1. precies �n keer moeten voorkomen zoals naam en telefoon, er is dan geen achtervoegsel,
  2. minimaal �n maal moeten voorkomen, zoals adres door het achtervoegsel +,
  3. nul of meer keer moeten voorkomen, zoals email door het achtervoegsel *,
  4. precies nul of �n keer moeten voorkomen, zoals rating door het achtervoegsel ?.

en daarbij is de aangegeven volgorde ook de volgorde waarin de elementen moeten voorkomen.

We hebben ook al aangegeven tags attributen kunnen hebben. In dit voorbeeld zijn er twee opgenomen. Als eerste de ID behorende bij het element deelnemer en als tweede de type aanduiding behorende bij het adres. Deze moeten worden opgegeven in de DTD. De syntax hiervoor is
<!ATTLIST element-name attribute-name attribute-type default-value>
Voor het attribute-type kunnen we kiezen uit een hele rij typen, waaronder het ID type, dat regelt dat elke attribute-value uniek moet zijn, het CDATA type dat zegt dat we met karakterdata te maken hebben en het keuzetype, aangegeven met (ch1|ch2|...) dat het mogelijk maakt de gebruiker te laten kiezen uit een beperkt aantal mogelijkheden. Daarnaast hebben we voor de default-value een aantal mogelijkheden, waaronder #IMPLIED, #FIXED en #REQUIRED.

Nu willen we dat het ID attribuut gaat voldoen aan de ID specificatie in XML, d.w.z. elke ID-waarde komt slechts �n maal voor. Dus kiezen we zowel voor de attribuutnaam als voor het attribuuttype ID. Omdat we per definitie natuurlijk nooit een default voor kunnen opgeven is deze #IMPLIED. Daarnaast willen we voor het adres type attribuut de keuze geven uit een beperkt aantal mogelijkheden, hiervoor kiezen we dus het keuzetype.

Als we dit document vervolgens zouden laden in een browser, dan zou dit een valide document moeten opleveren.

Namespaces

Met XML is het voorgoed verleden tijd dat documenten op zichzelf staan. We willen gebruik kunnen maken van de inspanningen die anderen reeds geleverd hebben. Daartoe is het nodig op een gemakkelijke wijze te kunnen verwijzen naar andere documenten. Hiervoor is het begrip namespace' ingevoerd. Indien een tag voorafgegaan wordt door bijvoorbeeld xsl: zoals in <xsl:stylesheet> dan wil dit zeggen dat de definitie van <stylesheet> te vinden is in de namespace die gekoppeld is aan xsl. Deze koppeling geschied handmatig met de toekenning: <xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl"> Alles in het element stylesheet wat voorafgegaan wordt door xsl: is te vinden in de namespace gedefinieerd door de URI "http://www.w3.org/TR/WD-xsl". Over namespaces valt nog veel meer te zeggen, maar dat zullen we nu niet nodig hebben, dus we beperken ons even hiertoe.

Mijn eerste Schema

We hebben het al even eerder aangestipt, wat met een DTD kan kan ook met een XML Schema. Het ligt dus voor de hand te kijken wat er allemaal verandert wanneer we gebruik gaan maken van Schema's. We scheiden het document van het Schema en kijken eerst naar het eerste [Open dit bestand in IE5] :

<?xml version="1.0"?>

<deelnemer
  ID="pat-0020-0562"
  xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
  xsi:noNamespaceSchemaLocation="E:\...\pat6.xsd">

  <naam>
    <voornaam> Maarten </voornaam>
    <achternaam> van Dijke </achternaam>
  </naam>
  <adres type="Nederlands">
    <straat> Jan Tiniusstraat </straat>
    <nummer>13</nummer>
	 <plaats> Zwaandam </plaats>
  </adres>
  <telefoon/>
  <email> maarten@coldmail.com </email>
  <rating>1402</rating>
</deelnemer>

Meteen valt op dat dit document niet meer op zichzelf' staat; we hebben een referentie nodig naar een publiek bestand. Deze referentie werkt met een namespace definitie, de afkorting xmlns:xsi staat voor "eXtended Markup Language Name Space : Xml Schema Instance", gevolgd door de URI voor de beschrijving. In dit geval hebben we de namespace-referentie maar �n keer nodig, namelijk voor het attribuut xsi:noNamespaceSchemaLocation. Dit lijkt een beetje tegenstrijdig, een namespace aanroepen om vervolgens te melden dat we geen namespaces nodig zullen hebben. Echter, we gebruiken het hier om te zorgen dat we voor ons Schema geen aparte namespace hoeven op te zetten.

Voor de rest ziet het bestand er uit zoals eerst. Bij een nadere beschouwing valt wellicht op dat we bij het element nummer de spaties rond de 13 hebben weggenomen. Dit is ook het geval rond de rating. We willen namelijk in staat zijn de gebruiker van het formaat te dwingen bij deze elementen alleen numerieke waarden te gebruiken. En aangezien bij XML, in tegenstelling tot HTML, spaties relevant zijn, moeten we die hier wegnemen voor een goede controle.

We gaan nu kijken naar het bijbehorende Schema. Deze krijgt als bestand de extensie xsd mee [Open dit bestand in IE5] :

<?xml version="1.0" encoding="UTF-8"?>

<xsd:schema xmlns:xsd="http://www.w3.org/1999/XMLSchema">

  <xsd:element name="deelnemer">
    <xsd:complexType content="elementOnly">
      <xsd:sequence>
        <xsd:element name="naam" type="Tnaam"/>
        <xsd:element name="adres" type="Tadres"
                     minOccurs="1" maxOccurs="unbounded"/>
        <xsd:element name="telefoon" type="Ttelefoon"/>
        <xsd:element name="email" type="xsd:string"
                     minOccurs="0" maxOccurs="unbounded"/>
        <xsd:element name="rating" type="Trating"
                     minOccurs="0" maxOccurs="1"/>
      </xsd:sequence>
      <xsd:attribute name="ID" type="xsd:string"
                     use="required"/>
      <xsd:attribute name="xmlns:xsi"
                     type="xsd:uriReference"
                     use="default"
         value="http://www.w3.org/1999/XMLSchema-instance"/>
      <xsd:attribute name="xsi:noNamespaceSchemaLocation"
                     type="xsd:string"/>
      <xsd:attribute name="xsi:schemaLocation"
                     type="xsd:string"/>
    </xsd:complexType>
  </xsd:element>

  <xsd:complexType name="Tnaam" content="elementOnly">
    <xsd:sequence>
      <xsd:element name="voornaam" type="xsd:string"/>
      <xsd:element name="achternaam" type="xsd:string"/>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:complexType name="Tadres" content="elementOnly">
    <xsd:sequence>
      <xsd:element name="straat" type="xsd:string"/>
      <xsd:element name="nummer"
                   type="xsd:positiveInteger"/>
      <xsd:element name="plaats" type="xsd:string"/>
    </xsd:sequence>
    <xsd:attribute name="type" type="xsd:string"
                   use="required"/>
  </xsd:complexType>

  <xsd:simpleType name="Ttelefoon" base="xsd:string">
    <xsd:pattern value="(\d{3}-\d{7})|(\d{4}-\d{6})"/>
  </xsd:simpleType>

  <xsd:simpleType name="Trating" base="xsd:integer">
    <xsd:minInclusive value="1"/>
    <xsd:maxInclusive value="3000"/>
  </xsd:simpleType>

</xsd:schema>

Als eerste moeten we weer een namespace definitie doen om te zorgen dat we gebruik kunnen maken van voorgekookte tags. We doen dat met xmlns:xsd, een afkorting die nu wel te raden valt denk ik, en voor alle tags die we uit deze namespace gebruiken komt dan het voorvoegsel xsd:.

Laten we nu eens kijken hoe de structuur van het document beschreven wordt. Als eerste wordt een globaal element deelnemer gedeclareerd. Binnen deelnemer wordt de complexe structuur van het element verder uitgewerkt. Dit uitwerken kunnen we binnen het element zelf doen, of we kunnen er een type voor defini�en zoals bijvoorbeeld voor het element naam gedaan is. In de XML wereld wordt meestal gekozen voor zoiets als naamType, maar met mijn Delphi achtergrond vind ik het praktischer gewoon Tnaam te gebruiken, het is ook wat korter. We hebben ook nog een aantal andere typen (Tadres, Ttelefoon en Trating) de gedefinieerd, alleen maar om een indruk te geven van de vele mogelijkheden. De attributen minOccurs en maxOccurs worden gebruikt om het aantal malen dat het element verwacht wordt op te geven. Daarbij is het goed om in het achterhoofd te houden dat maxOccurs per default gelijk is aan minOccurs en minOccurs per default gelijk is aan �n. Het alleen opgeven van minOccurs=4 betekent dus dat de parser het betreffende element exact vier maal verwacht, wellicht niet wat je op het eerste gezicht zou verwachten. Geef je niets op dan wordt het element precies �n maal verwacht.

Voor het element deelnemer worden nog enkele attributen gedefinieerd, die deels met het gebruik van Schema's zelf te maken hebben. De attributen van de attributen elementen spreken denk ik voor zich.

Vervolgens geven we in de type beschrijving Tnaam aan dat dit element slechts zal bestaan uit de subelementen voornaam en achternaam die van het simple type string zijn. Het type string is in de XML Schema als standaard ingebouwd, evenals een hele reeks anderen, zoals positiveInteger, welke we gebruiken in de complexe definitie van Tadres voor het huisnummer. Hiermee sluiten we het gebruik van nummers als 8b natuurlijk uit, maar na het lezen van dit artikel weet je hiervoor vast wel een intelligente oplossing!

Interessant zijn ook de typen Ttelefoon en Trating. Het type Ttelefoon is een type dat wordt afgeleid van een basistype en wordt een simpleType genoemd. We kunnen nu, door het opgeven van een patroon, met xsl:pattern, het aantal mogelijke strings inperken. Hier hebben we aangegeven dat een telefoonnummer of uit drie cijfers, gevolgd door een koppelteken, gevolgd door zeven cijfers bestaat; of uit vier cijfers, gevolgd door een koppelteken, gevolgd door zes cijfers bestaat.

De Trating leiden we af van een integer, en we geven daarbij op dat deze integer mag liggen tussen 0 en 3001. De bereik is voldoende ruim voor alle mogelijkheden en voorkomt dat door typefouten rare' waarden ontstaan.

Zichtbaar maken in een Browser

Nu we dit allemaal hebben opgezet wordt het langzamerhand tijd met de informatie iets te gaan doen. We kunnen XML bestanden openen in een browser. Hiervoor moet de browser natuurlijk wel in staat zijn de informatie te kunnen lezen. Openen we bijvoorbeeld pat.xml in IE5 dan zien we dat de browser het wel begrijpt, maar het ziet er nu niet bepaald flitsend' uit, bezie het resultaat in figuur 1.

Figuur 1: pat.xml in Internet Explorer 5.

Ook in NS6 ziet het er erg sober uit. We kunnen in IE5 overigens wel de structuur verkennen en controleren of een bestand valide is. Helaas werkt dit niet voor Schema's (ik kreeg het in ieder geval niet voor elkaar een foutmelding te genereren), terwijl dit volgens de opgave wel zou moeten werken. De DTD validatie werkt wel goed. Natuurlijk is het logisch dat er geen mooie opmaak te voorschijn komt. XML is immers helemaal geen taal die hiervoor bedoeld is; dat is HTML. We zouden HTML wel in XML kunnen formuleren, immers, ze werken beide met tags, en dat is dan ook gedaan. Deze beschrijving heet XHTML. Echter, wij zitten nu met een XML bestand dat we graag op de een of andere manier netjes in de browser zichtbaar zouden willen maken. We moeten het als het ware vertalen naar HTML. Ook aan deze wens is gedacht, lees maar even mee.

Mijn eerste XSL bestand.

We gaan nu een bestand schrijven waarin de vertaal instructies staan om van een XML bestand, met onze specifieke structuur, te komen tot een toonbaar HTML bestand. En, vanzelfsprekend wordt dit gedaan in XML. Een dergelijk vertaalbestand is geschreven in XSL: eXtensible Style Language. In theorie zouden we dit ook kunnen bereiken met een CSS, maar eigenlijk past dit niet in de XML gedachte. Wat mij betreft kan je, in deze context (!), CSS dan ook met een gerust hart vergeten.

We gaan er hierbij van uit dat we ons oorspronkelijke bestand hebben uitgebreid met een nieuw root-element, namelijk deelnemers, met daarin een aantal elementen deelnemer. De uitbreiding die op de DTD of het Schema nodig is laat ik als opgave aan de lezer. Ons bestand pat.xml ziet er dan bijvoorbeeld als volgt uit [Open dit bestand in IE5] :

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="pat8.xsl"?>

<deelnemers
  xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
  xsi:noNamespaceSchemaLocation="E:\...\pat9.xsd">

  <deelnemer ID="pat-0020-0562">
    <naam>
      <voornaam> Maarten </voornaam>
      <achternaam> van Dijke </achternaam>
    </naam>
    <adres type="Nederlands">
      <straat> Jan Tiniusstraat </straat>
      <nummer>13</nummer>
      <plaats> Zwaandam </plaats>
    </adres>
    <telefoon/>
    <email> maarten@coldmail.com </email>
    <rating>1402</rating>
  </deelnemer>

  <deelnemer ID="pat-0020-0563">
    <naam>
      <voornaam> Marieke </voornaam>
      <achternaam> Doorwinter </achternaam>
    </naam>
    <adres type="Nederlands">
      <straat> Achterdreef </straat>
      <nummer>233</nummer>
      <plaats> Zwaandam </plaats>
    </adres>
    <telefoon/>
    <email> marieke@coldmail.com </email>
    <rating>2231</rating>
  </deelnemer>

  <deelnemer ID="pat-0020-0564">
    <naam>
      <voornaam> Anne </voornaam>
      <achternaam> Sluis </achternaam>
    </naam>
    <adres type="Nederlands">
      <straat> Klaproos </straat>
      <nummer>53</nummer>
      <plaats> Zwaandam </plaats>
    </adres>
    <telefoon/>
    <email> anne@coldmail.com </email>
    <rating>1670</rating>
  </deelnemer>

</deelnemers>

Hiervan willen een nette tabel maken. Daartoe maken we gebruik van het volgende XSL bestand [Open dit bestand in IE5] :

<?xml version="1.0"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
  <html>
  <body>
    <table border="0" cellpadding="4">
	  <tr bgcolor="#AFAFFF">
	    <th> Rating </th>
	    <th> Naam </th>
	    <th> Email </th>
	  </tr>
	  <xsl:for-each select="deelnemers/deelnemer"
                   order-by="-rating">
       <tr bgcolor="#DFDFFF">
       <td> <xsl:value-of select="rating"/> </td>
	      <td>
          <xsl:value-of select="naam/voornaam"/>
          <xsl:value-of select="naam/achternaam"/>
        </td>
	      <td> <xsl:value-of select="email"/> </td>
	    </tr>
	  </xsl:for-each>
	</table>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

We herkennen ook hier weer een verwijzing naar een namespace welke de elementen definieert die we nodig zullen hebben. De eerste instructie xsl:template geeft aan dat we ons document vanaf de root / willen behandelen. Alle tags zonder namespace zullen in het doeldocument worden ingevoegd. We bouwen dus een tabel op volgens de standaard methoden in HTML. Daarnaast kunnen we ook gebruik maken van loop-instructies om het bron-bestand te doorlopen en de tabel te vullen met de inhoud van specifieke elementen. Met het attribuut order-by dragen we de xsl-processor op de beste schakers bovenaan de lijst te plaatsen. Ik denk dat al deze instructies voor zichzelf spreken en het is natuurlijk duidelijk dat dit voorbeeld slechts een fractie van de mogelijkheden weergeeft. Voor de volledigheid in figuur 2 nog even de tabel zoals IE5 deze weergeeft.

Figuur 2. Door xsl gegenereerde tabel.

Conclusie

We zijn in staat geweest gegevens die we normaliter in een database zouden opbergen op een flexibele wijze in een XML bestand onder te brengen, voor te schrijven welke structuur deze data heeft, en daarna deze data te publiceren op het web. Dit alles met applicaties die reeds op zowat elke PC voorkomen. Op mijn site [9] kun je de voorbeelden zelf uittesten. Helaas hebben we niet meer dan kunnen ruiken aan de mogelijkheden die XML allemaal biedt. Echter, op het Internet zijn vele XML bronnen te vinden waar de dorstigen naar meer kennis zich kunnen laven.

Referenties en nuttige links

[1] www.w3c.org/xml/
[2] www.xml.com/pub/1999/11/sml/
[3] community.borland.com/article/0,1410,20412,00.html
[4] www.delphihome.com/xml/
[5] www.destructor.de/xmlparser/
[6] xmlcomponents.com/
[7] www.icom-dv.de/products/xml_tools/uk_xml_tools.php3
[8] new.xmlspy.com/
[9] www.betaresearch.nl/