Javascript XML-Zugriff und Auswertung mit fetch

XML-Datei mit fetch lesen und auswerten

XML wird immer noch fleißig für den Austausch zwischen Anwendungen benutzt. Einfach elegant liest Javascript eine XML-Datei mit fetch aus und wandelt XML mit dem DOMParser und parseFromString in DOM um. Als DOM lässt sich XML mit denselben Methoden behandeln wie ein HTML-Dokument.

23-02-02 SITEMAP CSS HTML JS Basis JS Web Tutorial SVG

XML-Datei mit fetch lesen

JS fetch() ist die einfachste Methode, um eine XML-Datei vom Server zu lesen, denn dafür muss nur der Pfad zur XML-Datei bekannt sein. Die Anfrage wird automatisch im Hintergrund ausgeführt und alle Aktionen, die bei beim Eintreffen der Antwort anfallen, werden mit einem schlichten then nacheinander aufgereiht: Hol das XML und dann mach was damit.

<xml>
	<item>
		<date>Montag</date>
		<content>Peters und Schuiten: Mary</content>
		<image>img/xml-mary.jpg</image>
	</item>
	<item>
		<date>Dienstag</date>
		<content>Hergé: Die Zigarren des Pharao</content>
		<image>img/xml-zigarren.jpg</image>
	</item>
	<item>
		<date>Mittwoch</date>
		<content>Hergé: Der blaue Lotus</content>
		<image>img/xml-lotus.jpg</image>
	</item>
	…
</xml>

Javascript Response

Die Response / Antwort auf fetch ist ein promise, ein Versprechen. Wenn das Promise erfüllt ist, folgt Javascript dem then und empfängt die Antwort mit function (response).

// fetch-Aufruf mit Pfad zur XML-Datei
fetch ('comic-today.xml')
	.then (function (response) {
		// Antwort kommt als Text-String
		return response.text();
	})
	.then (function (data) {
		console.log (data);			  // schnell mal in der Konsole checken
		
		// String in ein XML-DOM-Objekt umwandeln
		let parser = new DOMParser (),
			xmlDoc = parser.parseFromString (data, 'text/xml');
		
		und noch ein paar Test-Ausgaben in die Konsole
		console.log (xmlDoc.getElementsByTagName ('item'));
		console.log ("item "  + xmlDoc.getElementsByTagName ('item')[1].children[0].textContent);

		comicToday (xmlDoc);			// Funktion zur Bearbeitung mit dem geparsten xmlDoc aufrufen	
}).catch (function (error) {
	 console.log ("Fehler: bei Auslesen der XML-Datei " + error);
});

Wenn nicht XML, sondern HTML mit Javascript fetch eingelesen werden soll? Das ist nur eine Frage des Mime-Typs.

// String in ein HTML-DOM-Objekt umwandeln
let parser = new DOMParser (),
	htmlDoc = parser.parseFromString (data, "text/html");

Antwort extrahieren

response ist ein Objekt, aus dem Javascript die Antwort extrahieren kann. Im Fall von XML soll Javascript die Antwort als Text interpretieren.

Der Lesevorgang braucht Zeit, auch wenn so eine kleine XML-Datei nur den Bruchteil eines Augenschlags dauert. Anders als beim klassischen XMLHttpRequest brauchen wir uns um die Anläufe im Hintergrund und die Dauer des Ladens nicht zu kümmern. Die Aktionen im then werden erst ausgeführt, wenn der Lesevorgang beendet ist.

.then (function (response) {
	return response.text();
})

Noch ein Promise: then (function (data)

.then (function (data) ist ein weiteres Versprechen. Sobald auch dieses Versprechen erfüllt ist, schreibt console.log die Daten für einen schnellen Check in die Browser-Konsole.

[Log]<xml>(xml-mit-fetch.html, line 307)<item><date>Montag</date><content>Peters und Schuiten: Mary</content><image>img/xml-mary.jpg</image></item><item><date>Dienstag</date><content>Hergé: Die Zigarren des Pharao</content><image>img/xml-zigarren.jpg</image></item><item><date>Mittwoch</date><content>Hergé: Der blaue Lotus</content><image>img/xml-lotus.jpg</image></item><item><date>Donnerstag</date><content>Die Kreise der Macht</content><image>img/xml-kreise.jpg</image></item><item><date>Freitag</date><content>Prado: Kreisestriche</content><image>img/xml-kreidestriche.jpg</image></item><item><date>Samstag</date><content>Peters und Schuiten: Brusel</content><image>img/xml-brusel.jpg</image></item><item><date>Sonntag</date><content>Hergé: Der Arumbaya-Fetisch</content><image>img/xml-fetisch.jpg</image></item></xml>

console.log ist nur für die Tests in der Zeit der Entwicklung gedacht.

Die Antwort auf den Fetch-Request in ein String. Für das Umwandeln des XML-Strings wird ein Parser gebraucht: DOMParser.

Arbeiten mit Javascript Collections / Sammlungen

getElementsByTagName ('item') gibt eine Sammlung von Elementen zurück. Sammlungen oder Collections ähneln Arrays und können mit Array-Techniken bearbeitet werden.

HTMLCollection [<item>, <item>, <item>,…]

Der Zugriff auf die Elemente date und content eines Eintrags (item) funktioniert also wie bei einem Array über die eckigen Klammern.

console.log (xmlDoc.getElementsByTagName ('item')[1].children[0].textContent);

Und die Konsole zeigt den Inhalt von <date> als erstes Kind (children[0]) des zweiten Eintrags (('item')[1]).

2020-03-24 

Auswerten der XML-Daten

Welcher Comic ist für heute vorgesehen? Dafür muss das aktuelle Datum mit dem Datum der item-Elemente der XML-Datei verglichen werden.

<xml>
	<item>
		<date>Montag</date>
		<content>Peters und Schuiten: Mary</content>
		<image>img/xml-mary.jpg</image>
	</item>
	<item>
		<date>Dienstag</date>
		<content>Hergé: Die Zigarren des Pharao</content>
		<image>img/xml-zigarren.jpg</image>
	</item>
	<item>
		<date>Mittwoch</date>
		<content>Hergé: Der blaue Lotus</content>
		<image>img/xml-lotus.jpg</image>
	</item>
	<item>
		<date>Donnerstag</date>
		<content>Die Kreise der Macht</content>
		<image>img/xml-kreise.jpg</image>
	</item>
	<item>
		<date>Freitag</date>
		<content>Prado: Kreisestriche</content>
		<image>img/xml-kreidestriche.jpg</image>
	</item>
	<item>
		<date>Samstag</date>
		<content>Peters und Schuiten: Brusel</content>
		<image>img/xml-brusel.jpg</image>
	</item>
	<item>
		<date>Sonntag</date>
		<content>Hergé: Der Arumbaya-Fetisch</content>
		<image>img/xml-fetisch.jpg</image>
	</item>
</xml>

xmlDoc.getElementsByTagName ('item') ist eine Sammlung oder HTML-Collection und kann mit einer for-Anweisung durchlaufen werden. In den Zeiten von querySelectorAll ist element.getElementsByTagName ins Hintertreffen geraten, weil es halt nur eben das kann: Elemente anhand ihres Tag-Namens filtern. Beides ist möglich, getElementsByTagName ist älter, einfacher und vielleicht etwas schneller.

<script>
function comicToday (xml) {
	const numItems = xml.getElementsByTagName("item").length;
	const days = ["Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag","Sonntag"];

	const tag = new Date().getDay() - 1;
	for (let i=0; i<numItems; i++) {		
		const wochentag = xml.querySelectorAll ('item')[i].children[0].textContent;
		if (tag == days.indexOf(wochentag)) {
			const div = document.createElement("DIV");
			div.innerHTML = "Am " +  xml.querySelectorAll ('item')[i].children[0].textContent + " lesen wir <br>" + xml.querySelectorAll ('item')[i].children[1].textContent;
			document.querySelector(".result").appendChild (div);
			const image = document.createElement ("img");
			image.src = xml.querySelectorAll ('item')[i].children[2].textContent;
			
			document.querySelector(".result").appendChild(image) 
		}
	}
}

fetch ('xml-mit-fetch.xml')
	.then (function (response) {
		return response.text();
	})
	.then (function (data) {
		let parser = new DOMParser (),
			xmlDoc = parser.parseFromString (data, 'text/xml');
		comicToday (xmlDoc);
}).catch (function (error) {
	console.log ("Fehler: bei Auslesen der XML-Datei " + error);
});
</script>