vorige: Website bouwen met Joomla!

IMS-contentpackage vanuit een Access database

volgende: Oh, what a beautifull morning...

gepost: 14 februari 07 om 23:40u

Ik heb vandaag mijn eerste zelfgegenereerde IMS-contentpackage in N@tschool weten te importeren en tot studieroute weten om te zetten.
Zelfgegenereerd omdat zowel bijna alle ruim 200 html-bestanden als het bijbehorende imsmanifest.xml zijn gecreeerd met behulp van een Access-database en een paar VBA-scriptjes.
Omdat de hierbij toegepaste techniek redelijk universeel toepasbaar is bij het maken van een grote reeks XML- of html-bestanden (of een groot samengesteld bestand als een manifest) in deze post wat meer uitleg over de gevolgde werkwijze.


De uitdaging

Bij datgene wat ik vandaag gemaakt heb (waarvan ik het eindresultaat helaas niet kan laten zien) ging het om een hele reeks (links naar) korte instructiefilmpjes. Alle metadata (titel, omschrijving, url) staan in een database. Gevraagd: voor elk filmpje een html-pagina te maken met daarin een overzichtelijke presentatie van de gegevens + een embedded mediaspeler waarop het filmpje kan worden afgespeeld. Het geheel te presenteren als studieroute in N@tschool, bij voorkeur met gebruikmaking van de standaard Natschool-navigatiestructuur.

Navigatiestructuur = IMS-contentpackage

Het probleem de uitdaging van de navigatiestructuur kan opgelost worden door aan de set html-bestanden een IMS-manifest toe te voegen. Dat is een XML-document waarin vastgelegd is wat voor bestanden er precies inzitten, wat de resources zijn (de als afzonderlijke eenheid te benaderen onderdelen)  en welke hulpbestanden daarbij horen (afbeeldingen, stylesheets etc). Verder kun je in het manifest de onderlinge samenhang (zeg maar de sitemap) bepalen in het onderdeel 'organisation'.

Overzicht gebruikte werkwijze

Om de gewenste bestanden te kunnen genereren zijn de volgende componenten nodig
Het script opent een tekstbestand voor schrijven, plaatst daar eerst de heading-regels in, vervolgens wordt voor elk record in de gegevenstabel een 'opgemaakt' stuk tekst gegenereerd waarna tenslotte de afsluitende 'footing'-regels worden toegevoegd.
Indien gewenst kan per (hoofd)record nog een aantal subrecords worden aangemaakt.

De tabelstructuren

Hieronder een overzicht van de structuur van de tabel met onveranderlijke gegevens.
De kolom 'gebruik' wordt in het VBA-script gebruikt om onderscheid te maken tussen het gedeelte wat aan het begin van het document moet komen en het gedeelte op het eind.
Deze tabel laat zich gemakkelijk aanmaken in Access door een voorbeeldbestand te hernoemen in .txt en het vervolgens te importeren in Access. Extra kolom toevoegen en Klaar is Kees.

vaste gegevens
Nr gebruik Tekst
10 start [?xml version="1.0" encoding="utf-8"?]
20 start [manifest identifier="IMSMANIFEST" version="1.1" xmlns="http://www.imsglobal.org/xsd/imscp_v1p1" xmlns si="http://www.w3.org/2001/XMLSchema-instance"
21 start xsi:schemaLocation="http://www.imsglobal.org/xsd/imscp_v1p1
22 start http://www.imsglobal.org/xsd/imscp_v1p1.xsd"]
30 start [metadata]
40 start [schema]IMS Content[/schema]
50 start [schemaversion]1.1[/schemaversion]
60 start [/metadata]
70 start [organizations default=""]
80 start [organization identifier="" structure="hierarchical"]
90 start [title]Overzicht[/title]
100 start [item identifier="Main_Overzicht" isvisible="true" identifierref="Main_overzicht"]
110 start [title]Overzicht[/title]
120 eindsub [/item]
180 resources [/item]
370 resources [/organization]
380 resources [/organizations]
390 resources [resources]
2760 eind [resource identifier="Main_Overzicht" type="webcontent" href="PMed_NasWS_index.htm"]
2770 eind [file href="_index.htm" /]
2780 eind [file href="voorbeeld.css" /]
2790 eind [file href="player.js" /]
2795 eind [/resource]
2800 eind [/resources]
2810 eind [/manifest]

De tabel met template voor variabele gegevens

De tabel die de template vormt voor de variabele gegevens bestaat uit 7 kolommen.
De structuur is simpel: het veld 'begin' bevat het begin van de af te drukken regel, dan staat in veldnm1 de naam van het veld uit de gegevenstabel, er is ruimte voor een 'tussentekst', eventueel kan een tweede veldnaam worden opgegeven en tenslotte de sluittekst (of -tag).
template voor variabele gegevens
nr gebruik begin veldnm1 tussen veldnm2 eind
130
[item identifier=" ref " isvisible="true" identifierref=" ref "]
140
[title] ondertitel

[/title]
Door twee veldnamen te gebruiken kun je de meest voorkomende regels html of xml code genereren. Ik heb deze methodiek inmiddels voor een hele reeks toepassingen gebruikt en heb eigenlijk nog nooit meer dan twee velden nodig gehad. Als je er meer nodig hebt dan kun je meestal ook wel meerdere regels gebruiken.

VBA-script: onderdeel MaakXMLBestand

In onderstaand voorbeeld wordt eerst de aanmaak van het IMS-manifest besproken. Hierbij gaat het om één bestand (imsmanifest.xml) met hoofd- en subsecties.
Sub MaakXMLBestand()

Dim strBasisPad As String
Dim bestandsnaam As String
Dim Handle As Byte

strBasisPad = "\pad\naar\het\bestand\"
bestandsnaam = "imsmanifest.xml"
Handle = FreeFile
Open strBasisPad & bestandsnaam For Output As #Handle
'beginregels afdrukken
DrukVasteTekstAf Handle, "start"
Print #Handle, ""
'organisation
MaakDeelXML Handle, SVH_main:="Qry_banden", SVH_XML_main:="Manifest_XML_main", _
            SVH_sub:="qry_fragm", SVH_XML_sub:="Manifest_XML_sub"
Print #Handle, ""
'start van resources
DrukVasteTekstAf Handle, "resources"
'overzichtspagina's
MaakDeelXML Handle, SVH_main:="Qry_banden", SVH_XML_main:="resources_XML_main"
Print #Handle, ""
'afzonderlijke fragmentpagina's
MaakDeelXML Handle, SVH_main:="Qry_fragm", SVH_XML_main:="resources_XML_main"

'eindregels afdrukken
DrukVasteTekstAf Handle, "eind"
Close #Handle

End Sub
In de code worden een aantal keren de subroutines "DrukVasteTekstAf" en "MaakDeelXML" aangeroepen. Op die manier wordt achtereenvolgens de "organisations" en de "resources" sectie aangemaakt.

VBA-sript: DrukVasteTekstAf

Private Sub DrukVasteTekstAf(handle2 As Byte, strDeel As String)
'wordt opgeroepen vanuit MaakXMLbestand
Dim strSQL As String
Dim XmlRst As Recordset
strSQL = "SELECT Manifest_XML_vast.* From Manifest_XML_vast " _
        & "WHERE (((Manifest_XML_vast.gebruik)=""" & strDeel & """)) " _
        & "ORDER BY Manifest_XML_vast.nr"
'Debug.Print strSQL

Set XmlRst = CurrentDb.OpenRecordset(strSQL, dbOpenForwardOnly)
With XmlRst
    Do Until .EOF
    Print #handle2, .Fields("tekst")
    .MoveNext
    Loop
End With

End Sub
Rechttoe, rechtaan: er wordt een query gedefinieerd met als selectiecriterium het veld "gebruik". Vervolgens wordt het veld 'tekst' regel voor regel afgedrukt.

VBA-script: MaakDeelXML

Sub MaakDeelXML(handle1 As Byte, _
        SVH_main As String, _
        SVH_XML_main As String, _
        Optional SVH_sub As String = "GEENSUB", _
        Optional SVH_XML_sub As String)
Dim strSQL As String
Dim SubDataRst As Recordset
Dim DataRst As Recordset
Dim strresult As String

strSQL = "SELECT " & SVH_main & ".* FROM " & SVH_main _
        & " ORDER BY " & SVH_main & ".volgnr"


Set DataRst = CurrentDb.OpenRecordset(strSQL, dbOpenForwardOnly)
With DataRst
    Do Until .EOF
    'Debug.Print strSQL
        'main-gedeelte afdrukken
        DrukRecordAf handle1, DataRst, SVH_XML_main
        If SVH_sub <> "GEENSUB" Then
            'sub-gedeelte afdrukken
            strSQL = "SELECT " & SVH_sub & ".* FROM " & SVH_sub & " " _
                        & "WHERE (((" & SVH_sub & ".volgnr)=" & .Fields("volgnr") _
                        & "))"
            Set SubDataRst = CurrentDb.OpenRecordset(strSQL, dbOpenForwardOnly)
            If SubDataRst.RecordCount > 0 Then
                Do Until SubDataRst.EOF
                    Print #handle1, ""
                    DrukRecordAf handle1, SubDataRst, SVH_XML_sub
                    SubDataRst.MoveNext
                Loop
            End If
            DrukVasteTekstAf handle1, "eindsub"
        End If
        Print #handle1, ""
        DataRst.MoveNext
    Loop
End With

End Sub
In dit script worden 4 parameters meegegeven:
Vervolgens wordt de gegevenstabel van het hoofdrecord stuk voor stuk doorgelopen waarbij eerst het hoofdrecord wordt afgedrukt (met drukRecordAf) en vervolgens in een loop het subrecord wordt doorlopen.
Na het subrecord wordt indien nodig nog een aantal vaste regels afgedrukt ter afsluiting van het subrecord.
Iets wat je handmatig in het VB-script zal moeten aanpassen is het selectiecriterium in het subrecord. Zowel de gegevenstabel van het hoofdrecord als die van het subrecord zullen een overeenkomstig veld moeten hebben waarop geselecteerd kan worden.

VBA-script: DrukRecordAf

Sub DrukRecordAf(handle2 As Byte, DataRst As Recordset, strBasis As String)
Dim XmlRst As Recordset
Dim strSQL As String
Dim strresult As String, result As Variant
Dim tlr As Long

    strSQL = "SELECT " & strBasis & ".* FROM " & strBasis & " ORDER BY " & strBasis & ".nr"
   
    Set XmlRst = CurrentDb.OpenRecordset(strSQL, dbOpenForwardOnly)
    With XmlRst
        Do Until .EOF
            strresult = ""
            For tlr = 2 To 6
                If .Fields(tlr).Value <> "" Then
                    If .Fields(tlr).Name Like "veldnm*" Then
                        strresult = strresult & DataRst.Fields(.Fields(tlr).Value)
                    Else
                        strresult = strresult & .Fields(tlr).Value
                    End If
                    'Debug.Print strresult
                End If
            Next tlr
            Print #handle2, strresult
            .MoveNext
        Loop
    End With

End Sub

Hier wordt de regels met variabele gegevens gecreerd. De template wordt regel voor regel doorlopen waarbij stap voor stap de inhoud van veld 2 t/m 6 aan elkaar wordt geplakt. Als de naam van het veld begint met "veldnm" dan wordt niet de tekst van het veld maar het bijbehorende veld uit de gegevenstabel opgehaald.

Losse XML/HTML-bestanden

In bovenstaand voorbeeld wordt zoals gezegd één groot bestand gemaakt bestaande uit meerdere records die ieder weer een aantal onderrecords kunnen hebben.
Wanneer je een reeks losse html-bestanden wilt maken zul je meestal per hoofdrecord één bestand willen hebben met eventueel wat onderrecords.
De structuur van bovenstaand VBA-script verandert dan in die zin dat de query die alle records stuk voor stuk doorloopt zal verhuizen van MaakDeelXML naar de hoofdroutine MaakXMLbestand. Inplaats van een vaste bestandsnaam zal dan een veld uit de query worden opgegeven.
Voor deze tpepassing is geen gebruik gemaakt van subrecords en zijn voor het gemak alle templateregels in  één bestand gezet.  In dat geval kan volstaan worden met onderstaand VBA-script:
Sub MaakSetBestanden()
MaakBestand "mypag"
End Sub

Sub MaakBestand(typeBestand As String)
Dim DataRst As Recordset
Dim XmlRst As Recordset
Dim strPadNaam As String
Dim Handle As Byte
Dim strresult As String
Dim tlr As Long

Handle = FreeFile
strPadNaam = strBasisPad
Set DataRst = CurrentDb.OpenRecordset("qry_" & typeBestand, dbOpenForwardOnly)
Set XmlRst = CurrentDb.OpenRecordset(typeBestand & "Basis", dbOpenDynaset)

Do Until DataRst.EOF
    Open strPadNaam & DataRst.Fields("Htmtitel") For Output As #Handle

    With XmlRst
        .MoveFirst
        Do Until .EOF
            strresult = ""
              For tlr = 1 To 5
                If .Fields(tlr).Value <> "" Then
                    If .Fields(tlr).Name Like "veldnm*" Then
                        strresult = strresult & DataRst.Fields(.Fields(tlr).Value)
                    Else
                        strresult = strresult & .Fields(tlr).Value
                    End If
                End If
              Next tlr
            Print #Handle, strresult
            .MoveNext
        Loop
    End With
    Close #Handle
  DataRst.MoveNext
Loop

End Sub
Dit script maakt gebruik van tabel en querynamen die aan een bepaalde structuur moeten voldoen. De template tabel heet 'typebestandbasis' en de gegevensquery 'qy_typebestand'. Op die manier kan de procedure MaakSetBestanden een hele reeks soorten pagina's achter elkaar laten maken.

Toepasbaarheid

Ik heb de database + bijbehorende scripts inmiddels al de nodige keren met succes toegepast. Zo gebruik ik het bijvoorbeeld voor het genereren van modulebeschrijvingen (html-pagina's) en het aanmaken van het XML-upload document voor de videotheekdienst van Surfnet.

Er zijn uiteraard andere wegen om hetzelfde doel te bereiken. Een webapplicatie met PHP en MySQL ligt voor de hand en je zou ook aan een XSLT-transformatie kunnen denken.  De reden dat ik voor Access + VBA heb gekozen is dat ik goed thuis ben in Access en daar precies de queryresultaten kan bereiken die ik nodig heb. En datzelfde geldt voor VBA, in ieder geval voor wat betreft de koppeling met Access-tabellen.
Categorie: ELO - tags: natschool, edublogs, ims-contentpackage, ims
3355 views -
Trackback
There are currently no trackbacks for this item.
Gebruik van 'Trackback' is vanwege spam-aanvallen helaas niet meer mogelijk.

Reacties

Nog geen reacties

Voeg reactie toe...



uit het fotoarchief