XML og XSLT med Active Server Pages

Microsofts scriptingmiljø på IIS-webserveren byder på robust understøttelse af XML og sprogets følgeteknologier. I denne artikel vises der, hvorledes disse standarder kan udnyttes til at skabe fornuftig separering imellem præsentation, logik og data.

Separering

Microsoft er vældig glad for XML-teknologierne. Det ses blandt andet i firmaets webarkitektur, .Net, som i stor udstrækning bygger på XML og dets følgeteknologier. Men XML giver også masser af mening uden .Net, og i særdeleshed i forbindelse med publicering af data til webbet og andre internetbaserede informationssystemer. De teknikker, der anvendes her i artiklen, bygger i øvrigt på standarder, som også findes i andre programmeringsmiljøer, for eksempel Java. Også dem, der ikke dagligt omgås ASP, burde kunne få noget ud af artiklens eksempel.

På webbet, og i mange andre klient/server-informationssystemer, kan et system eller en applikation separeres i tre dele: Præsentation, logik og data.

Præsentation henfører til systemets grænseflade beregnet til de mennesker, som benytter systemet. Selv om navnet ikke lige siger det, dækker det også over de brugere, som skal putte data ind i systemet.

Logik er de regler, som sammensætter og processerer information, og det er som regel den programmeringskode, der ligger under systemet. Det kan for eksempel også være XSLT, som specificerer hvorledes XML-data kan transformeres til nye sæt af XML-data ved hjælp af en XSLT-processor.

Data giver sig selv: Det er de data, som tilsammen giver de informationer, som brugerne kan udtrække af systemet. Men måden data organiseres på er ikke givet på forhånd. Den almindelige måde at gemme data er at benytte en relationsdatabase, men man skal være opmærksom på, at den måde, man vælger at organisere sine data på, har stor betydning for, hvorledes data kan processeres. Datamodellen har en høj grad af indflydelse på, hvorledes logikken kommer til at se ud, og det kan give et problem: Hvis der er behov for at ændre på datamodellen, kan det resultere i, at der skal foretages store ændringer i logikken.

Der findes andre måder at organisere sine data på end den model, som gives af en relationsdatabase, og XML er en af dem. XML kan give en større grad af frihed i mellem datalag og logik, og på den måde kan applikationens forskellige dele gives en større grad af indbyrdes fleksibilitet end ellers. I mellem logiklaget og præsentationsdelen kan XML også give håndfaste fordele. Ved hjælp af XML-skabeloner, XSLT, kan de færdige data præsenteres på mange forskellige måder til forskellige typer af slutmedier.

Når præsentation, logik og data separeres, bliver det nemmere at foretage ændringer på et af områderne, uden samtidig at skulle ændre på de andre dele. Da det som regel også er forskellige personer, som betjener hver enkelt del, er der også bedre økonomi i separering, da brugerfladedesigneren så at sige ikke behøves at sidde på skødet af programmøren for at udføre sin opgave.

Eksemplet

Eksemplet
I dette simple eksempel vil vi hente data fra forskellige kilder, sætte dem sammen og transformere disse data til god, gammeldags HTML-kode, som en browser kan læse.

Det er der ikke noget sindsoprivende i - eksemplet er faktisk ganske rudimentært. Pointen med dette eksempel er, at en stor del af applikationen er sprog-uafhængigt - den fungerer lige godt i det ene miljø som i det andet.

Den sparsomme kode, som findes i eksemplet, bygger på manipulation af XML-ark via DOM - dokument objekt-modellen. Denne model specificerer et standardiseret API til XML-dokumenter, og den ser altså ens ud, uanset om man benytter ASP, Java eller et andet programmeringsmiljø, som understøtter XML og DOM. DOM hører til i World Wide Web-konsortiets regi og er bredt understøttet som den gængse måde at processere XML-dokumenter programmatisk. Og så er DOM let at forstå og anvende. Ved at benytte DOM bliver koden portabel i højere grad - og når man først har lært teknikkerne, kan de som sagt benyttes i et stort antal programmeringsmiljøer.

Microsofts implementering af DOM er udmærket dokumenteret på Microsoft Developer Network.

Tre flade filer i kodekassen
I dette eksempel, der som sagt er ganske simpelt, henter vi en række XML-filer, der til sammen skal udgøre det færdige dokument, som vi så vil processere med en skabelon og sende til en browser.

Alle filerne kan ses her.

Den første XML-fil indeholder blot stien til de filer, som skal benyttes. I en mere virkelighedsnær situation kunne det være en mere generel angivelse af de datakilder, der skal anvendes.

Filen inputfiler.xml ser således ud:

<?xml version="1.0"?>
<inputkilder>
  <header>
    <fil>header.xml</fil>
  </header>
  <navigation>
    <fil>navigation.xml</fil>
  </navigation>
  <content>
    <fil>content.xml</fil>
  </content>
</inputkilder>

Tekstnoden i <fil>-elementet angiver stien til det dokument, som skal indsættes mellem de andre elementer. På den måde får vi både indhold og den sammenhæng, som indholdet indgår i.

Et lille script

Nu skriver vi et lille script, som indlæser inputfiler.xml, henter de specificerede filer og genererer et nyt XML-dokument af de tre filer. Det er ganske nemt. Først skal den seneste version af Microsofts XML-parser installeres, og det kræver blot at man installerer et lille program, som kan downloades fra Microsoft Developer Network. Den nyeste version hedder 4.0, her i eksemplet benyttede vi version 3, men det burde nu ikke betyde noget.

<SCRIPT LANGUAGE="JSCRIPT" RUNAT="SERVER">

var inputFilListe = "inputfiler.xml";

var xmlDoc = Server.CreateObject("MSXML2.DOMDocument.3.0");
xmlDoc.async = false;
xmlDoc.load(Server.MapPath(inputFilListe));

function hentData() {
  var nodeListe = xmlDoc.selectNodes("//fil/text()");
  for(var i=0; i<nodeListe.length; i++) {
    var aktuelNode = nodeListe.item(i);
    
    var indholdsFil = aktuelNode.nodeValue;

    var xmlIndhold = Server.CreateObject("MSXML2.DOMDocument.3.0");
    xmlIndhold.async = false;
    xmlIndhold.load(Server.MapPath(indholdsFil));

    var xmlIndholdRodNode = xmlIndhold.selectSingleNode("*");
    var moderNode = aktuelNode.parentNode.parentNode;
    moderNode.appendChild(xmlIndholdRodNode);
    
  }

  Response.write(xmlDoc.xml);
  
}

hentData();

</SCRIPT>

I de første par linjer opretter vi et XML-dokumentobjekt. Egenskaben async bestemmer, om scriptet skal fortsætte, selv om filen kun er delvist indlæst, hvilket kan være nyttigt, hvis den hentes fra en fjern kilde. Her sættes den til falsk, da vi blot læser en fil fra harddisken.

Metoden load indlæser XML-filen i vores objekt xmlDoc. Disse tre linjer går igen, hver gang vi skal oprette et XML-dokumentobjekt.

Funktionen hentData() skal nu indsætte de dokumenter, som er specificeret i inputfiler.xml, inde i selve XML-arket. Den første linje

var nodeListe = xmlDoc.selectNodes("//fil/text()");

genererer en liste af noder, elementer i XML-dokumentet, ud fra det kriterie, som er angivet i streng-argumentet. Streng-argumentet er et såkaldt XPath-udtryk. XPath er en standard til at navigere rundt i XML-dokumenter med. XML-dokumenter er træstrukturer, ligesom websider, og XPath minder meget om de adresser, man benytter på web. Denne artikel kan desværre ikke gå i dybden med XPath, men udtrykket her, "//fil/text()", betyder: Find alle tekst-noder, der befinder sig under et <fil>-element. Det giver os de tre filnavne i inputfiler.xml som resultat.

Derefter har vi en løkke, som gennemløber listen. Linjen

var indholdsFil = aktuelNode.nodeValue;

sætter variablen indholdsFil til det filnavn, som er angivet i hver af fil-elementerne i inputfiler.xml.

De næste tre linjer har vi set før - de indlæser det XML-dokument, hvis filnavn vi lige har udtrukket af inputfiler.xml, og gemmer det i objektet xmlIndhold.

Nu skal vi indlejre det XML-dokument, vi netop har indlæst, med det XML-dokument, som vi arbejder med. Vi indlæser xmlInhold som en node, et deltræ om man vil, i linjen

var xmlIndholdRodNode = xmlIndhold.selectSingleNode("*");

Ligesom tidligere finder vi her vores node ved hjælp af XPath. Argumentet "*" (asterisk) betyder blot "alle elementer".

Nu skal vi indsætte det nye træ i det gamle. I det gamle dokument peger vores variabel aktuelNode på en tekstnode (vores filnavn fra før), så vi skal bakke tilbage i træet, til vi lander i elementet lige før <fil>. Vi skal altså finde aktuelNode's oldeforældre. Og det er jo forældrenodens forældrenode:

var moderNode = aktuelNode.parentNode.parentNode;

Og så tilføjer vi det nye træ i det gamle:

moderNode.appendChild(xmlIndholdRodNode);

På ydersiden af løkken tester vi nu, hvad vi egentlig fik ud af det hele, med linjen

Response.write(xmlDoc.xml);

Det kunne godt se ud som om det var et filnavn, der står som argument, men det er det ikke. Det er xmlDoc-objektet, udskrevet som xml-tekst. Og det ser sådan ud, i Internet Explorer:

Det færdige XML-dokument. Dokumentet indeholder kun struktur og ingen præsentationselementer.

Nu har vi alle de elementer, vi skal bruge for at opbygge hele siden, i vores XML-dokument. Nu kan vi så opbygge de dokumenter, der skal sendes til klienterne. Man kunne forestille sig en skabelon til gamle browsere, en til nye browsere, en som genererer WML-sider til WAP-telefoner og meget mere.

Stil

Stil skal der til
Det næste skridt er altså at formatere vores XML. Her bruger vi blot en enkel skabelon, som genererer almindelig HTML-kode. Det gøres med XSLT, og det har vi gennemgået i en tidligere artikel her på kanalen.

Selve scriptet er lige ud af landevejen:

function transformerOgUdskriv() {
  var xsltSkabelon = "stylesheet.xsl";

  var xmlStylesheet = Server.CreateObject("MSXML2.DOMDocument.3.0");
  xmlStylesheet.async = false;
  xmlStylesheet.load(Server.MapPath(xsltSkabelon));
  
  var strValue = xmlDoc.transformNode(xmlStylesheet);

  Response.write(strValue);

}

Vi indlæser XSLT-dokumentet på samme vis som de øvrige XML-dokumenter. Så er det blot at benytte metoden transformNode på vores xmlDoc-objekt fra før og udskrive resultatet til browseren.

Så får vi dette resultat:

Kønt er det ikke, så vi fjerner den grimme tabelramme ved at modificere en anelse i XSLT-arket, og så smækker vi et CSS-stylesheet oven i hatten:

Der kan nørkles videre med XSLT- og CSS-ark - men det kræver ikke ændringer i programkoden. Og bare rolig - teknologien kan også klare æ, ø og å.

XML løser ikke alle problemer, men forhåbentlig gav eksemplet indtryk af, at man kan opnå en hel del med få linjers kode og med en høj grad af separering af præsentation, logik og data.




Brancheguiden
Brancheguide logo
Opdateres dagligt:
Den største og
mest komplette
oversigt
over danske
it-virksomheder
Hvad kan de? Hvor store er de? Hvor bor de?
Advania Danmark A/S
Hardware, licenser, konsulentydelser

Nøgletal og mere info om virksomheden
Skal din virksomhed med i Guiden? Klik her

Kommende events
AI i det offentlige: Potentiale, erfaringer og krav

Hør erfaringerne med at anvende AI til at transformere og effektivisere processer i det offentlige – og med at sikre datakvalitet, governance og overholdelse af retningslinjer.

27. august 2025 | Læs mere


Computerworld Cloud & AI Festival 2025

Med den eksplosive udvikling indenfor cloud & AI er behovet for at følge med og vidensdeling større end nogensinde før. Glæd dig til to dage, hvor du kan netværke med over 2.400 it-professionelle, møde mere end 50 it-leverandører og høre indlæg fra +90 talere. Vi sætter fokus på emner som AI; infrastruktur, compliance, sikkerhed og løsninger for både private og offentlige organisationer.

17. september 2025 | Læs mere


IT og OT i harmoni: Sikring uden at gå på kompromis med effektiviteten

IT og OT smelter sammen – men med risiko for dyre fejl. Få metoder til sikker integration med ERP, kundesystemer og produktion. Tilmeld dig og få styr på forskellene og faldgruberne.

24. september 2025 | Læs mere