XML-Dokumente mit VBA lesen

Wir haben nun in einigen Artikeln beschrieben, welche Möglichkeiten die Bordmittel von Access für das Lesen und Schreiben von XML-Dokumenten bieten. Richtig flexibel ist das ganze natürlich nicht beziehungsweise nur, wenn Sie mit XSL nachhelfen. Wenn es beim Einlesen von XML-Dokumenten richtig individuell werden soll, können Sie aber immer noch mit VBA arbeiten. Dazu benötigen Sie nur einen Verweis auf die Objektbibliothek mit den Befehlen zum Bearbeiten von XML-Dokumenten – und das Know-how aus diesem Artikel.

Beispieldatenbank

Die Beispiele dieses Artikels finden Sie in der Datenbank 1904_XMLLesenVBA.accdb.

Voraussetzungen

Um per VBA auf XML-Dokumente zuzugreifen, brauchen Sie imgrunde noch nicht einmal eine spezielle Bibliothek. XML-Dokumente sind ja auch nichts anderes als einfache Textdateien, nur das ihre Inhalte durch die XML-Auszeichnungen auf bestimmte Art strukturiert sind.

Im Notfall können Sie sich also auch mit der Open-Anweisung und den Zeichenkettenfunktionen von VBA behelfen. Aber wir wollen es natürlich schon etwas komfortabler haben und nutzen daher die Bibliothek Microsoft XML, 6.0.

Diese fügen Sie im VBA-Editor über den Menüeintrag Extras|Verweise und den dann erscheinenden Dialog Verweise wie in Bild 1 hinzu.

Verweis auf die XML-Bibliothek

Bild 1: Verweis auf die XML-Bibliothek

Wenn Sie nun mit der Schaltfläche F2 den Objektkatalog öffnen, können Sie nach der Auswahl des Eintrags MSXML2 oben im Kombinationsfeld alle Elemente dieser Bibliothek einsehen (siehe Bild 2).

Objektkatalog von VBA

Bild 2: Objektkatalog von VBA

Beispieldokument

Wir wollen die Daten aus einem XML-Dokument mit einer Bestellung als Beispiel verwenden, das Sie auch auf der folgenden Microsoftseite finden können – für den Fall, dass Sie mit weiteren Beispieldokumenten experimentieren wollen:

https://docs.microsoft.com/de-de/dotnet/visual-basic/programming-guide/concepts/linq/sample-xml-documents-linq-to-xml

Das Dokument sieht wie in Listing 1 aus. Es enthält genau eine Bestellung, die im Element PurchaseOrder enthalten ist. Das Hauptelement enthält in zwei Attributen die Bestellnummer und das Bestelldatum.

<xml version="1.0">  
<PurchaseOrder PurchaseOrderNumber="99503" OrderDate="1999-10-20">  
   <Address Type="Shipping">  
     <Name>Ellen Adams</Name>  
     <Street>123 Maple Street</Street>  
     <City>Mill Valley</City>  
     <State>CA</State>  
     <Zip>10999</Zip>  
     <Country>USA</Country>  
   </Address>  
   <Address Type="Billing">  
     <Name>Tai Yee</Name>  
     <Street>8 Oak Avenue</Street>  
     <City>Old Town</City>  
     <State>PA</State>  
     <Zip>95819</Zip>  
     <Country>USA</Country>  
   </Address>  
   <DeliveryNotes>Please leave packages in shed by driveway.</DeliveryNotes>  
   <Items>  
     <Item PartNumber="872-AA">  
       <ProductName>Lawnmower</ProductName>  
       <Quantity>1</Quantity>  
       <USPrice>148.95</USPrice>  
       <Comment>Confirm this is electric</Comment>  
     </Item>  
     <Item PartNumber="926-AA">  
       <ProductName>Baby Monitor</ProductName>  
       <Quantity>2</Quantity>  
       <USPrice>39.98</USPrice>  
       <ShipDate>1999-05-21</ShipDate>  
     </Item>  
   </Items>  
 

Listing 1: Inhalt eines XML-Dokuments mit einer Bestellung

Darunter finden Sie die Liefer- und die Rechnungsadresse jeweils in Address-Elementen mit entsprechenden Unterelementen.

Ob es sich um eine Liefer- oder Bestelladresse handelt, entnehmen Sie dem Attribut Type des Address-Elements.

Darunter folgen DeliveryNotes als eigenes Element sowie eine Auflistung namens Items mit einigen Item-Elementen, welche die eigentlichen Bestellpositionen ausmachen. In den folgenden Abschnitten zeigen wir, wie Sie die dort enthaltenen Informationen per VBA und mithilfe der XML-Bibliothek auslesen können.

Die DOMDocument-Klasse

Um auf den Inhalt eines Dokuments zuzugreifen, wollen wir dieses zunächst referenzieren. Dazu gibt es genau eine geeignete Klasse, nämlich DOMDocument60.

Diese deklarieren wir mit der Variablen objXML, danach instanzieren wir ein neues Objekt auf Basis dieser Klasse mit dem New-Schlüsselwort.

Die DOMDocument-Klasse bietet unter anderem die beiden Methoden Load und LoadXML an:

  • Load: Erwartet die Angabe des Pfades zum einzulesenden XML-Dokument als Parameter und liefert den Wert True zurück, wenn das Einlesen erfolgreich war.
  • LoadXML: Erwartet ein XML-Dokument in Form einer Zeichenkette als Parameter. Auch hier liefert der Rückgabewert die Information, ob das Einlesen erfolgreich war.

Mit unserer Beispieldatei PurchaseOrder.xml sieht das Einlesen wie in der folgenden Prozedur aus. Hier prüfen wir direkt, ob das Einlesen erfolgreich war. Falls ja, geben wir den Inhalt des Dokuments im Direktbereich des VBA-Editors aus. Dazu verwenden wir die Debug.Print-Anweisung mit der XML-Eigenschaft von objXML.

Public Sub DokumentReferenzieren()
    Dim objXML As DOMDocument60
    Set objXML = New DOMDocument60
    If objXML.Load(CurrentProject.Path _
            & "\PurchaseOrder.xml") = True Then
        Debug.Print objXML.XML
    Else
        MsgBox "Fehler beim Einlesen"
    End If
End Sub

Fehler beim Einlesen

In unserem Beispiel gibt es keine Probleme beim Einlesen. Was aber könnte dabei nicht funktionieren Es kann zum Beispiel vorkommen, dass das XML-Dokument nicht wohlgeformt ist.

Das bedeutet, dass zum Beispiel das öffnende Element vorhanden ist, aber das schließende Element fehlt. In diesem Fall liest Load das Dokument nicht ein, sondern liefert den Wert False zurück.

Um herauszufinden, welcher Fehler vorliegt, können Sie die Eigenschaften des Elements ParseError nutzen. Dazu fügen wir dem Else-Teil der If…Then-Bedingung aus der obigen Prozedur noch ein paar weitere Zeilen hinzu:

Debug.Print "Fehler bei Einlesen:"
Debug.Print "ErrorCode: " & objXML.parseError.errorCode
Debug.Print "Filepos:   " & objXML.parseError.filepos
Debug.Print "Line:      " & objXML.parseError.Line
Debug.Print "LinePos:   " & objXML.parseError.linepos
Debug.Print "Reason:    " & objXML.parseError.reason
Debug.Print "srcText:   " & objXML.parseError.srcText
Debug.Print "Url:       " & objXML.parseError.url

Wenn wir einmal das schließende PurchaseOrder-Element aus dem Dokument entfernen und die Prozedur erneut aufrufen, erhalten wir die Informationen aus Bild 3.

Fehlerinformationen des parseError-Objekts

Bild 3: Fehlerinformationen des parseError-Objekts

Die Meldung, welche die Eigenschaft Reason für uns bereithält, ist aussagekräftig genug, um den Fehler zu beheben.

Das Root-Element einlesen

Unser objXML-Objekt enthält nach dem Aufruf der Load-Methode, wie wir der XML-Eigenschaft entnehmen konnten, den kompletten Inhalt des XML-Dokuments. Wie können wir auf die einzelnen Elemente des Dokuments zugreifen und deren Inhalt ausgeben Als Erstes wollen wir dabei das sogenannte Root-Element referenzieren, das in unserem Fall so aussieht:


    ...

Um auf ein einzelnes XML-Element innerhalb eines Dokuments zu verweisen, benötigen wir eine Objektvariable mit dem passenden Typ, in diesem Fall IXMLDOMElement:

Public Sub RootElementReferenzieren()
    Dim objXML As DOMDocument60
    Dim objRoot As IXMLDOMElement
    Set objXML = New DOMDocument60

Nach dem Laden des documentElement-Elements referenzieren wir das Root-Element dann über die document-Element-Eigenschaft:

    objXML.Load CurrentProject.Path                                   & "\PurchaseOrder.xml"
    Set objRoot = objXML.documentElement

Danach können wir beispielsweise mit baseName den Namen des Elements ermitteln, hier PurchaseOrder, oder mit der XML-Eigenschaft den Inhalt des XML-Elements ausgeben:

    Debug.Print objRoot.baseName
    Debug.Print objRoot.XML
End Sub

Möchten Sie weiterlesen? Dann lösen Sie Ihr Ticket!
Hier geht es zur Bestellung des Jahresabonnements des Magazins Access [basics]:
Zur Bestellung ...
Danach greifen Sie sofort auf alle rund 400 Artikel unseres Angebots zu - auch auf diesen hier!
Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:

Schreibe einen Kommentar