Webservices können nicht nur Texte und Zahlen liefern oder entgegennehmen, sondern auch etwa mit Bildern oder PDF-Dateien arbeiten. So könnten Sie einen Webservice nutzen, der Bilder bearbeitet oder umwandelt, oder mit einem, der ein PDF für eine bestimmte Dienstleistung liefert und dazu in einen XML-Response verpackt – zum Beispiel eine Versandmarke et cetera. Für solche Fälle kann es hilfreich sein zu wissen, wie Sie die endlosen Zahlenkombinationen aus dem XML-Dokument in eine Datei umwandeln – und umgekehrt.
Dateien aus XML-Dokumenten exportieren
Wenn Sie gelegentlich Dateien im XML-Format verarbeiten, kommt dort sicher auch mal eine Base64-kodierte Datei vor. Eine einfache XML-Datei mit dem Root-Element file, das zwei weitere Elemente namens filename (zum Speichern des Dateinamens) und data (mit dem kodierten Inhalt einer PDF-Datei) enthält, sieht beispielsweise wie folgt aus – nur je nach Dateigröße viel länger:
<xml version="1.0"> <file> <filename>Beispieldatei.pdf</filename> <data>JVBERi0xLjQNJeLjz9MNCjk3NCAwIG9iag08PC9MaW5lYXJpeIIFsgMTA5OCA3MjddPj4NZW5kb2JqDSAgICAg...</data> </file>
Einen besseren Eindruck vom Umfang einer solchen Datei erhalten Sie durch einen Blick auf Bild 1. Die hier abgeschnittene Darstellung besteht tatsächlich aus über 17.000 Zeilen!
Bild 1: Beispiel für eine in einem XML-Dokument gespeicherte Datei
Und dieses Durcheinander wollen wir nun in eine Datei umwandeln Aber natürlich! Mehr dazu gleich.
Voraussetzungen
Für die Beispiele aus diesem Beitrag (und auch, wenn Sie diese in Ihrer eigenen Datenbank nutzen möchten) benötigen Sie zwei zusätzliche Verweise, nämlich auf die Bibliothek Microsoft XML, v6.0 und Microsoft ActiveX Data Objects 6.1 Library (s. Bild 2).
Bild 2: Verweise der Beispieldatenbank
Datei auslesen
Die Steuerung übernimmt die Prozedur aus Listing 1, in der Sie auch festlegen, welche XML-Datei als Quelle dient, aus welchem Element der Name der zu erzeugenden Datei und aus welchem Element der kodierte Dateiinhalt kommt. Die Prozedur erstellt ein neues DOMDocument-Objekt und lädt den Inhalt der Datei ArtikelInXML.xml, deren Inhalt Sie oben bereits kennen gelernt haben, in dieses Objekt. Die nächste Anweisung trägt das Verzeichnis der aktuellen Datenbank gefolgt von einem Backslash (\) und dem aus dem Element filename ermittelten Dateinamen, hier Beispieldatei.pdf, in die Variable strZieldatei ein.
Public Sub XMLElementInDatei() Dim objDocument As MSXML2.DOMDocument60 Dim strXMLDatei As String Dim strZieldatei As String Dim objData As MSXML2.IXMLDOMElement Set objDocument = New MSXML2.DOMDocument60 strXMLDatei = CurrentProject.Path & "\ArtikelInXML.xml" objDocument.Load strXMLDatei strZieldatei = CurrentProject.Path & "\" & objDocument.selectSingleNode("//filename").nodeTypedValue Set objData = objDocument.selectSingleNode("//data") WriteFileFromBytes strZieldatei, DecodeBase64(objData.nodeTypedValue) End Sub
Listing 1: Auslesen einer Datei aus einem XML-Dokument in das Filesystem
Mit der IXMLDOMElement-Variablen objBild referenzieren wir den Inhalt des Elements data unserer Zieldatei. Schließlich rufen wir gleich zwei Hilfsfunktionen in einer Zeile auf: Die Funktion WriteFileFromBytes erwartet den Namen der zu erstellenden Datei sowie ein Byte-Array mit dem zu schreibenden Dateiinhalt als Parameter und soll die Datei in das Datei-sytem schreiben. Das Byte-Array steuert mit dem zweiten Parameter die Funktion DecodeBase64 bei, welche mit dem Inhalt des Elements Data aus der Variablen objData versorgt wird.
Data-Element dekodieren
Schauen wir uns als Erstes die Funktion DecodeBase64 an. Diese erwartet einen String als Parameter, in diesem Fall den Inhalt des data-Elements unserer XML-Datei. Und jetzt kommt der Clou: Wir nutzen keinen selbst programmierten Algorithmus, um die Dekodierung vorzunehmen, sondern wir erstellen ein XML-Dokument, fügen diesem ein neues Element namens tmp hinzu, stellen den Datentyp auf bin.base64 ein und füllen es über seine Text-Eigenschaft mit dem Wert aus dem Parameter strBase64. Die XML-Bibliothek erledigt die Umwandlung dann automatisch für uns, sodass wir über die Eigenschaft nodeTypedValue des Elements auf das resultierende Byte-Array zugreifen können. Diesen Wert weisen wir dem Rückgabewert DecodeBase64 der Funktion zu, der als Byte() deklariert ist (s. Listing 2).
Private Function DecodeBase64(strBase64 As String) As Byte() Dim objDocument As MSXML2.DOMDocument60 Dim objElement As MSXML2.IXMLDOMElement Set objDocument = New MSXML2.DOMDocument60 Set objElement = objDocument.createElement("tmp") objElement.DataType = "bin.base64" objElement.Text = strBase64 DecodeBase64 = objElement.nodeTypedValue End Function
Listing 2: Dekodieren von Base64 in ein Byte-Array
Byte-Array in Datei schreiben
Damit erhalten wir den zweiten Parameter für die Funktion WriteFileFromBytes (s. Listing 3). Der erste Parameter erwartet den Pfad für die zu erstellende Datei, der zweite das soeben mit der Funktion DecodeBase64 erstellte Byte-Array. Die Prozedur nutzt wieder eine externe Bibliothek, und zwar Microsoft ActiveX Data Objects 6.1 Library. Davon deklariert sie zunächst ein ADODB.Stream-Objekt und erstellt eine neue Instanz dieses Objekts. Den Typ des Objekts stellt die Funktion auf adTypeBinary ein. Sie öffnet das Objekt mit der Open-Methode und schreibt dann das mit dem zweiten Parameter byt() übergebene Byte-Array hinein. Das Stream-Objekt bietet direkt eine SaveToFile-Methode an, mit der wir den Inhalt in die mit dem ersten Parameter übergebene Datei schreiben können. Mit dem Wert des zweiten Parameters legen wir fest, dass die Datei neu erstellt werden oder eine bestehende Datei überschreiben soll.
Private Sub WriteFileFromBytes(strFile As String, byt() As Byte) Dim objStream As ADODB.Stream Set objStream = New ADODB.Stream objStream.Type = adTypeBinary objStream.Open objStream.Write byt() objStream.SaveToFile strFile, adSaveCreateOverWrite End Sub
Listing 3: Schreiben eines Byte-Arrays in eine Datei
Es hat funktioniert – die Daten aus dem XML-Dokument ergeben tatsächlich eine lesbare Datei, hier im PDF-Format (s. Bild 3).
Bild 3: Es klappt – die exportierten XML-Daten ergeben tatsächlich eine lesbare Datei.
Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...
den kompletten Artikel im PDF-Format mit Beispieldatenbank
diesen und alle anderen Artikel mit dem Jahresabo