XML

XML KOULUTUSTA VUONNA 2025

Kysy myös tuotekohtaisia koulutuksia, kuten Altova XMLSpy. Kurssit saatavilla kautta Suomen. Tule ja varaa oma koulutustapahtumasi heti! Koulutuksen järjestää asiantuntijasi Koulutus- ja konsultointipalvelu KK Mediat.

Case study: Online-luettelo XML:n ja XSLT:n avulla

Lyhyt projektisuunnitelma

Tämän esimerkkiprojektin tavoitteena on muuntaa relaatiotietokannan sisältö XML-muotoon, validoita se skeeman avulla ja esittää tulos HTML-muodossa XSLT-muunnoksen avulla. Toteutusesimerkkinä toimii online-postimerkkiluettelo.

Projektin vaatimukset:

  1. Tietokannan rakenne kuvataan XML:llä, ja sitä varten laaditaan XSD-skeema.
  2. XML-datan täytyy olla sekä hyvin muotoiltua (well-formed) että skeeman mukaista (validia).
  3. Käyttäjälle näytettävä lopputulos rakennetaan palvelinpuolen XSLT-muunnoksella.

Projektin vaiheet:

  1. Suunnitellaan tietokannan rakenne ja laaditaan siitä alustava XML-kuvaus. Tämän yhteydessä luodaan XSD-skeema XML-kuvaukselle. Lopullinen XML-rakenne rakennetaan tämän XSD-skeeman mukaisesti.
  2. Datan noutaminen XML-formaatissa - Toteutetaan tietokantakyselyt ja ohjelmakoodi, joka tulostaa tietokannan tiedot XML-rakenteena.
  3. XML-skeeman laatiminen - Määritellään XSD, joka varmistaa XML-datan oikeellisuuden ja rakenteen.
  4. XSL/XSLT-muunnosten toteutus

Tietokantakuvaus

Koska projektin aihe saattaa olla vieras, perehdytään ensin tarvittavaan tietokannan rakenteeseen. Käytämme tietokantaa nimeltä dbStamps, joka koostuu viidestä taulusta:

Päätaulu on nimeltään julkaisu, muut taulut ovat aputauluja. Aputaulut yhdistetään päätauluun relaatioiden avulla.

Taulu 1. hammaste. Määrittelee julkaisun vaaka- ja pystyhammasteen mahdolliset arvot.
Kenttä Tietotyyppi Pituus
h_id int 5
h_vaakahammaste varchar 5
h_pystyhammaste varchar 5
Taulu 2. Tyyppi. Määrittelee julkaisun tyypin eli onko kyseessä käyttösarjan julkaisu, juhlamerkki tai jokin muu.
Kenttä Tietotyyppi Pituus
t_id int  
t_tyyppi varchar 25
Taulu 3. Väri. Määrittelee julkaisun värin.
Kenttä Tietotyyppi Pituus
v_id int  
v_vari varchar 25
Taulu 4. Valuutta. Määrittelee julkaisussa käytetyn valuutan, esimerkiksi markka vai penniarvoinen, eurot vai sentit jne.
Kenttä Tietotyyppi Pituus
va_id int  
va_vari varchar 5
Taulu 5. Julkaisu. Koostetaulukko.
Kenttä Tietotyyppi Pituus
j_id int  
j_vuosi integer  
j_luettelonro integer  
j_tyypi integer  
j_vaakahammaste integer  
j_pystyhammaste integer  
j_aihe varchar 50
j_kuvaus varchar 250
j_nimellisarvo varchar 5
j_valuutta varchar 10
j_vari integer  
j_painos integer  
j_ensipaiva date  
j_arvopt float  
j_arvole float  
j_kuva varchar 50

XML-kuvaus tietokannan rakenteesta

XML-kuvauksen tuottamiseen on olemassa useita työkaluja, jotka integroituvat esimerkiksi MS SQL Serveriin tai Oracleen. Näitä työkaluja suositaan erityisesti laajamittaisissa ratkaisuissa, koska ne perustuvat tietokantavalmistajien luomille standardeille. Tässä projektissa käytämme kuitenkin vaihtoehtoista lähestymistapaa ja luomme yksinkertaisen XML-rakenteen tietokannan kuvaamiseksi.

Ensimmäinen askel on määritellä, mitä elementtejä tarvitaan tietokantarakenteen kuvaamiseen XML-muodossa. Mallin perustana toimivat tietokannan peruselementit:

Jokaisella elementillä (db, table, column) on joukko ominaisuuksia — osa yhteisiä, osa uniikkeja. Yhteistä kaikille elementeille on, että niillä on oltava yksilöllinen nimi. Etenkin taulukon kentät sisältävät useita ominaisuuksia, koska niihin data varastoidaan yksilöitynä. Alla lyhyt luettelo ominaisuuksista, jotka suunnittelussa on huomioitu:

Näiden tietojen pohjalta laadittu attribuuttipohjainen lähestymistapa voisi näyttää esimerkiksi tältä:


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

<db name="" 
xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"> 
<table name=""> 

<column name="" datatype="" length="" pk="" unique="" default="" nulls="" 
autoidentidy="" fk="" description=""/>
</table> 

</db> 

Tai vaihtoehtoisesti saman asian voi ilmaista elementtipohjaisesti:


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

<db name="" xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance">

<table name="">

<column name="" >
<datatype> </datatype>
<length/> </length>
<pk> </pk> 
<unique> </unique> 
<default> </default> 
<nulls> </nulls>
<autoidentidy> </autoidentidy> 
<fk> </fk> 
<description> </description>
</column>
</table> 
</db> 

Molemmat rakenteet ovat käyttökelpoisia – valinta riippuu sovelluksen tarpeista. Attribuuttimalli on yleensä tiiviimpi, mutta sen laajennettavuus on rajallista. Elementtipohjainen malli tukee paremmin monimutkaisia arvoja, kuten listoja tai monikielisiä kuvauksia.

Tässä lähestymistavassa on kuitenkin yksi selkeä ongelma: pelkkä XML ei riitä määrittelemään rakenteen sääntöjä muille järjestelmille. Esimerkiksi:

Näihin kysymyksiin vastaa XSD-skeema, joka määrittelee XML:n rakenteen ja säännöt. Ilman skeemaa data on rakenteellisesti epäselvää, eikä sen validointi tai koneellinen käsittely muissa sovelluksissa ei ole luotettavaa.

XML-skeeman määrittäminen tietokannan rakenteelle

Jotta XML-pohjainen tietokantakuvaus olisi käyttökelpoinen muille järjestelmille, sen rakenteelle on määriteltävä säännöt. Tämä tehdään XML-skeeman (XSD) avulla. Skeema varmistaa, että XML-dokumentti on rakenteellisesti validi ja noudattaa sovittua rakennetta. Seuraavassa on kuvattu tärkeimmät säännöt suunnitellulle projektille:

Sääntö 1: Vain yksi tietokanta per dokumentti.
XML-dokumentti voi sisältää täsmälleen yhden tietokannan (db-tagi). Vaikka useampi tietokanta olisi teknisesti mahdollista, rajoitamme määrän yhteen — muuten dokumentti ei ole skeeman mukainen.

Sääntö 2: Taulukoita voi olla ääretön lukumäärä.
Tietokannan sisällä voi olla 0...∞ taulua (table-tagi). Tämä vastaa yleistä tietokannan toimintamallia: taulujen lukumäärä on käytännössä rajaton, vaikka teknisiä ylärajoja voi järjestelmissä esiintyä.

Sääntö 3: Jokaisella taululla vähintään yksi kenttä.
Jokaisessa taulussa (table) täytyy olla vähintään yksi kenttä (column). Kenttien määrä voi kuitenkin vaihdella tarpeen mukaan, mikä heijastaa tietokannan joustavuutta.

Sääntö 4: Elementtien järjestys on pakotettu.
Tämä noudattaa tietokantojen rakennetta: tietokanta sisältää tauluja, jotka sisältävät kenttiä. Sen sijaan kenttä-dataa ei saa sijoittaa esimerkiksi taulukoiden ulkopuolelle.

Sääntö 5: Elementit vai attribuutit?
Mallissa käytetään elementtejä kuvaamaan rakennetta ja attribuutteja kuvaamaan ominaisuuksia. Elementteinä kuvataan rakenteelliset osat (db, table, column), attribuuteilla kuvataan näiden ominaisuuksia kuten nimi (name), tietotyyppi (datatype) jne. Elementeillä db ja table voi olla vain ja ainoastaan attibuutti name. Kunkin attribuutin ilmemenisen pakollisuudesta voimme tehdä tarvittavat säännöt erikseen.

Näiden sääntöjen pohjalta rakennetaan XML Schema Definition (XSD), joka kuvaa sallitun XML-rakenteen tarkasti. Koska skeemojen kuvaamisessa käytettävä XSD-kieli on oma erillinen kokonaisuutensa josta voisi kirjoittaa kymmeniä sivuja, käydään asia tässä lävitse seuraavan esimerkin koodiin upotettujen kommenttien avulla. Lisätietoa XSD skeema-kielestä löytyy W3C:n sivuilta.

 <?xml version="1.0" encoding="UTF-8" ?>
 <xsd:schema xmlns:xsd="http://www.w3.org/2000/10/XMLSchema"  elementFormDefault="qualified">

  <!-- xsd:annotation mahdollistaa scheman kommentoinnin -->

  <xsd:annotation>
 <xsd:documentation>
Tämä schema määrittelee tietokantojen kuvauksessa  käytettävän perusrakenteen.</xsd:documentation>
 </xsd:annotation>

  <!-- Käyttämällä simpleType määrittelyä voimme luoda omia tietotyyppejä, joita  voimme periyttää -->

  <xsd:simpleType name="dataType">
 <xsd:annotation>
 <xsd:documentation>
Tyyppi dataType sisältää mahdolliset tietotyypit  kentille</xsd:documentation>
 </xsd:annotation>

  <!-- Käyttämällä restriction määrittelyä voimme määrätä tiettyjä reunaehtoja,  kuten tietotyypin, sallitut arvot jne -->

  <xsd:restriction base="xsd:NMTOKEN">
 <xsd:enumeration value="integer"/>
 <xsd:enumeration value="varchar"/>
 <xsd:enumeration value="datetime"/>
 <xsd:enumeration value="bit"/>
 <xsd:enumeration value="float"/>
 </xsd:restriction>

 </xsd:simpleType>

   <xsd:simpleType name="dataLength">
 <xsd:annotation>
 <xsd:documentation>
Tyyppi dataLength määrittelee kentän pituuden.  </xsd:documentation>
 </xsd:annotation>
 <xsd:restriction base="xsd:integer"/>
 </xsd:simpleType>



    <!-- Sitten alkaa varsinainen rakenteen kuvaus. Huomaa, että olemme joissain  elementeissä perittyäneet tyypin SimpleTypesta -->

   <xsd:element name="db">

   <xsd:complexType>
 <xsd:sequence>
 <xsd:element name="table" maxOccurs="unbounded">

  <xsd:complexType>
 <xsd:sequence>
 <xsd:annotation>
 <xsd:documentation>
Kenttä voi sisältää seuraavat attribuutit, name,  datatype, length, pk, description, fk, unique, autoidentity ja description.  Näistä kaikki muut paitsi autoid. ovat pakollisia. </xsd:documentation>
 </xsd:annotation>

  <xsd:element name="column" maxOccurs="unbounded">
 <xsd:complexType>
 <xsd:attribute name="name" type="xsd:string" use="required"/>
 <xsd:attribute name="datatype" type="dataType" use="required"/>
 <xsd:attribute name="length" type="dataLength" use="required"/>
 <xsd:attribute name="pk" type="xsd:boolean" use="required"/>
 <xsd:attribute name="description" type="xsd:string" use="required"/>
 <xsd:attribute name="default" type="xsd:string" use="required"/>
 <xsd:attribute name="fk" type="xsd:string" use="required"/>
 <xsd:attribute name="unique" type="xsd:boolean" use="required"/>
 <xsd:attribute name="nulls" type="xsd:boolean" use="required"/>
 <xsd:attribute name="autoidentidy" type="xsd:boolean" use="optional"/>

  </xsd:complexType>

  </xsd:element>
 </xsd:sequence>

  <xsd:attribute name="name" type="xsd:string" use="required"/>

  </xsd:complexType>
 </xsd:element>

  </xsd:sequence>

  <xsd:attribute name="name" type="xsd:string" use="required"/>

  </xsd:complexType>
 </xsd:element>

  </xsd:schema>

 
 

Nyt kun XML-rakenteen säännöt on määritelty, voimme rakentaa XML-kuvauksen tietokannan rakenteesta:

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

 <db name="dbStamps" xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance">  

 <table name="hammaste"> 

 <column name="h_id" datatype="integer" length="" pk="true" unique="true"  default="max + 1" nulls="false" autoidentidy="true" fk="" description="1"/>  

 <column name="h_vaaka" datatype="varchar" length="5" pk="false" unique="false"  default="" nulls="false" autoidentidy="false" fk="" description="Vaakahammaste,  esim.15"/> 

 <column name="h_pysty" datatype="varchar" length="5" pk="false" unique="false"  default="" nulls="false" autoidentidy="false" fk="" description="Pystyhammaste,  esim.15"/> 

 </table> 


  <table name="tyyppi"> 

 <column name="t_id" datatype="integer" length="" pk="true" unique="true"  default="max + 1" nulls="false" autoidentidy="true" fk="" description="123"/>  

 <column name="t_tyyppi" datatype="varchar" length="25" pk="false"  unique="false" default="" nulls="false" autoidentidy="false" fk=""  description="Tyypin nimi, esim. juhlamerkki"/> 

 </table> 


  <table name="valuutta"> 

 <column name="va_id" datatype="integer" length="" pk="true" unique="true"  default="max + 1" nulls="false" autoidentidy="true" fk="" description="123"/>  

 <column name="va_yksikko" datatype="varchar" length="5" pk="false"  unique="false" default="" nulls="false" autoidentidy="false" fk=""  description="Merkin valuutta, esim. mk"/> 

 </table> 


  <table name="varit"> 

 <column name="v_id" datatype="integer" length="" pk="true" unique="true"  default="max + 1" nulls="false" autoidentidy="true" fk="" description="123"/>  

 <column name="v_vari" datatype="varchar" length="25" pk="false" unique="false"  default="" nulls="false" autoidentidy="false" fk="" description="Julkaisun  vari, esim. lila"/> 

 </table> 


  <table name="julkaisut"> 

 <column name="j_id" datatype="integer" length="" pk="true" unique="true"  default="max + 1" nulls="false" autoidentidy="true" fk="" description="123"/>  

 <column name="j_vuosi" datatype="integer" length="" pk="false" unique="false"  default="" nulls="false" autoidentidy="false" fk="" description="1975"/>  

 <column name="j_luettelonro" datatype="integer" length="" pk="false"  unique="false" default="" nulls="false" autoidentidy="false" fk=""  description="990"/> 

 <column name="j_tyyppi" datatype="integer" length="" pk="false" unique="false"  default="" nulls="false" autoidentidy="false" fk="t_id" description="2"/>  

 <column name="j_vaakahammaste" datatype="integer" length="" pk="false"  unique="false" default="" nulls="false" autoidentidy="false" fk="h_id"  description="5"/> 

 <column name="j_pystyhammaste" datatype="integer" length="" pk="false"  unique="false" default="" nulls="false" autoidentidy="false" fk="h_id"  description="5"/> 

 <column name="j_aihe" datatype="varchar" length="50" pk="false" unique="false"  default="" nulls="false" autoidentidy="false" fk="" description="Julkaisun  nimi; esim. Hiihdon MM-kisat"/> 

 <column name="j_kuvaus" datatype="varchar" length="250" pk="false"  unique="false" default="" nulls="false" autoidentidy="false" fk=""  description="Merkin kuva-aiheen lyhyt kuvaus"/> 

 <column name="j_nimellisarvo" datatype="varchar" length="10" pk="false"  unique="false" default="" nulls="false" autoidentidy="false" fk=""  description="Merkin nimellisarvo, esim. 0,40 + 5"/> 

 <column name="j_valuutta" datatype="integer" length="" pk="false"  unique="false" default="" nulls="false" autoidentidy="false" fk="va_id"  description="Merkin valuutta, esim. 3"/> 

 <column name="j_vari" datatype="integer" length="" pk="false" unique="false"  default="" nulls="false" autoidentidy="false" fk="v_id" description="Merkin  väri(t)"/> 

 <column name="j_painos" datatype="integer" length="" pk="false" unique="false"  default="" nulls="false" autoidentidy="false" fk="" description="Julkaisun  painos"/> 

 <column name="j_ensipaiva" datatype="date" length="" pk="false" unique="false"  default="" nulls="false" autoidentidy="false" fk="" description="Ensipäivä,  esim. 15.5.1940"/> 

 <column name="j_arvopt" datatype="float" length="" pk="false" unique="false"  default="" nulls="false" autoidentidy="false" fk="" description="Arvo  postituoreena, esim. 2,50"/> 

 <column name="j_arvole" datatype="float" length="" pk="false" unique="false"  default="" nulls="false" autoidentidy="false" fk="" description="Arvo  leimattuna, esim. 2,50"/> 

 <column name="j_kuva" datatype="varchar" length="50" pk="false" unique="false"  default="" nulls="false" autoidentidy="false" fk="" description="Merkin kuvan  nimi / polku"/> 

 </table> 

  </db> 

    

Datan konvertoiminen tietokannasta XML-muotoon

Web-sovelluksissa kaikki rakenteellinen tieto kannattaa tallentaa tietokantaan. Projektin tavoitteena on kehittää menetelmä, jonka avulla sovellukset, joissa ei ole mahdollisuutta suoraan tietokantayhteyteen, voivat käsitellä ja esittää tietokannassa olevaa sisältöä XML:n kautta. Yleinen esimerkki tästä ovat mobiili- tai selainkäyttöliittymät, joiden kautta tietokannassa olevaa dataa halutaan tarjota; kumpikaan ei sisällä mahdollisuutta suoraan tietokantayhteyteen, mutta molemmat pystyvät lukemaan XML-muotoista dataa /tietovirtaa.

Aiemmassa vaiheessa määrittelimme XML-datan rakenteen, seuraavaksi haemme tietokannasta siihen sopivaa dataa.

Useimmissa ohjelmointikielissä prosessi etenee seuraavasti:

  1. Avaa tietokantayhteys (katso esimerkit tietokantayhteyden luomisesta PHP:n kautta)
  2. Suorita haluttu SQL-kysely (katso esimerkit SQL-kyselystä PHP-kielellä)
  3. Tulosta tulosjoukko - normaalisti tulosjoukko sijoitetaan HTML-rakenteen sisään, mutta tässä tapauksessa tulosjoukon arvot sijoitetaankin XML-rakenteen sisään.

Seuraava PHP-esimerkki näyttää, miten tietokannasta haettu data muunnetaan XML-muotoon:

<?php 
echo ("<?xml version="1.0" encoding="ISO 8859-1"?>" . "\n");

// Avataan tietokantayhteys
mysql_connect("palvelimen_osoite","kayttajatunnus","salasana");  

// Valitaan tietokanta
mysql_selectdb("dbStamps");

// Suoritetaan haku tietokannasta
// tallennetaan tulokset muuttujaan $result
$SQL = "SELECT SQL_CACHE j_id,j_luettelonro, j_vuosi....";
$result = mysql_query($SQL);	

// tarkistetaan onko tuloksia
if (mysql_num_rows($result)) {
	echo ("<julkaisut>");
	// käydään tulosjoukko lävitse
    	while ($row = mysql_fetch_object($result, MYSQL_BOTH)) {
		echo "<julkaisu>";
		echo "<j_id>$row->j_id</j_id>";
		echo "<j_luettelonro>$row->j_luettelonro</j_luettelonro>";
		echo "<j_vuosi>$row->j_vuosi</j_vuosi>";
		echo "<j_nimellisarvo>$row->j_nimellisarvo</j_nimellisarvo>";
		echo "<j_valuutta>$row->j_valuutta</j_valuutta>";
		echo "<j_aihe>$row->j_aihe</j_aihe>";
		echo "<j_kuvaus>$row->j_kuvaus</j_kuvaus>";
		echo "</julkaisu>";
    	}
	echo ("</julkaisut>");	}
}

XML-skeema datalle

PHP-esimerkin tuottama XML-data voi näyttää esimerkiksi tältä:

<?xml version="1.0" encoding="ISO 8859-1"?>
<julkaisut>
 	<julkaisu>
 		<j_id>29</j_id>
 		<j_luettelonro> 20</j_luettelonro>
 		<j_vuosi>1885</j_vuosi>
 		<j_nimellisarvo>5</j_nimellisarvo>
 		<j_valuutta>penniä</j_valuutta>
 		<j_aihe> M 1885</j_aihe>
 		<j_kuvaus>Suomen kansallisvaakuna. Leijonan kilvessä 8 tähteä, kolme jalkaa sapelilla.</j_kuvaus>
 	</julkaisu>
 	<julkaisu>
 		<j_id> 30</j_id>
 		<j_luettelonro>21</j_luettelonro>
 		<j_vuosi>1885</j_vuosi>
 		<j_nimellisarvo>10</j_nimellisarvo>
 		<j_valuutta>penniä</j_valuutta>
 		<j_aihe> M 1885</j_aihe>
 		<j_kuvaus>Suomen kansallisvaakuna. Leijonan kilvessä 8 tähteä, kolme jalkaa sapelilla.</j_kuvaus>
 	</julkaisu>
 </julkaisut>
    

Seuraavaksi luodaan skeema kyseiselle datalle. Tätä varten julkaisut-juurielementtiin on lisättävä attribuutit, jotka määrittävät skeeman sijainnin. Tämä lisäys tehdään XML:n tulostuskoodissa, eli tässä tapauksessa PHP:ssä:

 <julkaisut xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance" xsi:noNamespaceSchemaLocation="projekti.xsd">

Skeema-tiedoston (projekti.xsd) sisältö on yksinkertainen:

 <?xml version="1.0" encoding="UTF-8"?>
 <xsd:schema xmlns:xsd="http://www.w3.org/2000/10/XMLSchema" elementFormDefault="qualified">

 	<xsd:element name="j_aihe" type="xsd:string"/>
 	<xsd:element name="j_id" type="xsd:string"/>
 	<xsd:element name="j_kuvaus" type="xsd:string"/>
 	<xsd:element name="j_luettelonro" type="xsd:string"/>
 	<xsd:element name="j_nimellisarvo" type="xsd:byte"/>
 	<xsd:element name="j_valuutta" type="xsd:string"/>
 	<xsd:element name="j_vuosi" type="xsd:short"/>

 	<xsd:element name="julkaisu">

 		<xsd:complexType>
 			<xsd:sequence>
 				<xsd:element ref="j_id"/>
 				<xsd:element ref="j_luettelonro"/>
 				<xsd:element ref="j_vuosi"/>
 				<xsd:element ref="j_nimellisarvo"/>
 				<xsd:element ref="j_valuutta"/>
 				<xsd:element ref="j_aihe"/>
 				<xsd:element ref="j_kuvaus"/>
 			</xsd:sequence>
 		</xsd:complexType>

 	</xsd:element>

  	<xsd:element name="julkaisut">

  		<xsd:complexType>
 			<xsd:sequence>
 				<xsd:element ref="julkaisu" maxOccurs="unbounded"/>
 			</xsd:sequence>
 		</xsd:complexType>

  	</xsd:element>
 </xsd:schema>
 

Jo pelkästään tässä muodossa data soveltuu hyödynnettäväksi esimerkiksi mobiilisovelluksissa. Jos datan hyödyntämisen haluaa viedä vielä askelen pitemmälle, voi sen muuntaa XSL/XSLT-muunnoksella esimerkiksi HTML- tai PDF-tiedostoiksi.

XSL/XSLT-muunnos datalle

Nyt kun kaikki tarvittavat elementit ovat käsillä, voimme julkaista työmme tuloksen HTML-sivuna. Tämä onnistuu käyttämällä XSL/XSLT-muunnosta XML-datalle. XSL/XSLT-muunnoksen suorittamiseksi XML-dataan on lisättävä seuraava prosessointiohje:

 <?xml-stylesheet type="text/xsl" href="projekti.xsl"?> 

Aihetta on käsitelty tarkemmin XSLT-oppaassa, joten tässä yhteydessä tyydymme tarkastelemaan esimerkin koodia:

  <?xml version="1.0" encoding="UTF-8"?>
 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"> <html xmlns:xsl="http://www.w3.org/TR/WD-xsl"> <head> <title> 2K mediat.com : esimerkki palvelinpuolen xslt muunnoksesta</title> <link href="naytto.css" rel="stylesheet" media="screen" type="text/css"/></head> <body> <div id="print"> <img id="logo" src="logo.jpg" alt="2K mediat.com logo"/> <h1 class="pprint"> www.2kmediat.com</h1> <div id="toc"> <h1 class="paa"> Sisällysluettelo</h1> <h1 class="tocserver"> Suomi postimerkkiluettelo</h1> <p> <xsl:for-each select="julkaisut/julkaisu"> <xsl:value-of select="j_vuosi"/> , <xsl:value-of select="j_aihe"/> <br/> <br/> </xsl:for-each> </p> </div> <xsl:for-each select="julkaisut/julkaisu"> <h1 class="paa"> <xsl:value-of select="j_aihe"/> </h1> <p class="desc"> <b> Numero : </b> <xsl:value-of select="j_luettelonro"/> </p> <p class="desc"> <b> Nimellisarvo: </b> <xsl:value-of select="j_nimellisarvo"/> <xsl:value-of select="j_valuutta"/> </p> <p class="desc"> <b> Kuvaus: </b> <xsl:value-of select="j_kuvaus"/> </p> <hr/> </xsl:for-each> </div> </body> </html> </xsl:stylesheet>