Datentransformation mit XSLT

Hat man als Anwendungsprogrammierer die Aufgabe, eine Datentransformation (z.b von csv nach xml) durchzuführen, entwickelt man in der Regel ein normales Programm, welches die Eingabedatei einliest, diese nach bestimmten Vorgaben umformt und wieder ausgibt. Die gleiche Vorgehensweise wird auch angewandt, wenn es lediglich darum geht, die Struktur der Daten zu anzupassen ohne das Dateiformat zu ändern.

Neben dieser Vorgehensweise gibt es auch eine weitere Alternative, nämlich die Konvertierung mit XSLT. Ursprünglich wurde diese Stylesheetsprache eigentlich dafür entwickelt, XML-Dokumente zu transformieren. In der Tat ist sie jedoch weitaus mächtiger und erlaubt sogar formatübergreifende Transformationen textbasierter strukturierter Dateien.

Vorteile einer Datentransformation mit XSLT

Ein Vorteil dieser Sprache ist ihre Plattformunabhängigkeit, sodass ein XSLT-Skript sowohl unter Windows als auch unter Apple oder Unix/Linux ausgeführt werden kann – dazu benötigte XSLT-Prozessoren gibt es nämlich für alle Plattformen.

Ein weiterer Vorteil ist, dass man für das Schreiben von XSLT-Skripten keine spezielle Entwicklungsumgebung benötigt, theoretisch kommt man mit dem rudimentären Windows Editor aus. Für den praktischen Einsatz greife ich persönlich viel lieber zum kostenlosen NodePad++, der, nebenbei gesagt, sich mit zahlreichen PlugIns zu einem Editor mit allen benötigten Funktionalitäten erweitern lässt. Für unser Beispiel bietet sich das PlugIn „XML Tools“ an, welches auch einen XSLT-Prozessor umfasst, was das Ausführen von XSLT-Skripten direkt in diesem Editor erlaubt.

Einsatz als XML to JSON-Konverter

Da mein letztes großes Projekt im medizinischen Bereich angesiedelt war, bleibe ich dabei und nehme als Beispiel ein ICD-Verzeichnis im XML-Format vom Bundesinstitut für Arzneimittel und Medizinprodukte, siehe Listing 1.

Listing 1. So sieht ein Fragment aus der Input-XML-Datei aus

	<Class code="A00" kind="category">
		<Meta name="Para295" value="V"/>
		<Meta name="Para301" value="V"/>
		<Meta name="MortL1Code" value="1-002"/>
		<Meta name="MortL2Code" value="2-001"/>
		<Meta name="MortL3Code" value="3-003"/>
		<Meta name="MortL4Code" value="4-002"/>
		<Meta name="MortBCode" value="001"/>
		<Meta name="SexCode" value="9"/>
		<Meta name="SexReject" value="9"/>
		<Meta name="AgeLow" value="9999"/>
		<Meta name="AgeHigh" value="9999"/>
		<Meta name="AgeReject" value="9"/>
		<Meta name="Exotic" value="J"/>
		<Meta name="Content" value="J"/>
		<Meta name="Infectious" value="J"/>
		<Meta name="EBMLabor" value="J"/>
		<SuperClass code="A00-A09"/>
		<SubClass code="A00.0"/>
		<SubClass code="A00.1"/>
		<SubClass code="A00.9"/>
		<Rubric kind="preferred">
			<Label xml:lang="de" xml:space="default">Cholera</Label>
		</Rubric>
	</Class>
	<Class code="A00.0" kind="category">
		<Meta name="Para295" value="P"/>
		<Meta name="Para301" value="P"/>
		<Meta name="MortL1Code" value="1-002"/>
		<Meta name="MortL2Code" value="2-001"/>
		<Meta name="MortL3Code" value="3-003"/>
		<Meta name="MortL4Code" value="4-002"/>
		<Meta name="MortBCode" value="001"/>
		<Meta name="SexCode" value="9"/>
		<Meta name="SexReject" value="9"/>
		<Meta name="AgeLow" value="9999"/>
		<Meta name="AgeHigh" value="9999"/>
		<Meta name="AgeReject" value="9"/>
		<Meta name="Exotic" value="J"/>
		<Meta name="Content" value="J"/>
		<Meta name="Infectious" value="J"/>
		<Meta name="EBMLabor" value="J"/>
		<SuperClass code="A00"/>
		<Rubric kind="preferred">
			<Label xml:lang="de" xml:space="default">Cholera durch Vibrio cholerae O:1</Label>
		</Rubric>
		<Rubric kind="inclusion">
			<Label xml:lang="de" xml:space="default">Klassische Cholera</Label>
		</Rubric>
	</Class>

Nehmen wir an, wir wollen aus diesem riesigen XML-Dokument (rund 340.000 Zeilen, 13 MB groß, was für eine Datei im Textformat schon wirklich beachtlich ist) lediglich ICD-Codes sowie die Bezeichnung auslesen und diese in ein JSON-Format überführen (Listing 2), um die Inhalte in eine HTML-Seite bequem einbinden zu können.

Listing 2. So sieht ein Fragment aus der Output-JSON-Datei aus

	{
	"icds": [	
			{
				"code":"A00",				
				"bezeichnung":"Cholera"	
			}
			,
			{
				"code":"A00.0",				
				"bezeichnung":"Cholera durch Vibrio cholerae O:1"	
			}
            ....

Um dies umsetzen zu können, schauen wir uns die Struktur der XML-Datei und überlegen, in welchen Knoten die benötigten Daten abgelegt sind.

Jeder ICD-Code samt Bezeichnung ist im Knoten Class abgelegt. Um all die Codes auslesen zu können, benötigen wir hier eine Schleife, so wie wir sie aus herkömmlichen Programmiersprachen kennen. Mit der for-each-Schleife durchlaufen wir so jeden Knoten „class“. Innerhalb der Schleife platzieren wir 2 value-of-Anweisungen, mit derer Hilfe wir zum einen den Inhalt des Attributes „code“ auslesen und zum anderen den Inhalt des Knoten „Label“.

Durch die Angabe der öffnenden und der schließenden geschweiften Klammern vervollständigen wir den JSON-Knoten. An letzter Stelle bei jedem Durchlauf der Schleife erfolgt noch eine Überprüfung, ob der ausgelesene Knoten der letzte Knoten im XML-Dokument ist. Ist es der Fall, wird kein Komma (Trennzeichen zwischen einzelnen JSON-Knoten) gesetzt. Der komplette Quellcode des XSLT-Skriptes ist im Listing 3 zu sehen.

Listing 3. Der XSLT-Skript für die XML-JSON-Transformation

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
	<xsl:template match="/">
	{
	"icds": [
		<xsl:for-each select="/ClaML/Class[@kind='category']">
				<xsl:choose>
					<xsl:when test="SubClass"></xsl:when>
					<xsl:otherwise>
						{
							"code":"<xsl:value-of select="@code"/>",
							"bezeichnung":"<xsl:value-of select="Rubric[@kind='preferred']/Label"/>"
						}
						<xsl:if test="position() != last()">,</xsl:if>
					</xsl:otherwise>
				</xsl:choose>
		</xsl:for-each>	
		]
	}
	</xsl:template>
</xsl:stylesheet>

Die hier gezeigte Datentransformation lässt sich mit wenigen Änderungen so umbauen, dass anstellen von JSON- ein CSV-File erzeugt werden kann. So ist es möglich, ein und die selbe Quelldatei für unterschiedliche Verwendungszwecke vorzubereiten.

Einsatz als XML to XML-Konverter

Ich persönlich setze XSLT auch für einmalige größere Datenmigrationen ein. In einem Kundenprojekt von mir entstand umfangreiches Schlüsselverzeichnis als XML-Datei. Im Laufe der Weiterentwicklung hat sich ergeben, dass das Schlüsselverzeichnis noch weitere Daten aufnehmen muss und dadurch die vor mir ursprünglich gewählte Namensgebung der einzelnen XML-Attribute nicht mehr ganz genau passt. Um die Struktur und die Daten dieser XML-Datei in ein neues Schlüsselverzeichnis zu migrieren, habe ich ein XSLT-Skript entwickelt. Für eine kleine XML-Datei, die vielleicht aus 20 Zeilen besteht, hätte dies sicherlich nicht geloht – da wäre man händisch wahrscheinlich viel schneller gewesen. Dies war jedoch eine fast 1.000 Zeilen XML-Datei gewesen – diese „zu Fuß“ anzupassen, hätte sicherlich keinen Spaß gemacht.

Fazit

Als letztes sei noch gesagt, dass die Datentransformation für eine maschinelle Verarbeitung nicht das einzige Einsatzgebiet von XSLT ist. So wäre beispielsweise auch eine Umwandlung in HTML möglich, um die Daten auch fürs menschliche Auge gut lesbar darstellen zu können.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.