Datentransformation mit XSLT

Hat man als Entwickler die Aufgabe, eine Datei mit strukturierten Daten aus einem Format in ein anderes (z.b von csv nach xml) umzuwandeln, 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 diese Sprache jedoch weitaus mächtiger und erlaubt sogar formatübergreifende Transformationen textbasierter strukturierter Dateien.

XSLT-Vorteile

Ein Vorteil dieser Sprache ist die 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 die Tatsache, dass man für die Entwicklung XSLT-Skripte 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 habe ich das PlugIn „XML Tools“ installiert, welches auch einen XSLT-Prozessor umfasst, was das Ausführen von XSLT-Skripten direkt in diesem Editor erlaubt.

Beispiel einer Konvertierung mit XSLT

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, Biovar cholerae</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 den ICDCode 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 ICDCode 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 Transformation 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.

Fazit

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

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.