Einlesen von XML-Dateien mit DOMAccess bietet mit steigender Versionsnummer mehr und mehr Möglichkeiten zum Import und Export von Daten im XML-Format. Wenn es allerdings um den Import von Daten aus einer XML-Datei in eine bestehende Datenstruktur handelt, helfen die automatisierten Importmöglichkeiten nur bedingt weiter. In dem Fall ist Handarbeit angesagt, und dabei hilft Ihnen unter VBA das Objektmodell DOM. BeispieldatenbankDie Beispieldatenbank enthält zwei Tabellen namens tblProjekte und tblProjektphasen sowie ein Modul mit den beschriebenen Funktionen. Außerdem finden Sie in der ZIP-Datei die Datei beispiel.xml.

DOM verfügbar machenUm mit DOM (Abkürzung für das XML-Document Object Model) in VBA zu arbeiten, müssen Sie zunächst die entsprechende Bibliothek verfügbar machen. Dazu wechseln Sie zunächst in den VBA-Editor und zeigen dann mit dem Menüeintrag Extras/Verweise den Dialog Verweise an. Hier wählen Sie einen der vorhandenen Einträge Microsoft XML aus. Öffnen eines XML-DokumentsBevor Sie die Daten in einem XML-Dokument lesen können, müssen Sie es zunächst öffnen. Die folgende Prozedur lädt ein XML-Dokument mit dem per Parameter übergebenen Dateinamen und ruft eine weitere Funktion namens XMLEinlesen auf, die zum Verarbeiten des Inhalts des XML-Dokuments dient:
Public Function XMLOeffnen(strDateiname As String)
Dim MSXML As New MSXML2.DOMDocument
With MSXML
.async = False
.preserveWhiteSpace = False
.validateOnParse = True
.resolveExternals = False
End With
If MSXML.Load(strDateiname) = True Then
XMLOeffnen = XMLEinlesen(MSXML)
Else
XMLOeffnen = 0
End If
End Function Einlesen des XML-DokumentsDie nachfolgenden Beschreibungen beziehen sich auf die Datei Beispiel.xml, die sich mit der Beispieldatenbank in der oben zum Download bereitstehenden ZIP-Datei befindet. Die XML-Datei hat den folgenden Inhalt:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<projekte>
<projektbezeichnung>Beispielprojekt 1</projektbezeichnung>
<projektstart>1.1.2004</projektstart>
<projektende>31.1.2004</projektende>
<projektleiter>Andre Minhorst</projektleiter>
<projektphasen>
<projektphase projektphaseID="1">
<projektphasenbezeichnung>Beispielphase 1</projektphasenbezeichnung>
<projektphasenstart>1.1.2004</projektphasenstart>
<projektphasenende>10.1.2004</projektphasenende>
</projektphase>
<projektphase projektphaseID="2">
<projektphasenbezeichnung>Beispielphase 2</projektphasenbezeichnung>
<projektphasenstart>11.1.2004</projektphasenstart>
<projektphasenende>20.1.2004</projektphasenende>
</projektphase>
</projektphasen>
<!--...weitere Projekte...-->
</projekte>
Die Beispieldatenbank enthält zwei Tabellen namens tblProjekte und tblProjektphasen. Den Aufbau der Tabellen zeigt Abbildung 1. In den nachfolgenden Schritten wird eine Funktion erstellt, die zum Parsen der XML-Datei und dem Eintragen der Informationen in die Tabellen der Datenbank dient.
Abbildung 1: Aufbau der Beispieltabellen Ausgeben aller DatenWenn Sie einfach alle Daten hintereinander ausgeben möchten, erstellen Sie ein neues Objekt, mit dem Sie auf das äußerste, alle anderen Elemente umschließende Element verweisen. Anschließend geben Sie mit der Eigenschaft Text alle untergeordneten Elemente aus:
Public Function XMLEinlesen(objXMLDocument As MSXML2.DOMDocument)
Dim objXMLDocumentElement As Object
Set objXMLDocumentElement = objXMLDocument.documentElement
Debug.Print objXMLDocument.Text
End Function Zugreifen auf bestimmte ElementeUm die Daten des XML-Dokuments einzulesen, wäre es praktisch, auf die einzelnen Elemente des Dokuments zugreifen zu können. Die folgende Funktion gibt alle Elemente des Typs Projekt aus. Dabei verwendet die Funktion die Methode GetElementsByTagName, um der Variablen objXMLChildNodes eine Auflistung der Elemente mit dem gesuchten Namen zuzuweisen.
Diese Auflistung kann dann komfortabel durchlaufen werden. Die Methode Text gibt innerhalb einer Schleife die Werte aller untergeordneten Elemente aus.
Public Function ProjekteAusgeben(strDateiname As String)
Dim objXMLDocument As New MSXML2.DOMDocument
Dim objXMLChildNodes As Object
Dim objXMLChildNode As Object
With objXMLDocument
.async = False
.preserveWhiteSpace = False
.validateOnParse = True
.resolveExternals = False
End With
If objXMLDocument.Load(strDateiname) = True Then
Set objXMLChildNodes = _
objXMLDocument.getElementsByTagName"projekt")
For Each objXMLChildNode In objXMLChildNodes
Debug.Print objXMLChildNode.Text
Next objXMLChildNode
Else
MsgBox objXMLDocument.parseError.reason
End If
End Function Ausgeben von Elementinhalten und -eigenschaftenWesentlich interessanter als die Auflistung aller unterhalb eines bestimmten Elements liegenden Inhalte ist die Ermittlung und Ausgabe von Elementinhalten und Elementeigenschaften.
Mit der nachfolgenden Beispielfunktion lernen einige Anweisungen und Eigenschaften kennen, die zum Auseinandernehmen einer XML-Datei erforderlich sind. Die Funktion öffnet wiederum zunächst das weiter oben beschriebene XML-Beispiel mit den Projektdaten.
Die Projektdaten sind in zwei Ebenen eingeteilt: in Projekte und in die den Projekten zugeordneten Projektphasen. Diese beiden Objekttypen werden durch die Funktion nacheinander durchlaufen.
Die Funktion setzt wiederum über die Variable objXMLDocumentElement einen Verweis auf das äußerste Element der Datei. Dann werden in einer For Next-Schleife alle untergeordneten Elemente durchlaufen. Um den Endpunkt der Schleife festzulegen, ermittelt der Ausdruck objXMLDocumentElement.childNodes.Item(i) die Anzahl der untergeordneten Elemente. Das jeweils aktuelle Element wird in der Variablen objXMLProjekt gespeichert, wobei der Bezug zu dem gewünschten Auflistungselement über die Item-Eigenschaft hergestellt wird.
Nach der Überprüfung, ob es sich bei dem Element um ein Projekt handelt, werden die einzelnen Unterelemente über die Methode selectSingleNode referenziert und deren Wert über die Eigenschaft Text ausgelesen. Auf diese Weise werden die Informationen über die Projektbezeichnung, Projektstart und -ende sowie den Projektleiter ermittelt.
Etwas anders erfolgt der Zugriff auf die ProjektID, die als Eigenschaft des Projekt-Elements selbst gespeichert wird: Der Zugriff erfolgt hier über die Methode getAttribute, die als Parameter den Eigenschaftsnamen erfordert.
Die Projektphasen sind den Projekten untergeordnet. Es kann je Projekt beliebig viele Projektphasen geben, daher sind diese in einem eigenen Knoten aufgelistet. Nach einer Überprüfung, ob der Knoten vorhanden ist, werden die enthaltenen Projektphasen durchlaufen und die Informationen ähnlich wie bereits bei den Projekten ausgegeben.
Public Function ProjekteAusgeben(strDateiname As String)
Dim objXMLDocument As New MSXML2.DOMDocument
Dim objXMLDocumentElement As Object
Dim objXMLProjekt As Object
Dim objXMLProjektphase As Object
Dim objXMLProjektleiter As Object
Dim i As Integer
Dim j As Integer
With objXMLDocument
.async = False
.preserveWhiteSpace = False
.validateOnParse = True
.resolveExternals = False
End With
If objXMLDocument.Load(strDateiname) = True Then
Set objXMLDocumentElement = objXMLDocument.documentElement
For i = 0 To objXMLDocumentElement.childNodes.length - 1
Set objXMLProjekt = objXMLDocumentElement.childNodes.Item(i)
If objXMLProjekt.nodeName = "projekt" Then
Debug.Print "ProjektID: " _
& objXMLProjekt.getAttribute("projektID")
Debug.Print "Bezeichnung: " _
& objXMLProjekt.selectSingleNode("projektbezeichnung").Text
Debug.Print "Leitung: " _
& objXMLProjekt.selectSingleNode("projektleiter").Text
Debug.Print "Start: " _
& objXMLProjekt.selectSingleNode("projektstart").Text
Debug.Print "Ende: " _
& objXMLProjekt.selectSingleNode("projektende").Text
Set objXMLProjektphasen = _
objXMLProjekt.selectSingleNode("projektphasen")
If Not objXMLProjektphasen Is Nothing Then
For j = 0 To objXMLProjektphasen.childNodes.length - 1
Set objXMLProjektphase = _
objXMLProjektphasen.childNodes.Item(j)
If objXMLProjektphase.nodeName = "projektphase" Then
Debug.Print " ProjektphaseID: " _
& objXMLProjektphase.getAttribute("projektphaseID")
Debug.Print " Bezeichnung: " _
& objXMLProjektphase. _
selectSingleNode("projektphasenbezeichnung").Text
Debug.Print " Start: " _
& objXMLProjektphase. _
selectSingleNode("projektphasenstart").Text
Debug.Print " Ende: " _
& objXMLProjektphase. _
selectSingleNode("projektphasenende").Text
End If
Next j
End If
End If
Next i
Else
MsgBox objXMLDocument.parseError.reason
End If
End Function Übernehmen der Daten der XML-Datei in die DatenbankUm die eingelesenen Daten in die Datenbank zu übernehmen, müssen Sie diese lediglich in geeigneter Weise in die beiden Tabellen der Datenbank schreiben. Die folgende Funktion entspricht vom Aufbau her der Funktion ProjekteAusgeben. Sie gibt aber keinerlei Daten im Testfenster aus, sondern schreibt diese direkt in die beiden Tabellen tblProjekte und tblProjektphasen.
Achtung: Die Funktion enthält keinerlei Mechanismen, die das Vorhandensein der ProjektIDs und ProjektphasenIDs überprüfen. Wenn die gleiche ID also zweimal in eine Tabelle geschrieben wird, erzeugt dies einen Fehler.
Public Function ProjekteSchreiben(strDateiname As String)
Dim objXMLDocument As New MSXML2.DOMDocument
Dim objXMLDocumentElement As Object
Dim objXMLProjekt As Object
Dim objXMLProjektphase As Object
Dim objXMLProjektleiter As Object
Dim cnn As ADODB.Connection
Dim rstProjekte As New ADODB.Recordset
Dim rstProjektphasen As New ADODB.Recordset
Dim i As Integer
Dim j As Integer
Dim intProjektID As Integer
Set cnn = CurrentProject.Connection
rstProjekte.Open "tblProjekte", cnn, adOpenDynamic, adLockOptimistic
rstProjektphasen.Open "tblProjektphasen", cnn, adOpenDynamic, _
adLockOptimistic
With objXMLDocument
.async = False
.preserveWhiteSpace = False
.validateOnParse = True
.resolveExternals = False
End With
If objXMLDocument.Load(strDateiname) = True Then
Set objXMLDocumentElement = objXMLDocument.documentElement
For i = 0 To objXMLDocumentElement.childNodes.length - 1
Set objXMLProjekt = objXMLDocumentElement.childNodes.Item(i)
If objXMLProjekt.nodeName = "projekt" Then
With rstProjekte
.AddNew
intProjektID = objXMLProjekt.getAttribute("projektID")
!ProjektID = intProjektID
!Projektbezeichnung = _
objXMLProjekt.selectSingleNode("projektbezeichnung").Text
!Projektleiter = _
objXMLProjekt.selectSingleNode("projektleiter").Text
!Projektstart = _
objXMLProjekt.selectSingleNode("projektstart").Text
!ProjektEnde = _
objXMLProjekt.selectSingleNode("projektende").Text
.Update
End With
Set objXMLProjektphasen = objXMLProjekt. _
selectSingleNode("projektphasen")
If Not objXMLProjektphasen Is Nothing Then
For j = 0 To objXMLProjektphasen.childNodes.length - 1
Set objXMLProjektphase = _
objXMLProjektphasen.childNodes.Item(j)
If objXMLProjektphase.nodeName = "projektphase" Then
With rstProjektphasen
.AddNew
!ProjektphaseID = _
objXMLProjektphase.getAttribute("projektphaseID")
!ProjektID = intProjektID
!Projektphasenbezeichnung = _
objXMLProjektphase. _
selectSingleNode("projektphasenbezeichnung").Text
!Projektphasenstart = _
objXMLProjektphase. _
selectSingleNode("projektphasenstart").Text
!ProjektphasenEnde = _
objXMLProjektphase. _
selectSingleNode("projektphasenende").Text
.Update
End With
End If
Next j
End If
End If
Next i
Else
MsgBox objXMLDocument.parseError.reason
End If
rstProjektphasen.Close
rstProjekte.Close
Set rstProjektphasen = Nothing
Set rstProjekte = Nothing
Set cnn = Nothing
End Function
|